สำหรับเนื้อหาในตอนนี้ จะเป็นการแนะนำ plugin ที่ชื่อ Local Notification หรือ
การแจ้งเตือนจากการทำงานของ app โดยตรง จะแตกต่างจากระบบ Push Notification
ตรงที่ข้อควม push นั้นเป็นการส่งจาก server โดยผ่าน google service มาแสดงที่เครื่องของเรา
ส่วนการทำงานของ Local Notification เป็นการแสดงข้อความเตือนจากคำสั่งในตัว app ที่เรากำหนดขึ้น
โดยสามารถให้แจ้งเตือนหนึ่งรายการในครั้งเดียว แจ้งเตือนหลายรายการในครั้งเดียว
แจ้งเตือนที่เวลาที่กำหนด แจ้งเตือนทุก วินาที นาที ชั่วโมง วัน สัปดาห์ เดือน หรือปี
รูปแบบการแสดงของ Local Notification จะแสดงคล้ายๆ กับข้อความ push แต่อาจจะกำหนด
บางค่าไม่ได้หรือไม่สามารถใช้งานบางค่าได้ จากที่ทดสอบ การกำหนด icon และการกำหนด sound
ใน android ไม่สามารถใช้ได้ จะเป็นการใช้ค่าเริ่มต้นของมือถือนั้นๆ แทน ส่วนการทำงานก็เป็นลักษณะ
ทำงานแม้ว่า app จะปิด หรือไม่ได้เปิดใช้งาน ทั้งนี้ขึ้นกับการใช้งานการกำหนดการแจ้งเตือน ยกตัวอย่าง
เช่น การกำหนดให้มีการแจ้งทุกๆ 5 นาที กรณีแบบนี้เมื่อเราปิด app แล้ว ระบการแจ้งเตือนก็จะยังทำงาน
อยู่เบื้องหลังหรือทำงาน background และแจ้งเตือนขึ้นมาเมื่อครบทุกๆ 5 นาที แบบนี้เป็นต้น
ระบบการแจ้งเตือนแบบ Local Notification สามารถนำไปใช้ในการทำ app แจ้งกำหนดการต่างๆ เช่น
app แจ้งเตือนก่อนถึงกำหนดนัดหมาย หรือ app แจ้งเตือนเมื่อเลยกำหนดการทำงานใดๆ เป็นต้น
1. ติดตั้ง Local Notification plugin
ด้วยคำสั่ง
1 | cordova plugin add de.appplant.cordova.plugin.local-notification |
สามารถศึกษาหรือดูข้อมูลการใช้งานเพิ่มเติมได้ที่
2. แทรกการทำงานการตรวจจับ event ของ local notification เมื่อเริ่มต้น app
ให้เปิดไฟล์ app.js ในโฟลเดอร์ js และแทรกโค้ดเกี่ยวกับการใช้งาน local notification
ในส่วนของการตรวจสอบ event ต่างๆ เข้าใปใน method run() มีการเรียกใช้งาน
$cordovaLocalNotification โดย inject เข้าไปใน method นี้ด้วย
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | /////////////// ส่วนของการตรวจจับ event ของ local notification $ionicPlatform.ready( function () { // เตรียมก่อนเรียกใช้ plugin // รอรับการทำงานเมื่อทำการสร้างกำหนดการแจ้งเตือนแล้ว $rootScope.$on( '$cordovaLocalNotification:schedule' , function (event, notification, state) { alert( "SCHEDULED:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อแสดงการแจ้งเตือน $rootScope.$on( '$cordovaLocalNotification:trigger' , function (event, notification, state) { alert( "TRIGGER:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการอัพเดทการแจ้งเตือนแล้ว $rootScope.$on( '$cordovaLocalNotification:update' , function (event, notification, state) { alert( "UPDATE:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการเคลียร์รายการแจ้งเตือนนั้นๆ $rootScope.$on( '$cordovaLocalNotification:clear' , function (event, notification, state) { alert( "CLEARED:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการเคลียร์รายการแจ้งเตือนทั้งหมด $rootScope.$on( '$cordovaLocalNotification:clearall' , function (event, state) { alert( "CLEARED ALL:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการยกเลิกการแจ้งเตือน $rootScope.$on( '$cordovaLocalNotification:cancel' , function (event, notification, state) { alert( "CANCELED:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการยกเลิกการแจ้งเตือนทั้งหมด $rootScope.$on( '$cordovaLocalNotification:cancelall' , function (event, state) { alert( "CANCELED ALL:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการคลิกที่รายการแจ้งเตือน $rootScope.$on( '$cordovaLocalNotification:click' , function (event, notification, state) { alert( "CLICKED:" +JSON.stringify(notification)); }); // ในตัวอย่างเป็นการใช้ alert เพื่อทดสอบการทำงานเท่านั้น สามารถไปประยุกต์สร้างฟังก์ชั่น // หรือกำหนดการทำงานอื่นๆ เพิ่มเติมได้ }); /////////////// ส่วนของการตรวจจับ event ของ local notification |
จะได้ส่วนของ method run() ดังนี้
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | .run( function ($ionicPlatform,$ionicPopup,$cordovaDialogs, $cordovaPushV5, $rootScope, $cordovaDevice, notifyService, $state, $cordovaBadge, $cordovaLocalNotification) { $ionicPlatform.ready( function () { if (window.cordova && window.cordova.plugins.Keyboard) { cordova.plugins.Keyboard.hideKeyboardAccessoryBar( true ); } if (window.StatusBar) { StatusBar.styleDefault(); } }); // กำหนด senderID สำหรับ android var options = { android: { senderID: "1095008408714" } }; $ionicPlatform.ready( function () { // เตรียมก่อนเรียกใช้ plugin // ตั้งค่าเริ่มต้น $cordovaPushV5.initialize(options).then( function () { // เรียกฟังก์ชั่นตรวจจับข้อความ push กรณีได้รับข้อความ $cordovaPushV5.onNotification(); // เรียกฟังก์ชั่นตรวจจับข้อความ push กรณีเกิดข้อผิดพลาด $cordovaPushV5.onError(); // ลงทะเบียนรับ registrationId $cordovaPushV5.register().then( function (registrationId) { // alert('RegID: '+registrationId); // alert('UUID: '+$cordovaDevice.getUUID()); // เตรียมข้อมูลสำหรับส่งไปบันทึกบน server var dataSend = { uid:$cordovaDevice.getUUID(), regid:registrationId }; // service เรียกใช้ฟังก์ชั่น notifyService ส่งค่าไปยัง server notifyService.setNotify(dataSend) .then( function (response) { // ทดสอบแสดงค่าว่าบันทึกสำเร็จหรือไม่ // alert(JSON.stringify(response)); }); }); }); // รอรับทำงานเมื่อ มีข้อความ push เข้ามา $rootScope.$on( '$cordovaPushV5:notificationReceived' , function (event, data){ $cordovaBadge.hasPermission().then( function (yes) { alert(JSON.stringify(yes)); $cordovaBadge.set(data.count).then( function () { alert( 'IN set Badge' ); // You have permission, badge set. }, function (err) { // alert('ERR SET:'+JSON.stringify(err)); // You do not have permission. }); }, function (no) { // alert(JSON.stringify(no)); }); // alert('OK Received:'+JSON.stringify(data)); $state.go( 'app.article' ); // เมื่อเปิดที่ข้อความ push ให้ไปหน้าที่ต้องการ // ชุดข้อมูลที่เราจะได้จากข้อความ push สามารถกำหนดค่าเองเพิ่มเติมได้ // ด้านล่างนี้คือค่าพื้นฐาน // data.message, // ข้อความแจ้ง // data.title, // หัวข้อ // data.count, // จำนวนเลขระบุ กรณีมีการแจ้งจำนวนใดๆ // data.sound, // เสียง // data.image, // รูปภาพที่แสดงใน push ใช้เป็น url ได้ // data.additionalData // ข้อมูลเพิ่ม // ค่าข้างต้นเหล่านี้เป็นค่าที่เรา ต้องกำหนดในไฟล์ส่งข้อความ push }); // รอรับทำงานเมื่อ เกิดข้อผิดพลาด ปกติเราจะไม่ให้ทำงานใดๆ $rootScope.$on( '$cordovaPushV5:errorOcurred' , function (event, e){ // alert('ERR Received:'+JSON.stringify(e)); // e.message // ข้อความ error }); }); /////////////// ส่วนของการตรวจจับ event ของ local notification $ionicPlatform.ready( function () { // เตรียมก่อนเรียกใช้ plugin // รอรับการทำงานเมื่อทำการสร้างกำหนดการแจ้งเตือนแล้ว $rootScope.$on( '$cordovaLocalNotification:schedule' , function (event, notification, state) { alert( "SCHEDULED:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อแสดงการแจ้งเตือน $rootScope.$on( '$cordovaLocalNotification:trigger' , function (event, notification, state) { alert( "TRIGGER:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการอัพเดทการแจ้งเตือนแล้ว $rootScope.$on( '$cordovaLocalNotification:update' , function (event, notification, state) { alert( "UPDATE:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการเคลียร์รายการแจ้งเตือนนั้นๆ $rootScope.$on( '$cordovaLocalNotification:clear' , function (event, notification, state) { alert( "CLEARED:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการเคลียร์รายการแจ้งเตือนทั้งหมด $rootScope.$on( '$cordovaLocalNotification:clearall' , function (event, state) { alert( "CLEARED ALL:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการยกเลิกการแจ้งเตือน $rootScope.$on( '$cordovaLocalNotification:cancel' , function (event, notification, state) { alert( "CANCELED:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการยกเลิกการแจ้งเตือนทั้งหมด $rootScope.$on( '$cordovaLocalNotification:cancelall' , function (event, state) { alert( "CANCELED ALL:" +JSON.stringify(notification)); }); // รอรับการทำงานเมื่อทำการคลิกที่รายการแจ้งเตือน $rootScope.$on( '$cordovaLocalNotification:click' , function (event, notification, state) { alert( "CLICKED:" +JSON.stringify(notification)); }); // ในตัวอย่างเป็นการใช้ alert เพื่อทดสอบการทำงานเท่านั้น สามารถไปประยุกต์สร้างฟังก์ชั่น // หรือกำหนดการทำงานอื่นๆ เพิ่มเติมได้ }); /////////////// ส่วนของการตรวจจับ event ของ local notification }) |
จากตัวอย่าง เราใช้คำสั่ง alert เพื่อดูการทำงานเท่านั้น สามารถเปลี่ยนเป็นคำสั่งอื่นๆ ตามต้องการ
ลำดับการทำงานของ event ต่างๆ ที่จะเกิดขึ้น เป็นดังนี้
- เมื่อเรามีการตั้งกำหนดการแจ้งเตือน event schedule ก็จะทำงาน
- จากนั้นเมื่อมีการแจ้งเตือนแสดงขึ้น event trigger ก็จะทำงาน
- เมื่อมีการแจ้งเตือนขึ้นแถบด้านบนของ app ถ้าเรากด clear หรือลบการแจ้งเตือน event clear ก็จะทำงาน
event clearall จะทำงานเมื่อเรามีการแจ้งเตือนแบบหลายรายการ แล้วทำการ ลบการแจ้งเตือนทั้งหมด
- แต่ถ้าเรากดไปที่การแจ้งเตือน event click ก็จะทำงาน และ event cancel จะทำงานอัตโนมัติถ้า
รายการแจ้งเตือนนั้นเป็นรายการที่แสดงเพียงครั้งเดียว
- ในบางกรณี เราต้องการยกเลิกการกำหนดการแจ้งเตือน เราจะเรียกใช้ฟังก์ชันยกเลิกการแจ้งเตือน และ
เมื่อฟังก์ชันยกเลิกการแจ้งเตือนทำงาน event cancel ก็จะทำงาน
event cancelall จะทำงานเมื่อเรามีการเรียกใช้งานฟังก์ชั่นยกเลิกการกำหนดการแจ้งเตือนทั้งหมด
ในแต่ละ event ที่เกิดขึ้น หากเราต้องการทำงานโดยมีเงื่อนไข เพื่มเติม เราสามารถใช้ค่าจาก
notification และ state สำหรับการทำงานที่หลากหลายได้ เช่น การใช้ state
state ก็จะเป็นลักษณะของการทำงานในขณะนั้น ทำงานแบบ foreground หรือ background
หรือก็คือ ทำงานขณะที่ app นั้นเปิดอยู่ หรือทำงานเบื้องหลังขณะที่ app นั้นปิดอยู่ ตัวอย่างการกำหนด
ในกรณีการคลิก ก็จะได้เป็นประมาณนี้
1 2 3 4 5 6 7 | // รอรับการทำงานเมื่อทำการคลิกที่รายการแจ้งเตือน $rootScope.$on( '$cordovaLocalNotification:click' , function (event, notification, state) { if (state == "background" ) { alert( "CLICKED:" +JSON.stringify(notification)); } }); |
หรือกรณีใช้เงื่อนไขจากค่า notification object (เราสามารถดูค่า property ของ object
ด้วยคำสั่ง JSON.stringify(notification))
1 2 3 4 5 6 7 | // รอรับการทำงานเมื่อทำการคลิกที่รายการแจ้งเตือน $rootScope.$on( '$cordovaLocalNotification:click' , function (event, notification, state) { if (notification.id == 1) { alert( "CLICKED:" +JSON.stringify(notification)); } }); |
3. กำหนดฟังก์ชั่นสำหรับเรียกใช้การสร้างการแจ้งเตือน และการยกเลิกรูปแบบต่างๆ
สำหรับฟังก์ชั่นที่เราจะสร้างขึ้นมา เพื่อใช้สำหรับสร้างการแจ้งเตือน และยกเลิก
หรือเคลียร์การแจ้งเตือนนั้น เราสามารถที่สร้างไว้ใน controller ใดๆ ก็ได้ที่เราต้องการเรียกใช้
ในตัวอย่างนี้ เราจะสร้างไว้ที่ controller หลักหรือ AppCtrl controller
ให้เปิดไฟล์ controllers.js ในโฟลเดอร์ js และกำหนดโค้ดส่วนนี้เข้าไปใน AppCtrl controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | $ionicPlatform.ready( function () { // ========== การกำหนดการแจ้งเตือน // สร้างฟังก์ชั่นกำหนดการแจ้งเตือนรายการเดียว แบบแสดงครั้งเดียว ที่เรียกใช้ $scope.scheduleSingleNotification = function () { $cordovaLocalNotification.schedule({ id: 1, // ค่า id เฉพาะไม่ซ้ำกัน title: 'Title here' , text: 'Text here' , badge:2, // จำนวนตัวเลขที่แสดง data: { // ข้อมูลเพิ่มเตืมถ้าเราต้องการส่งค่าหรือนำค่าไปใช้ customProperty: 'custom value' } }).then( function (result) { // ... }); }; // สร้างฟังก์ชั่นกำหนดการแจ้งเตือนหลายรายการ แบบแสดงครั้งเดียว ที่เรียกใช้ $scope.scheduleMultipleNotifications = function () { $cordovaLocalNotification.schedule([ { id: 1, title: 'Title 1 here' , text: 'Text 1 here' , data: { customProperty: 'custom 1 value' } }, { id: 2, title: 'Title 2 here' , text: 'Text 2 here' , data: { customProperty: 'custom 2 value' } }, { id: 3, title: 'Title 3 here' , text: 'Text 3 here' , data: { customProperty: 'custom 3 value' } } ]).then( function (result) { // ... }); }; // สร้างฟังก์ชั่นกำหนดการแจ้งเตือนรายการเดียว แบบแสดงครั้งเดียว ตามเวลาที่กำหนด $scope.scheduleDelayedNotification = function () { // ตัวนี้จะให้แสดงหลังจากถูกกำหนด 10 วินาที var now = new Date().getTime(); // 10 วินาที่ ให้เอา 10 * 10000 แล้วบวกกับ now var _10SecondsFromNow = new Date(now + 10 * 1000); $cordovaLocalNotification.schedule({ id: 1, title: 'Title here' , text: 'Text here' , at: _10SecondsFromNow // วันที่ เวลาที่กำหนด }).then( function (result) { // ... }); }; // สร้างฟังก์ชั่นกำหนดการแจ้งเตือนรายการเดียว แบบแสดงทุกๆ เวลาที่กำนหด // every ถ้ากำหนดเป็นตัวเลขจะหมายถึง ทุกๆ กี่นาที หรือกำหนดเป็นข้อความเช่น // every: 'minute' หรือใช้คำว่า second, minute, hour, day, week, month or year $scope.scheduleEveryMinuteNotification = function () { $cordovaLocalNotification.schedule({ id: 1, title: 'Title here' , text: 'Text here' , every: 2 // กำหนดเป็นตัวเลขหมายถึง ทุกๆ 2 นาที }).then( function (result) { // ... }); }; // ========== การกำหนดการแจ้งเตือน // ========== การแก้ไขการแจ้งเตือน // การแก้ไขการแจ้งเตือนกรณีแสดงรายการเดียว เครื่องเดียว การแก้ไขคือการอ้างอิงค่า id // ที่ยังทำงานอยู่ให้เปลี่ยนแปลงค่าหรือรูปแบบการแจ้งเตือน โดยจะไม่ใช้การสร้างการแจ้งเตือนใหม่ // การแก้ไขการแจ้งเตือนจะทำได้กรณีค่าการแจ้งเตือนนั้นๆ ไม่ถูกเคลียร์หรือยกเลิกไปก่อน $scope.updateSingleNotification = function () { $cordovaLocalNotification.update({ id: 1, title: 'Title - UPDATED' , text: 'Text - UPDATED' }).then( function (result) { // ... }); }; // การแก้ไขการแจ้งเตือนกรณีแสดงหลายรายการ เครื่องเดียว การแก้ไขคือการอ้างอิงค่า id // ที่ยังทำงานอยู่ให้เปลี่ยนแปลงค่าหรือรูปแบบการแจ้งเตือน โดยจะไม่ใช้การสร้างการแจ้งเตือนใหม่ // การแก้ไขการแจ้งเตือนจะทำได้กรณีค่าการแจ้งเตือนนั้นๆ ไม่ถูกเคลียร์หรือยกเลิกไปก่อน $scope.updateMultipleNotifications = function () { $cordovaLocalNotification.update([ { id: 1, title: 'Title 1 - UPDATED' , text: 'Text 1 - UPDATED' }, { id: 2, title: 'Title 2 - UPDATED' , text: 'Text 2 - UPDATED' }, { id: 3, title: 'Title 3 - UPDATED' , text: 'Text 3 - UPDATED' } ]).then( function (result) { // ... }); }; // ========== การแก้ไขการแจ้งเตือน // ========== ฟังก์ชั่นส่วนของการยกเลิกการแจ้งเตือน $scope.cancelSingleNotification = function () { $cordovaLocalNotification.cancel(1).then( function (result) { alert( "CANCELED SINGLE:" +JSON.stringify(result)); }); }; $scope.cancelMultipleNotifications = function () { $cordovaLocalNotification.cancel([1, 2]).then( function (result) { alert( "CANCELED MULTI:" +JSON.stringify(result)); }); }; $scope.cancelAllNotifications = function () { $cordovaLocalNotification.cancelAll().then( function (result) { alert( "CANCELED ALL:" +JSON.stringify(result)); }); }; // ========== ฟังก์ชั่นส่วนของการยกเลิกการแจ้งเตือน // ========== ฟังก์ชั่นส่วนของการเคลียร์รายการแจ้งเตือนที่แสดง $scope.clearSingleNotification = function () { $cordovaLocalNotification.clear(1).then( function (result) { alert( "CLEARED SINGLE:" +JSON.stringify(result)); }); }; $scope.clearMultipleNotifications = function () { $cordovaLocalNotification.clear([1, 2]).then( function (result) { alert( "CLEARED MULTI:" +JSON.stringify(result)); }); }; $scope.clearAllNotifications = function () { $cordovaLocalNotification.clearAll().then( function (result) { alert( "CLEARED ALL:" +JSON.stringify(result)); }); }; // ========== ฟังก์ชั่นส่วนของการเคลียร์รายการแจ้งเตือนที่แสดง }); |
จะได้ในส่วนของ AppCtrl controller ทั้งหมดเป็นประมาณนี้
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | .controller( 'AppCtrl' , function ($scope, $ionicModal, $ionicPopover, $timeout, $ionicPopup,$ionicPlatform, $cordovaDialogs, $cordovaToast, $state, $cordovaLocalNotification) { $scope.loginData = {}; $scope.isExpanded = false ; $scope.hasHeaderFabLeft = false ; $scope.hasHeaderFabRight = false ; var navIcons = document.getElementsByClassName( 'ion-navicon' ); for ( var i = 0; i < navIcons.length; i++) { navIcons.addEventListener( 'click' , function () { this .classList.toggle( 'active' ); }); } //////////////////////////////////////// // Layout Methods //////////////////////////////////////// $scope.hideNavBar = function () { document.getElementsByTagName( 'ion-nav-bar' )[0].style.display = 'none' ; }; $scope.showNavBar = function () { document.getElementsByTagName( 'ion-nav-bar' )[0].style.display = 'block' ; }; $scope.noHeader = function () { var content = document.getElementsByTagName( 'ion-content' ); for ( var i = 0; i < content.length; i++) { if (content[i].classList.contains( 'has-header' )) { content[i].classList.toggle( 'has-header' ); } } }; $scope.setExpanded = function (bool) { $scope.isExpanded = bool; }; $scope.setHeaderFab = function (location) { var hasHeaderFabLeft = false ; var hasHeaderFabRight = false ; switch (location) { case 'left' : hasHeaderFabLeft = true ; break ; case 'right' : hasHeaderFabRight = true ; break ; } $scope.hasHeaderFabLeft = hasHeaderFabLeft; $scope.hasHeaderFabRight = hasHeaderFabRight; }; $scope.hasHeader = function () { var content = document.getElementsByTagName( 'ion-content' ); for ( var i = 0; i < content.length; i++) { if (!content[i].classList.contains( 'has-header' )) { content[i].classList.toggle( 'has-header' ); } } }; $scope.hideHeader = function () { $scope.hideNavBar(); $scope.noHeader(); }; $scope.showHeader = function () { $scope.showNavBar(); $scope.hasHeader(); }; $scope.clearFabs = function () { var fabs = document.getElementsByClassName( 'button-fab' ); if (fabs.length && fabs.length > 1) { fabs[0].remove(); } }; $scope.noShadow = function () { var headerBar = document.getElementsByTagName( 'ion-header-bar' ); for ( var i = 0; i < headerBar.length; i++) { if (!headerBar[i].classList.contains( 'no-shadow' )) { headerBar[i].classList.add( 'no-shadow' ); } } }; $scope.hasShadow = function () { var headerBar = document.getElementsByTagName( 'ion-header-bar' ); for ( var i = 0; i < headerBar.length; i++) { if (headerBar[i].classList.contains( 'no-shadow' )) { headerBar[i].classList.remove( 'no-shadow' ); } } }; // ตัวแปรสำหรับกำหนด การซ่อนหรือแสดงเมนูสมาชิก false คือซ่อนเมนูสมาชิก $scope.showMemberMenu = false ; // สร้างฟังก์ชั่น สำหรับเรียกใช้ เพื่อกำหนดการ กำหนดค่าตัวแปรเพื่อซ่อนหรือแสดงเมนู $scope.setMemberMenu = function (status){ $scope.showMemberMenu = status; }; // กำหนดตัวแปรไว้สำหรับเก็บ id ของสมาชิกที่สมัครในเครื่องนั้นๆ $scope.sesMemberID = null ; // สร้างฟังก์ชั่นสำหรับกำหนดค่า id ให้สามารถเรียกใช้งานจาก $scope หลักได้ $scope.setMemberID = function (memID){ $scope.sesMemberID = memID; }; // สร้างฟังก์ชั่นสำหรับเรียกดูค่า id ของสมาชิกจาก $scope หลักได้ $scope.getMemberID = function (){ return $scope.sesMemberID; }; // สร้างฟังก์ชั่นสำหรับเรียกใช้ Toast plugin $scope.showToast = function (str, duration, position){ $ionicPlatform.ready( function () { // เตรียมก่อนเรียกใช้ plugin return $cordovaToast .show(str, duration, position) .then( function (success) { // success }, function (error) { // error }); }); }; var db = null ; $ionicPlatform.ready( function () { // เตรียมก่อนเรียกใช้ plugin // ตรวจสอบและทำการเชื่อมต่อกับ db db = window.sqlitePlugin.openDatabase({ name: 'my.db' , location: 'default' }, function (db) { // เชื่อมต่อ db สำเร็จ $scope.showToast( 'Open DB Success' , 'long' , 'bottom' ); // เริ่มทำงานของคำสั่ง db db.transaction( function (tx) { // เวลามีการทดสอบและเพิ่มฟิลด์หรือแก้ไขตารางควรเปิดคอมเม้นการลบตารางก่อน // นั้นหมายถึงตารางจะถูกสร้างและจัดรูปแบบใหม่ทุกครั้ง ข้อมูลตารางจะรีเซ็ต ล้างค่า // พอว่างโครงสร้างตารางเรียบร้อยแล้ว ให้ปิดคอมเม้นไว้เหมือนเดิม เพื่อให้ข้อมูลยังคงอยู่ // tx.executeSql('DROP TABLE IF EXISTS setting'); // ทำคำสั่งสร้างตาราง setting ถ้ายังไม่มี ในที่นี้เราเก็บแค่ setting_id และ member_id tx.executeSql( '' + 'CREATE TABLE IF NOT EXISTS setting ' + '(setting_id integer primary key,' + 'member_id integer,notify_status interger)' + '' ); // เช็คตาราง setting ว่ามีข้อมูลไหม tx.executeSql( '' + 'SELECT setting_id,member_id,' + 'notify_status FROM setting' , [], function (tx, res) { if (res.rows.length<=0){ // ถ้าไม่มีข้อมูล ให้เพิ่มข้อมูลไป var query = "INSERT INTO setting" + " (member_id,notify_status) " + " VALUES (?,1)" ; var member_id = 0; // ทำงานคำสั่ง sql tx.executeSql(query, [member_id], function (tx, res) { // เมื่อทำการบันทึกข้อมูลสำเร็จ // ค่าเริ่มต้น เราจะให้ member_id เป็น 0 ไว้ก่อน แล้วค่อยมาอัพเเดทที่หลัง $scope.showToast( 'insertId: ' + res.insertId + ' -- probably 1' , 'long' , 'bottom' ); $scope.showToast( 'rowsAffected: ' + res.rowsAffected + ' -- should be 1' , 'long' , 'bottom' ); }, function (tx, error) { $scope.showToast( 'INSERT error: ' + error.message, 'long' , 'bottom' ); }); } else { // ถ้ามีข้อมูลอยู่แล้ว และ member_id ที่เก็บไว้ไม่เท่ากับ 0 $scope.setNotify(res.rows.item(0).notify_status); if (res.rows.item(0).member_id!=0){ // เช็ค member_id ที่เก็ยไว้ไม่เท่ากับ 0 $scope.setMemberID(res.rows.item(0).member_id); // กำหนดค่าตัวแปร $state.go( 'app.profile' ); // ไปที่หน้าโพรไฟล์ } } }); }, function (error) { $scope.showToast( 'transaction error: ' + error.message, 'long' , 'bottom' ); }, function () { $scope.showToast( 'transaction ok' , 'long' , 'bottom' ); }); }, function (error) { $scope.showToast( 'Open database ERROR: ' + JSON.stringify(error), 'long' , 'bottom' ); }); }); // สร้างฟังก์ชั่นสำหรับ logout $scope.logoutMember = function (){ $ionicPlatform.ready( function () { // เตรียมก่อนเรียกใช้ plugin // ขึ้นแจ้งเตือนว่าต้องการจะออกจากระบบหรือไม่ $cordovaDialogs.confirm( 'ยืนยันออกจากระบบ?' , 'ออกจากระบบ?' , [ 'ตกลง' , 'ยกเลิก' ]) .then( function (buttonIndex) { // no button = 0, 'OK' = 1, 'Cancel' = 2 var btnIndex = buttonIndex; if (btnIndex==2){ // ถ้าตอบ ยกเลิก return false ; // หยุดการทำงาน ไม่ต้องออกจากระบบ } if (btnIndex==1){ // ถ้าตอบ ตกลง ยืนบันออกจากรับบ // เริ่มทำงานของคำสั่ง db db.transaction( function (tx) { // ล้างค่า member_id ที่บันทึกไว้ในตาราง setting ให้เป็น 0 คือไม่จำ member_id var query = "UPDATE setting SET member_id = 0 WHERE setting_id = 1" ; tx.executeSql(query); $scope.sesMemberID = null ; $state.go( 'app.login' ); // ไปที่หน้าล็อกอิน }, function (error) { $scope.showToast( 'transaction error: ' + error.message, 'long' , 'bottom' ); }, function () { $scope.showToast( 'transaction ok' , 'long' , 'bottom' ); }); } }); }); }; // กำหนดตัวแปรไว้สำหรับเก็บ notify status ในเครื่องนั้นๆ $scope.sesNotify = null ; // สร้างฟังก์ชั่นสำหรับกำหนดค่า notify status ให้สามารถเรียกใช้งานจาก $scope หลักได้ $scope.setNotify = function (status){ $scope.sesNotify = status; }; // สร้างฟังก์ชั่นสำหรับเรียกดูค่า notify status ของสมาชิกจาก $scope หลักได้ $scope.getNotify = function (){ return $scope.sesNotify; }; $ionicPlatform.ready( function () { // ========== การกำหนดการแจ้งเตือน // สร้างฟังก์ชั่นกำหนดการแจ้งเตือนรายการเดียว แบบแสดงครั้งเดียว ที่เรียกใช้ $scope.scheduleSingleNotification = function () { $cordovaLocalNotification.schedule({ id: 1, // ค่า id เฉพาะไม่ซ้ำกัน title: 'Title here' , text: 'Text here' , badge:2, // จำนวนตัวเลขที่แสดง data: { // ข้อมูลเพิ่มเตืมถ้าเราต้องการส่งค่าหรือนำค่าไปใช้ customProperty: 'custom value' } }).then( function (result) { // ... }); }; // สร้างฟังก์ชั่นกำหนดการแจ้งเตือนหลายรายการ แบบแสดงครั้งเดียว ที่เรียกใช้ $scope.scheduleMultipleNotifications = function () { $cordovaLocalNotification.schedule([ { id: 1, title: 'Title 1 here' , text: 'Text 1 here' , data: { customProperty: 'custom 1 value' } }, { id: 2, title: 'Title 2 here' , text: 'Text 2 here' , data: { customProperty: 'custom 2 value' } }, { id: 3, title: 'Title 3 here' , text: 'Text 3 here' , data: { customProperty: 'custom 3 value' } } ]).then( function (result) { // ... }); }; // สร้างฟังก์ชั่นกำหนดการแจ้งเตือนรายการเดียว แบบแสดงครั้งเดียว ตามเวลาที่กำหนด $scope.scheduleDelayedNotification = function () { // ตัวนี้จะให้แสดงหลังจากถูกกำหนด 10 วินาที var now = new Date().getTime(); // 10 วินาที่ ให้เอา 10 * 10000 แล้วบวกกับ now var _10SecondsFromNow = new Date(now + 10 * 1000); $cordovaLocalNotification.schedule({ id: 1, title: 'Title here' , text: 'Text here' , at: _10SecondsFromNow // วันที่ เวลาที่กำหนด }).then( function (result) { // ... }); }; // สร้างฟังก์ชั่นกำหนดการแจ้งเตือนรายการเดียว แบบแสดงทุกๆ เวลาที่กำนหด // every ถ้ากำหนดเป็นตัวเลขจะหมายถึง ทุกๆ กี่นาที หรือกำหนดเป็นข้อความเช่น // every: 'minute' หรือใช้คำว่า second, minute, hour, day, week, month or year $scope.scheduleEveryMinuteNotification = function () { $cordovaLocalNotification.schedule({ id: 1, title: 'Title here' , text: 'Text here' , every: 2 // กำหนดเป็นตัวเลขหมายถึง ทุกๆ 2 นาที }).then( function (result) { // ... }); }; // ========== การกำหนดการแจ้งเตือน // ========== การแก้ไขการแจ้งเตือน // การแก้ไขการแจ้งเตือนกรณีแสดงรายการเดียว เครื่องเดียว การแก้ไขคือการอ้างอิงค่า id // ที่ยังทำงานอยู่ให้เปลี่ยนแปลงค่าหรือรูปแบบการแจ้งเตือน โดยจะไม่ใช้การสร้างการแจ้งเตือนใหม่ // การแก้ไขการแจ้งเตือนจะทำได้กรณีค่าการแจ้งเตือนนั้นๆ ไม่ถูกเคลียร์หรือยกเลิกไปก่อน $scope.updateSingleNotification = function () { $cordovaLocalNotification.update({ id: 1, title: 'Title - UPDATED' , text: 'Text - UPDATED' }).then( function (result) { // ... }); }; // การแก้ไขการแจ้งเตือนกรณีแสดงหลายรายการ เครื่องเดียว การแก้ไขคือการอ้างอิงค่า id // ที่ยังทำงานอยู่ให้เปลี่ยนแปลงค่าหรือรูปแบบการแจ้งเตือน โดยจะไม่ใช้การสร้างการแจ้งเตือนใหม่ // การแก้ไขการแจ้งเตือนจะทำได้กรณีค่าการแจ้งเตือนนั้นๆ ไม่ถูกเคลียร์หรือยกเลิกไปก่อน $scope.updateMultipleNotifications = function () { $cordovaLocalNotification.update([ { id: 1, title: 'Title 1 - UPDATED' , text: 'Text 1 - UPDATED' }, { id: 2, title: 'Title 2 - UPDATED' , text: 'Text 2 - UPDATED' }, { id: 3, title: 'Title 3 - UPDATED' , text: 'Text 3 - UPDATED' } ]).then( function (result) { // ... }); }; // ========== การแก้ไขการแจ้งเตือน // ========== ฟังก์ชั่นส่วนของการยกเลิกการแจ้งเตือน $scope.cancelSingleNotification = function () { $cordovaLocalNotification.cancel(1).then( function (result) { alert( "CANCELED SINGLE:" +JSON.stringify(result)); }); }; $scope.cancelMultipleNotifications = function () { $cordovaLocalNotification.cancel([1, 2]).then( function (result) { alert( "CANCELED MULTI:" +JSON.stringify(result)); }); }; $scope.cancelAllNotifications = function () { $cordovaLocalNotification.cancelAll().then( function (result) { alert( "CANCELED ALL:" +JSON.stringify(result)); }); }; // ========== ฟังก์ชั่นส่วนของการยกเลิกการแจ้งเตือน // ========== ฟังก์ชั่นส่วนของการเคลียร์รายการแจ้งเตือนที่แสดง $scope.clearSingleNotification = function () { $cordovaLocalNotification.clear(1).then( function (result) { alert( "CLEARED SINGLE:" +JSON.stringify(result)); }); }; $scope.clearMultipleNotifications = function () { $cordovaLocalNotification.clear([1, 2]).then( function (result) { alert( "CLEARED MULTI:" +JSON.stringify(result)); }); }; $scope.clearAllNotifications = function () { $cordovaLocalNotification.clearAll().then( function (result) { alert( "CLEARED ALL:" +JSON.stringify(result)); }); }; // ========== ฟังก์ชั่นส่วนของการเคลียร์รายการแจ้งเตือนที่แสดง }); }) |
การสร้างฟังก์ชั่นข้างต้นเป็นรูปแบบตัวอย่าง เราสามารถนำไปประยุกต์สร้างรูปแบบฟังก์ชั่นตามต้องการได้
เช่น สร้างฟังก์ชั่นการกำหนดการแจ้งเตือน โดยสามารถให้รับค่าตัวแปรค่าต่างๆ เข้าไปแทนการกำหนดตายตัว
ตัวอย่างเช่น
1 2 3 4 5 6 7 8 9 10 | $scope.myscheduleSingleNotification = function (id, title, text, badge, ) { $cordovaLocalNotification.schedule({ id: id, title: title, text: text, badge:badge }).then( function (result) { // ... }); }; |
การที่เรากำหนดฟังก์ชั่นไว้ใน controller หลัก ก็เพื่อที่จะให้สะดวกในการเรียกใช้งาน โดยสามารถเรียกใช้
ในหน้า view ใดๆ ก็ได้ เช่น เรียกใช้เมื่อคลิกที่ปุมที่ต้องการ
1 2 | < button ng-click = "scheduleSingleNotification()" class = "button button-small button-calm-900" > Single Schedule</ button > |
หรือเรียกใช้จาก controller อื่นๆ ผ่านคำตัวแปร $scope เช่น
1 | $scope.$parent.scheduleSingleNotification(); |
4. ทำการเรียกใช้ฟังก์ชั่นกำหนดการแจ้งเตือน จากหน้าอื่นๆ
ในที่นี้สมมติเราจะสร้างไว้ในหน้า Notification จากบทความตอนที่แล้ว โดยเราจะเพิ่มปุ่มเข้าไป
แล้วเรียกใช้ฟังก์ชั่นต่างๆ จ่างปุ่มนั้น ให้เราเปิดไฟล์
notification.html ในโฟลเดอร์ templates แล้วปรับโค้ดเพิ่มเติมเป็นดังนี้
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | < ion-view view-title = "Notification" > < ion-nav-buttons side = "right" > < div class = "buttons buttons-right header-item" > < span class = "right-buttons" > < button class = "button button-icon button-clear ion-android-more-vertical" > </ button > </ span > </ div > </ ion-nav-buttons > < ion-content class = "stable-bg" ng-class = "{expanded:isExpanded}" > < div class = "list card" > < div ng-repeat = "notify in notifyItem" class = "item item-avatar" ng-click = "gourl(notify.id);" > < img src = "img/logo.png" > < h2 >{{notify.topic}}</ h2 > < p >{{notify.daydate}}</ p > </ div > </ div > < div class = "padding" > < button ng-click = "scheduleSingleNotification()" class = "button button-small button-calm-900" > Single Schedule</ button > < br />< br /> < button ng-click = "scheduleMultipleNotifications()" class = "button button-small button-calm-900" > Multi Schedule</ button > < br />< br /> < button ng-click = "scheduleDelayedNotification()" class = "button button-small button-calm-900" > Single Schedule Delay 10 seconds</ button > < br />< br /> < button ng-click = "scheduleEveryMinuteNotification()" class = "button button-small button-calm-900" > Single Schedule Every Minute</ button > < br /> < br />< br /> < button ng-click = "updateSingleNotification()" class = "button button-small button-balanced-900" > Update Single Schedule</ button > < br />< br /> < button ng-click = "updateMultipleNotifications()" class = "button button-small button-balanced-900" > Update Multi Schedule</ button > < br /> < br />< br /> < button ng-click = "cancelSingleNotification()" class = "button button-small button-assertive-900" > Cancel Single Schedule </ button > < br />< br /> < button ng-click = "cancelMultipleNotifications()" class = "button button-small button-assertive-900" > Cancel Multi Schedule </ button > < br />< br /> < button ng-click = "cancelAllNotifications()" class = "button button-small button-assertive-900" > Cancel All Schedule </ button > < br /> < br />< br /> < button ng-click = "clearSingleNotification()" class = "button button-small button-energized-900" > Clear Single Notification </ button > < br />< br /> < button ng-click = "clearMultipleNotifications()" class = "button button-small button-energized-900" > Clear Multi Notification </ button > < br />< br /> < button ng-click = "clearAllNotifications()" class = "button button-small button-energized-900" > Clear All Notification </ button > < br /> </ div > </ ion-content > </ ion-view > |
5. ทำการ build apk ไฟล์แล้วนำไปทดสอบติดตั้งบนมือถือ
ด้วยคำสั่ง
1 | C:\phonegap\learn005>phonegap build android |
ให้ทำการทดสอบติดตั้งในมือถือ android ของเรา จะได้หน้าตา app ประมาณนี้
หน้าทดสอบ Local Notification สมมติกด แสดงรายการเดียว จะขึ้นตามรูปทีสอง ในรูปที่สอง เราจะเห็นปุ่ม clear ขีดๆ สามอัน ถ้าเรากดปุ่มนี้ event clear ก็จะทำงาน



ปุ่มอื่นๆ สามารถทดสอบกดูได้ ตัวอย่างที่กำหนดทุกนาที ในไฟล์ทดสอบได้กำหนดเป็น 2 นาที หากทดสอบแล้วให้รอ 2 นาที รูปสุดท้าย ทดสอบแส้งแบบหลายรายการ

