Wednesday, July 8, 2020

Push notify by Firebase Cloud Messaging แบบกลุ่ม (Flutter & PHP)

Flutter (NEWS คือ ชื่อ topic ที่เรากำหนดเอง)
firebaseMessaging.subscribeToTopic("NEWS");
 //firebaseMessaging.unsubscribeFromTopic("NEWS");
ยิงผ่าน PHP
ยิงผ่าน Firebase console
  • ใส่ Title และ Body กด Next
  • เลือกที่ Topic ใส่หัวข้อ อันเดียวกันกับที่เราใส่ใน app flutter ในที่นี้คือ NEWS และ กด Next
  • เลือก Now คือ จะส่งตอนนี้ และ กด Next
  • อันนี้ไม่รู้ Next อย่างเดียว
  • กด Review เลย
  • สุดท้าย Publish
  • ใน Flutter app เราก็จะได้รับ Message แล้ว
Ref

สั่งให้ส่งข้อความด้วย Cloud Messaging (Firebase Service) ด้วย PHP

Step
  • เข้าไปที่โปรเจค Firebase ที่เราได้สร้างและ ผูกกับ Flutter app เราไว้
  • เลือกที่ app ของเราเลือก
  • มันจะขึ้นฟันเฟืองเลือกซะ
  • ไปที่ Cloud Messaging มองหา  Server key
  • เราจะเอา Server key นี่แหละไปใช้ต่อใน PHP เรา
  • สร้าง Class และ function ไว้ใน Class รอนำไปใช้
  • url ที่เราจะส่งไปคือ https://fcm.googleapis.com/fcm/send
  • ใส่ server key
class FCM {
    public function send_notification($token, $payload_notification, $payload_data) {
     
        $url =
'https://fcm.googleapis.com/fcm/send';
        $server_key = "AAAAd5RlNIc:APA91bFd3DplNtHcxGIauRHHJnXXXkCak6VaM4te6IA89H4MKr-OqzlapuohWNS-4rIZgdOWQu00tlUOWXMxLP9ROCffcuXth2N7nO9-CsbEkgirwaEk35DuuXeFOg-9Oeo0XmPzEd41";
        $fields = array(
            'registration_ids' => $token,
            // 'condition' => "'logined' in topics || 'news' in topics",
            // 'to' => '/topics/news',
            'priority' => 'normal',
            'notification' => $payload_notification,
            'data' => $payload_data
        );
        $headers = array(
            "Authorization: key=$server_key",
            'Content-Type: application/json'
        );
        // Open connection
        $ch = curl_init();
        // Set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        // Disabling SSL Certificate support temporary
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
        // Execute post
        $result = curl_exec($ch);
        if ($result === FALSE) {
            die('Curl failed: ' . curl_error($ch));
        }
        // Close connection
        curl_close($ch);
        echo $result;
    }
}
?>
  • ที่นี้เรียกใช้งาน Class ที่เราสร้างขึ้น โดยเราต้องไปเอา Token จาก app flutter เรามาใช้ด้วย เพราะเราจะส่งข้อความไป app นั้น
include("fcm.php");
/*
$token = array('TOKEN1', 'TOKEN2');
*/
$token = array(
'eRmBqU2oZrQ:APA91bEH5I-VK0rkMqrwuWaGRBWkCiWsCwJLCRTgKU3tkQG6eVQdexUOvfbO_7ET19eDHsxEj8PMWes3_slWPvFsXZOTr52Fux6Ej1nwjIQ8lHgLi_Ug4wrrSWnw4hAK3f1rj7IhuN7f');
$msg =
"ข้อความแสดงใน body";
$notification = array(
'title' =>
'ข้อความ title',
'body' => "$msg", // Required for iOS 'sound' => 'default',
'badge' => 1,
'click_action' => 'OPEN_ACTIVITY_1'
);
$data = array(
'picture_url' => 'https://xxxx/slide/uploads2/20200318141207_0183.png'
);
$fcm = new FCM();
$fcm->send_notification($token, $notification, $data);
?>
  • สั่งผ่านเว็บ ส่งสำเร็จจะได้ประมาณนี้
Ref

Flutter ทำ push notify by Firebase 2

Step
  • มองหา Cloud Messaging
  • เลือกที่ Send your first message
  • ใส่ Title และ Body ที่เราจะส่งไปที่ app เรา จากนั้นเลือก Send test message
  • จากนั้นใส่ Token key ที่ได้จาก Flutter app เรา (คือจะส่งไปให้ app ที่ใช้ token key นี้ว่างั้นคล้ายๆ ระบุตัวตน) กดปุ่ม บวก
  • ตามด้วยกดปุ่ม Test
  • ดูข้อความใน app เรา
  • และใน console terminal ของ android studio
Related

Flutter ทำ push notify by Firebase 1

  • ครั้งก่อนเขียนเกี่ยวกับการทำ push notify เมื่อเรากดปุ่มบน app เรา
  • วันนี้จะลองคือ ไม่ต้องกดปุ่มแล้วสั่ง online มาแล้วให้แสดง push notify โดยใช้ความสามารถนี้ผ่าน Firebase service (Cloud Messaging)
Pre
  • ก่อนอื่นเลยอย่าลืม add Firebase config ใน Flutter 
  • ขั้นต่อไป คือเตรียมโค้ดทำ Local push notify เตรียมไว้รอ
  • จากนั้นมาเพิ่มส่วนโค้ดเกี่ยวกับ firebase messaging กัน
Step
  • เพิม dependencies firebase_massging กับ firebase_core ใน pubspec.yaml
  • ตามด้วยคำสั่ง flutter pub get
  • import firebase_messaging.dart
  • ประกาศตัวแปร FirebaseMessaging
  • ที่นี้เพิ่มโค้ดเกี่ยวกับรอรับ Messaging จาก Firebase ประมาณนี้ (โค้ดเดิม Local push notify คงไว้)
initFirebaseMessaging();


void initFirebaseMessaging() {
    firebaseMessaging.configure(
      onMessage: (Map message) async {
        print("onMessage: $message");
        Map mapNotification = message["notification"];
        String title = mapNotification["title"];
        String body = mapNotification["body"];
        sendNotificationOnline(title: title, body: body);
      },
      onLaunch: (Map message) async {
        print("onLaunch: $message");
      },
      onResume: (Map message) async {
        print("onResume: $message");
      },
    );
    firebaseMessaging.requestNotificationPermissions(
        const IosNotificationSettings(sound: true, badge: true, alert: true));
    firebaseMessaging.onIosSettingsRegistered
        .listen((IosNotificationSettings settings) {
      print("Settings registered: $settings");
    });
    firebaseMessaging.getToken().then((String token) {
      assert(token != null);
      print("Token : $token");
    });
  }
  • สร้าง sendMessaging สำหรับทำงานเมื่อ Message เข้ามาใน onMessage

  • ถ้าลองรันดูแล้ว รันได้แต่ exception ประมาณนี้
[firebase_core_web , firebase_auth_web, cloud_firestore_web ] 
  • เข้าไปแก้ไขที่ android -> setting-gradle
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
    include ":$name"
    project(":$name").projectDir = pluginDirectory
}
  • ทดสอบรันอีกครั้งถ้าสำเร็จเราจะได้ Token key จาก Firebase แบบนี้ ในหน้าต่างด้านล่าง
Ref

Friday, July 3, 2020

Flutter ทำ push notify แบบ local


  • push notify ก็คล้ายๆ เราใช้ Line แล้วมีคนส่งข้อความถึงเรา
  • ข้อความนั้นก็จะแสดงป๊อปอัพด้านบนโทรศัพท์เรา อันนั้นแหละเลือก push notify
  • ซึ่งแบบ Line นั้นมัน online มา
  • แต่ local notify คือประมาณเราจะสั่งให้แสดงเองจากโปรแกรมที่เราเขียนนี่แหละ

Step

  • เพิ่ม dependencies: ใน pubspec.yaml (แนะนำใช้ version ล่าสุด โดยไป search ใน https://pub.dev/ ดูตรง Installing เราจะได้ version ล่าสุด) 


  • จากนั้นสั่งคำสั่ง ตามด้านล่างนี้ (หรือคลิก Pub get บน bar IDE ก็ได้เช่นกัน) 
  • $ flutter pub get
  • ต่อไปคือแก้ไขไฟล์ AndroidManifest.xml เพิ่ม permission และ receiver และ Save ให้เรียบร้อย


  • เริ่มโค้ดจริงๆ แหละ เปิด main.dart เลย จัดการที่ไฟล์นี้แหละ
  • เพิ่ม import package และ สร้าง global object 1 ตัว

FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();

  • ที่ initState คือ เราต้องกำหนด initialize ของ flutterLocalNotificationsPlugin
  • ซึ่งสิ่งที่เราต้องทำคือ สร้าง InitializationSettings สำหรับ android และ iOS ให้มัน
  • ใน android หากเรากดที่ noti มันจะเข้ามาที่ onSelectNotification แต่ใน iOS จะเข้ามาที่ onDidReceiveLocalNotification
  • เพิ่ม initState() ภายใน class _MyHomePageState extends State { ... }

  @override  initState() {    message = "No message.";
    var initializationSettingsAndroid =        AndroidInitializationSettings('logo_moph');
    var initializationSettingsIOS = IOSInitializationSettings(        onDidReceiveLocalNotification: (id, title, body, payload) {      print("onDidReceiveLocalNotification called.");    });
    var initializationSettings = InitializationSettings(        initializationSettingsAndroid, initializationSettingsIOS);
    flutterLocalNotificationsPlugin.initialize(initializationSettings,        onSelectNotification: (payload) {      // when user tap on notification.      print("onSelectNotification called.");      setState(() {        message = payload;      });    });    super.initState();  }

  • โดยสังเกตใน AndroidInitializationSettingAndroid('logo_moph');
  • logo_moph คือ ไฟล์ภาพ png ที่จะเอามาเป็น icon แสดงใน notify ด้วย พาธจะอยู่ที่นี้ android/app/src/main/res/drawable (อันนี้เจอ error บ่อยๆ เวลารัน)


  • สร้าง method send... สำหรับรับกับการกดปุ่มของเรา ใส่ title และ body ของ notify ส่วน payload คือ คลิก notify popup แล้ว เอา data ส่วนนี้ไปใช้งานต่อ เผื่อ setstate ใหม่

sendNotification() async {    var androidPlatformChannelSpecifics = AndroidNotificationDetails(      '10000',      'FLUTTER_NOTIFICATION_CHANNEL',      'FLUTTER_NOTIFICATION_CHANNEL_DETAIL',      importance: Importance.Max,      priority: Priority.High,    );    var iOSPlatformChannelSpecifics = IOSNotificationDetails();
    var platformChannelSpecifics = NotificationDetails(        androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
    await flutterLocalNotificationsPlugin.show(111, 'My title',        'My body message', platformChannelSpecifics,        payload: 'My data');  }

  • เพิ่มเรียก send method ใน onpressed


  • รันโค้ดแล้วกดปุ่ม Send เลย ถ้าทุกอย่างถูกต้องเราจะได้ push notify แสดงดังภาพ


เพิ่มเติม
  • ชื่อ popup เหนือ title เราตั้งค่าได้ใน AndroidManifest.xml โดยตั้งที่ 
  • android:label="your_app_name"
Ref

Add firebase service to Flutter project

  • ประเด็นมีอยู่ว่า จะทำ Mobile app และ มีระบบ push notify
  • และเราเองไม่เคยเขียน  android app เลย ทำไงดีล่ะ 
  • ลองเขียน Flutter ดูพอจะเข้าใจบ้างเล็กน้อยแล้วหว่า เลยหาวิธีทำ Push notify ใน Flutter
  • ซึ่งลองหาข้อมูลแล้ว เห็นเค้าๆ ใช้ Cloud Messaging ซึ่งเป็น Service ของ Firebase
  • ขึ้นแรกต้องเพิ่ม Firebase เข้าไปใน Flutter project เราก่อน ถึงจะเรียกใช้ Service ต่างๆ ได้
Environment
  • Ubuntu 18.04 Desktop 64bit
  • Flutter v1.17.3
  • Android Studio 4.0
  • Emulator Pixel XL, API 27, 1440x2560:560dpi, Android 8.1(Google APIs), CPU/ABI = x86
Step 
  • สร้าง Flutter Project ขึ้นมา => Start a new Flutter project
  • เลือก Flutter Application แล้วกัน
  • ตั้งชื่อ Project และ เลือกพาธ Flutter SDK บนเครื่องเรา
  • ตั้งชื่อ Package และ Finish
  • ตั้งชื่อ Firebase project ของเรา
  • ไม่ต้องทำไร เลือก Continue
  • เลือก Default Account for Firebase และ Create project
  • รอมันสร้างเสร็จแล้ว Continue
  • ใน Console project ที่เราสร้างเลือก Android Icon (iOS ไว้ทีหลังทำไม่เป็น)
  • ให้เราไปเปิดไฟล์ AndroidManifest.xml มองหาค่า package="packagename" เราต้องใช้ค่ามันไปใส่ในขั้นตอนต่อไป (พาธนี้ projectname/android[projectname]/app/src/main/AndroidManifest.xml)
  • Register app android package name ใส่ค่าที่ได้จากไฟล์ AndroidManifest.xml
  • Nickname ใส่ไปเลยแล้วแต่เรา ส่วนค่า Debug signing certificate SHA-1 คลิกที่รูป ? เพื่อไปเอาค่ามา
  • หลังจากที่คลิก ? ไปที่หน้า doc
  • ให้เราใช้คำสั่งในหน้า doc นั้นไปรันใน terminal
  • $ keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore
  • มันจะให้ใส่ Password เราก็ใส่เป็น android ตามคู่มือเค้า ให้เราเอาค่าที่ต่อจาก SHA1: 5D:0A:34:EF:8B:AC:37:42:21:80.......  เอาอันนี้แหละไปลงทะเบียนต่อขั้นตอนต่อไป
  • ใส่ค่าครบแล้วเลือก Register app
  • ขั้นตอนต่อไป Download google-services.json
  • นำไปใส่ Flutter project เราที่นี่เลย
  • ขั้นตอนต่อไปแก้ไฟล์ build.gradle 2 พาธ ตาม doc เค้า (ของ Flutter projectname/android[projectname]/build.gradle และ projectname/android[projectname]/app/build.gradle)

  • ที่ build.gradle ระดับ project เพิ่มคอนฟิกประมาณ 1 บรรทัด ถ้าไม่มีอะไรผิดปกตินะ
  • classpath 'com.google.gms:google-services:4.3.3'
  • ที่ build.gradle ระดับ app เพิ่มประมาณ 2 บรรทัด
  • apply plugin: 'com.google.gms.google-services'
  • อีกบรรทัดประมาณนี้
  • implementation 'com.google.firebase:firebase-analytics:17.2.2'
  • ตาม doc เค้าบอกให้กด Sync now บน bar ของ IDE แต่ไม่เห็นมีเลย งั้นเราก็ Next

  • ให้เราทำการ Run Flutter project ของเรา

  • จากนั้นกด Next ระบบจะตรวจสอบความถูกต้อง

  • เมื่อเรารันระบบแล้ว มันจะ Sync กับ Firebase เอง สถานะของการตรวจสอบจะเป็น 
  • Congratulations, you've successfully added Firebase to your app!
  • Flutter project พร้อมใช้งาน Firebase service แล้ว
Ref
  • https://www.youtube.com/watch?v=3rMM4adtCJk