پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP
پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP

پوش نوتیفیکیشن اندروید با استفاده از Firebase Cloud Messaging) FCM & PHP)

اخیراً، گوگل از سیستم پیام‌رسانی ابری‌گوگل (GCM) به سامانه ی پیام‌رسانی ابری فایربیس (FCM) منتقل شده است. مشابه GCM، FCM یک راه حل پیام‌رسانی چند پلتفرمی است که به شما امکان ارسال پیام را می‌دهد. FCM کاملاً رایگان و نامحدود است. در این مقاله ما ویژگیهایFCM  را مطالعه خواهیم کرد و یک اپلیکیشن ساده خواهیم ساخت. همچنین خواهیم دید که چطور فایربیس را با بک‌اند پروژه یکپارچه کنیم، تا بتوانید از سرور پیام ارسال کنیم. با مقاله پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP و سیستم پیام‌رسانی ابری‌گوگل تیک4 همراه باشید.

  1. انواع پیامهای فایربیس

با استفاده از  FCM می‌توانید سه نوع پیام ارسال کنید که عبارتند از: پیام اعلان(Notification Message)، پیام داده (Data Message) و پیام با هر دوی اعلان و دیتا پی‌لود (Data payload)

1.1 پیام اعلان

پیام اعلان با خود SDK ی فایربیس مدیریت می‌گردد. به طور معمول پیام اعلان شامل عنوان، پیام، آیکون و … می‌شود. این پیامها ممکن است از طریق رابط کاربری کنسول فایربیس ارسال شوند. با ارسال این نوع پیامها شما کنترل زیادی برروی اعلان ها نخواهید داشت. اعلان به طور خودکار وقتی که برنامه در پس زمینه در حال اجرا است نمایش داده خواهد شد.

برای ارسال اعلان پیام، شما باید از کلید notification در داده‌های Json استفاده کنید. یک نمونه از اعلانات مربوط به پیام در زیر نشان داده شده است.

{
    "to": "e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak...",
    "notification": {
        "body": "Cool offers. Get them before expiring!",
        "title": "Flat 80% discount",
        "icon": "appicon"
    }
}

1.2 پیام داده

پیام داده باید با برنامه‌ی اندروید مدیریت شود. شما می‌توانید این نوع پیام را در صورتی که بخواهید داده‌های اضافی همراه اعلان ارسال کنید، اضافه کنید. اما ارسال این پیامها از طریق کنسول فایربیس ممکن نیست. برای ارسال اعلان با استفاده از api ی فایربیس، احتیاج به منطق سمت سرور دارید. وقتی که می خواهید این پیام را ارسال کنید باید از کلید data  استفاده کنید

یک نمونه از Json پیام داده در زیر آورده شده است.

{
   "to" : "e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak...",
   "data" : {
     "name" : "LG LED TV S15",
     "product_id" : "123",
     "final_price" : "2500"
   }
 }

1.3 پیامهایی با هردوی اعلان و Data loaded

همچنین یک پیام هم شامل اعلان و هم داده‌ی پی‌لود باشد. وقتی که این نوع پیامها فرستاده می شوند، بسته به وضعیت برنامه (اجرا در پس زمینه یا پیش زمینه) به دو صورت قابل مدیریت است. برای این پیامها ما می توانیم از کلیدهای notification  و  dataاستفاده کنیم

وقتی که در پس زمینه در حال اجرا است- برنامه‌ها اعلانات پی‌لود را دریافت می‌کنند در قسمت اعلانات، و داده ی پی‌لود فقط وقتی که کاربر برروی اعلان ضربه می زند مدیریت می شود. وقتی که در پیش زمینه است- برنامه یک شیءپیام با هر دو پی‌لود دردسترس دریافت می‌کند. یک مورد از پیام اعلان و داده‌ی پی‌لود مورد زیر است. با ادامه مقاله پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP همراه ما باشید.

{
    "to" : "e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak...",
    "notification": {
        "body": "Cool offers. Get them before expiring!",
        "title": "Flat 80% discount",
        "icon": "appicon"
    },
    "data" : {
     "name" : "LG LED TV S15",
     "product_id" : "123",
     "final_price" : "2500"
   }
}
  1. هدف‌گیری پیام

زمانی که با فایربیس پیام ارسال می‌کنید، شما می‌توانید مخاطبین هدف را انتخاب کنید. شما هم می‌توانید  به کاربر تنها ارسال کنید و هم به یک گروه کاربر با یک اسم موضوع (topic name)

  • ارسال به یک کاربر

وقتی هدف یک کاربر است، شناسه ی ثبت نام فایربیس (firebase registration id) برای تشخیص دستگاه مورد نظر استفاده می‌شود. Reg id باید در فیلد to  از فایل Json حتماً ذکر شود.

{
  "to": "e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak...",
  "data": {
    "message": "This is a Firebase Cloud Messaging Topic Message!",
   }
}

2.2 پیام رسانی موضوعی

پیامرسانی موضوعی وقتی که تعدادی از کاربران هدف هستند مفید است. برای این کاربران باید به موضوع فایربیس  مشترک شوند.  به طور مثال: وقتی که می‌خواهید به تمام کاربرانی که علاقمند به اخبار هستند پیام بدهید شما می‌توانید یک موضوع (topic)  به نام اخبار ایجاد کنید و به موضوع(تاپیک) نیوز اعلان ارسال کنید. فرمت درخواست پیام موضوعی در زیر آورده شده است. در فیلد to شما باید به نام موضوع (تاپیک نیم) اشاره کنید. با ادامه مقاله پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP همراه ما باشید.

{
  "to": "/topics/news",
  "data": {
    "message": "This is a Firebase Cloud Messaging Topic Message!",
   }
}

3.  یکپارچه سازی با ابر پیام رسانی فایربیس(firebase cloud messaging)

ما امیدواریم اطلاعات بالا مرور خوبی بر ویژگیهای فایربیس و امکاناتی که آنها فراهم می کنند، باشد. حالا ما می خواهیم یک برنامه‌ی ساده بسازیم که هم پیامهای کنسول فایربیس و هم پیامهای پی اچ پی را دریافت کند.

  1. اول باید به آدرس https://firebase.google.com/ بروید و برای دسترسی به کنسول یک حساب کاربری بسازید. بعد از اینکه به کنسول دسترسی پیدا کردید با ایجاد پروژه‌تان شروع کنید.
  2. نام پکیج پروژه‌تان را که می‌خواهید با فایربیس یکپارچه کنید تنظیم کنید(برای ما tik4.firebasenotifications است) . اینجا فایل google-services.json وقتی که روی دکمه ی add برنامه کلیک می‌کنید دانلود می‌شود.

سیستم پیام‌رسانی ابری‌گوگل

  1. از قسمت File New Project یک پروژه‌ی جدید در اندروید استادیو ایجاد کنید. زمانی که جزئیات مربوط به پروژه را پر می‌کنید از همان نامی استفاده کنید که در کنسول فایربیس استفاده کرده بودید که در مورد ما tik4.firebasenotifications است.
  2. فایل google-services.json را در داخل پوشه‌ی app پروژه وارد کنید. این قدم بسیار مهم است چون بدون آن پروژه‌ی شما ایجاد نخواهد شد.
build.gradle
dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0-rc1'
        classpath 'com.google.gms:google-services:3.0.0'
 
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
  1. فایل app/build.gradle را باز کنید و وابستگی‌های مربوط به firebase messaging را اضافه کنید. در انتهای فایل apply plugin: ‘com.google.gms.google-services’ را اضافه کنید
app/build.gradle
dependencies {
    compile 'com.google.firebase:firebase-messaging:9.6.0'
}
 
apply plugin: 'com.google.gms.google-services'
  1. چهار پکیج به نام‌های activity، app، service، utils، زیر پوشه‌ی اصلی پروژه ایجاد کنید. در زیر ساختار و فایل‌های مورد نیاز پروژه آمده است.

…pic…

  1. فایل notification.mp3 را دانلود و در پوشه‌ی res raw قرار دهید. این گام اختیاری است، برای زمانی که می‌خواهید که در هنگام دریافت اعلان صدای خاصّی را پخش نمایید(به طور سفارشی).
  2. کلاسی با نام Config.java در پکیج app ایجاد کنید. این کلاس شامل تمام مقادیر ثابتی است که در برنامه استفاده می‌کنیم.
Config.java
package tik4.firebasenotifications.app;
 
public class Config {
 
    // global topic to receive app wide push notifications
    public static final String TOPIC_GLOBAL = "global";
 
    // broadcast receiver intent filters
    public static final String REGISTRATION_COMPLETE = "registrationComplete";
    public static final String PUSH_NOTIFICATION = "pushNotification";
 
    // id to handle the notification in the notification tray
    public static final int NOTIFICATION_ID = 100;
    public static final int NOTIFICATION_ID_BIG_IMAGE = 101;
 
    public static final String SHARED_PREF = "ah_firebase";
}
  1. کلاسی به نام NotificationUtils.java در زیر پکیج utils ایجاد کنید. این کلاس شامل توابع ضروری برای نمایش پیامها (با عنوان، پیام، عکس و زمان) در قسمت اعلانات است.
NotificationUtils.java
package tik4.firebasenotifications.util;
 
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.text.Html;
import android.text.TextUtils;
import android.util.Patterns;
 
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
 
import tik4.firebasenotifications.R;
import tik4.firebasenotifications.app.Config;
 
/**
 * Created by Ravi on 31/03/15.
 */
public class NotificationUtils {
 
    private static String TAG = NotificationUtils.class.getSimpleName();
 
    private Context mContext;
 
    public NotificationUtils(Context mContext) {
        this.mContext = mContext;
    }
 
    public void showNotificationMessage(String title, String message, String timeStamp, Intent intent) {
        showNotificationMessage(title, message, timeStamp, intent, null);
    }
 
    public void showNotificationMessage(final String title, final String message, final String timeStamp, Intent intent, String imageUrl) {
        // Check for empty push message
        if (TextUtils.isEmpty(message))
            return;
 
 
        // notification icon
        final int icon = R.mipmap.ic_launcher;
 
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        final PendingIntent resultPendingIntent =
                PendingIntent.getActivity(
                        mContext,
                        0,
                        intent,
                        PendingIntent.FLAG_CANCEL_CURRENT
                );
 
        final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
                mContext);
 
        final Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
                + "://" + mContext.getPackageName() + "/raw/notification");
 
        if (!TextUtils.isEmpty(imageUrl)) {
 
            if (imageUrl != null && imageUrl.length() > 4 && Patterns.WEB_URL.matcher(imageUrl).matches()) {
 
                Bitmap bitmap = getBitmapFromURL(imageUrl);
 
                if (bitmap != null) {
                    showBigNotification(bitmap, mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
                } else {
                    showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
                }
            }
        } else {
            showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
            playNotificationSound();
        }
    }
 
 
    private void showSmallNotification(NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
 
        NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
 
        inboxStyle.addLine(message);
 
        Notification notification;
        notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
                .setAutoCancel(true)
                .setContentTitle(title)
                .setContentIntent(resultPendingIntent)
                .setSound(alarmSound)
                .setStyle(inboxStyle)
                .setWhen(getTimeMilliSec(timeStamp))
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
                .setContentText(message)
                .build();
 
        NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(Config.NOTIFICATION_ID, notification);
    }
 
    private void showBigNotification(Bitmap bitmap, NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
        NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();
        bigPictureStyle.setBigContentTitle(title);
        bigPictureStyle.setSummaryText(Html.fromHtml(message).toString());
        bigPictureStyle.bigPicture(bitmap);
        Notification notification;
        notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
                .setAutoCancel(true)
                .setContentTitle(title)
                .setContentIntent(resultPendingIntent)
                .setSound(alarmSound)
                .setStyle(bigPictureStyle)
                .setWhen(getTimeMilliSec(timeStamp))
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
                .setContentText(message)
                .build();
 
        NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(Config.NOTIFICATION_ID_BIG_IMAGE, notification);
    }
 
    /**
     * Downloading push notification image before displaying it in
     * the notification tray
     */
    public Bitmap getBitmapFromURL(String strURL) {
        try {
            URL url = new URL(strURL);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            Bitmap myBitmap = BitmapFactory.decodeStream(input);
            return myBitmap;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
 
    // Playing notification sound
    public void playNotificationSound() {
        try {
            Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
                    + "://" + mContext.getPackageName() + "/raw/notification");
            Ringtone r = RingtoneManager.getRingtone(mContext, alarmSound);
            r.play();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    /**
     * Method checks if the app is in background or not
     */
    public static boolean isAppIsInBackground(Context context) {
        boolean isInBackground = true;
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
            List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
                if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    for (String activeProcess : processInfo.pkgList) {
                        if (activeProcess.equals(context.getPackageName())) {
                            isInBackground = false;
                        }
                    }
                }
            }
        } else {
            List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
            ComponentName componentInfo = taskInfo.get(0).topActivity;
            if (componentInfo.getPackageName().equals(context.getPackageName())) {
                isInBackground = false;
            }
        }
 
        return isInBackground;
    }
 
    // Clears notification tray messages
    public static void clearNotifications(Context context) {
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.cancelAll();
    }
 
    public static long getTimeMilliSec(String timeStamp) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = format.parse(timeStamp);
            return date.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }
}
  1. یک کلاس با نام MyFirebaseInstanceIDService.java زیر پکیج service ایجاد کنید. این کلاس آی دی ثبت نام فایربیس که برای هر برنامه منحصر به فرد است را دریافت می‌کند. این آی دی ثبت نام وقتی که می خواهید به یک دستگاه پیام ارسال کنید مورد نیاز است. شما می‌توانید این توکن را به برنامه‌ی سرور ارسال کنید تا بعداً به دسگاه اعلان ارسال کند.

متد onTokenRefresh وقتی که آی دی ثبت نام فایربیس تغییر می‌کند فراخوانی می‌شود.

متد storeRegIdInPref()  آی دی ثبت نام را در shared preferences ذخیره می‌کند.

LocalBroadcastManager مدیریت کننده انتشار، reg id را برای تمام اکتیویتی‌های گوش کننده منتشر می‌کند.

MyFirebaseInstanceIDService.java
package tik4.firebasenotifications.service;
 
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
 
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
 
import tik4.firebasenotifications.app.Config;
 
/**
 * Created by tik4 on 08/08/16.
 * www.androidhive.info
 */
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
    private static final String TAG = MyFirebaseInstanceIDService.class.getSimpleName();
 
    @Override
    public void onTokenRefresh() {
        super.onTokenRefresh();
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
 
        // Saving reg id to shared preferences
        storeRegIdInPref(refreshedToken);
 
        // sending reg id to your server
        sendRegistrationToServer(refreshedToken);
 
        // Notify UI that registration has completed, so the progress indicator can be hidden.
        Intent registrationComplete = new Intent(Config.REGISTRATION_COMPLETE);
        registrationComplete.putExtra("token", refreshedToken);
        LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
    }
 
    private void sendRegistrationToServer(final String token) {
        // sending gcm token to server
        Log.e(TAG, "sendRegistrationToServer: " + token);
    }
 
    private void storeRegIdInPref(String token) {
        SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF, 0);
        SharedPreferences.Editor editor = pref.edit();
        editor.putString("regId", token);
        editor.commit();
    }
}
  1. کلاس دیگری با نام MyFirebaseMessagingService.java زیر پکیج service ایجاد کنید. این کلاس پیامهای فایربیس را با متد onMessageReceived() دریافت می‌کند.

>وقتی که پیام با نوع اعلان ارسال شد، وقتی که که برنامه در پس زمینه در حال اجرا است، فایربیس به طور خودکار اعلان را نمایش می‌دهد. اگر برنامه در پیش زمینه در حال اجرا باشد متد handleNotification()  پیام اعلان را مدیریت می‌کند

>وقتی که پیام با نوع داده ارسال شد، متد   handleDataMessage() برای مدیریت پی‌لود بدون در نظر گرفتن وضعیت برنامه(از نظر اجرا در پس زمینه یا پیش زمینه)

> LocalBroadcastManager  برای انتشار پیام بین تمام اکتیویتی‌هایی که برای دریافت برودکست ثبت نام کرده‌اند.

MyFirebaseMessagingService.java
package tik4.firebasenotifications.service;
 
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
 
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
 
import org.json.JSONException;
import org.json.JSONObject;
 
import tik4.firebasenotifications.activity.MainActivity;
import tik4.firebasenotifications.app.Config;
import tik4.firebasenotifications.util.NotificationUtils;
 
/**
 * Created by tik4 on 08/08/16.
 * www.androidhive.info
 */
public class MyFirebaseMessagingService extends FirebaseMessagingService {
 
    private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
 
    private NotificationUtils notificationUtils;
 
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.e(TAG, "From: " + remoteMessage.getFrom());
 
        if (remoteMessage == null)
            return;
 
        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.e(TAG, "Notification Body: " + remoteMessage.getNotification().getBody());
            handleNotification(remoteMessage.getNotification().getBody());
        }
 
        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
            Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
 
            try {
                JSONObject json = new JSONObject(remoteMessage.getData().toString());
                handleDataMessage(json);
            } catch (Exception e) {
                Log.e(TAG, "Exception: " + e.getMessage());
            }
        }
    }
 
    private void handleNotification(String message) {
        if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
            // app is in foreground, broadcast the push message
            Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);
            pushNotification.putExtra("message", message);
            LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
 
            // play notification sound
            NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
            notificationUtils.playNotificationSound();
        }else{
            // If the app is in background, firebase itself handles the notification
        }
    }
 
    private void handleDataMessage(JSONObject json) {
        Log.e(TAG, "push json: " + json.toString());
 
        try {
            JSONObject data = json.getJSONObject("data");
 
            String title = data.getString("title");
            String message = data.getString("message");
            boolean isBackground = data.getBoolean("is_background");
            String imageUrl = data.getString("image");
            String timestamp = data.getString("timestamp");
            JSONObject payload = data.getJSONObject("payload");
 
            Log.e(TAG, "title: " + title);
            Log.e(TAG, "message: " + message);
            Log.e(TAG, "isBackground: " + isBackground);
            Log.e(TAG, "payload: " + payload.toString());
            Log.e(TAG, "imageUrl: " + imageUrl);
            Log.e(TAG, "timestamp: " + timestamp);
 
 
            if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
                // app is in foreground, broadcast the push message
                Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);
                pushNotification.putExtra("message", message);
                LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
 
                // play notification sound
                NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
                notificationUtils.playNotificationSound();
            } else {
                // app is in background, show the notification in notification tray
                Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
                resultIntent.putExtra("message", message);
 
                // check for image attachment
                if (TextUtils.isEmpty(imageUrl)) {
                    showNotificationMessage(getApplicationContext(), title, message, timestamp, resultIntent);
                } else {
                    // image is present, show notification with image
                    showNotificationMessageWithBigImage(getApplicationContext(), title, message, timestamp, resultIntent, imageUrl);
                }
            }
        } catch (JSONException e) {
            Log.e(TAG, "Json Exception: " + e.getMessage());
        } catch (Exception e) {
            Log.e(TAG, "Exception: " + e.getMessage());
        }
    }
 
    /**
     * Showing notification with text only
     */
    private void showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {
        notificationUtils = new NotificationUtils(context);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        notificationUtils.showNotificationMessage(title, message, timeStamp, intent);
    }
 
    /**
     * Showing notification with text and image
     */
    private void showNotificationMessageWithBigImage(Context context, String title, String message, String timeStamp, Intent intent, String imageUrl) {
        notificationUtils = new NotificationUtils(context);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        notificationUtils.showNotificationMessage(title, message, timeStamp, intent, imageUrl);
    }
}
  1. AndroidManifest.xml را باز کنید و دو سرویس MyFirebaseMessagingService و MyFirebaseInstanceIDService فایربیس را اضافه کنید
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="tik4.firebasenotifications">
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".activity.MainActivity"
            android:label="@string/title_main_activity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
 
        <!-- Firebase Notifications -->
        <service android:name=".service.MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
 
        <service android:name=".service.MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>
        <!-- ./Firebase Notifications -->
    </application>
</manifest>
  1. در نهایت ما نیاز داریم اکتیویتی اصلی را تغییر دهیم برای نمایش پیامهای که وارد می‌شوند در صفحه. فایل لایوت اکتیویتی اصلی activity_main.xml را باز کنید و لایوت را به صورت زیر تغیر دهید. با ادامه مقاله پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP و سیستم پیام‌رسانی ابری‌گوگل همراه ما باشید.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="tik4.firebasenotifications.activity.MainActivity">
 
    <TextView
        android:id="@+id/txt_push_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp"
        android:gravity="center_horizontal"
        android:textColor="@color/colorPrimary"
        android:textSize="26dp" />
 
    <TextView
        android:id="@+id/txt_reg_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" />
</RelativeLayout>
  1. فایل MainActivity.java را باز کنید و تغییرات ضروری زیر را در آن انجام دهید. اینجا در متد onResume() دریافت کننده‌ی برودکست را ثبت می‌کنیم. بنابراین این اکتیویتی پوش مسیج و آی دی ثبت نام را دریافت می کند.

displayFirebaseRegId() آی دی ثبت نام فایربیس از (SharedPrefrences) واکشی می‌کند و  آن را برروی صفحه نمایش نمایش می‌دهد. این فقط برای استفاده شما مطرح شد، ما در هیچ جای این برنامه از آی دی ثبت نام استفاده نمی‌کنیم.

مشترک شدن در یک موضوع

وقتی که می‌خواهید در یک موضوع مشترک شوید، تابعsubscribeToTopic()  را می‌توانید استفاده کنید. وقتی که برنامه ی مشتری به یک موضوع جدید مشترک می شود(موردی که تا کنون در پروژه ی فایربیس شما وجود نداشته است)، یک موضوع جدید با آن نام در fcm  ایجاد شود و هر مشتری بعد از آن می تواند مشترک آن شود.

FirebaseMessaging.getInstance().subscribeToTopic('news');

خارج شدن از اشتراک یک موضوع

به طور مشابه، مشتری با صدا زدن متد unsubscribeFromTopic()  می‌تواند از اشتراک یک موضوع خارج شود.

FirebaseMessaging.getInstance().unsubscribeFromTopic('news');
MainActivity.java
package tik4.firebasenotifications.activity;
 
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
 
import com.google.firebase.messaging.FirebaseMessaging;
 
import tik4.firebasenotifications.R;
import tik4.firebasenotifications.app.Config;
import tik4.firebasenotifications.util.NotificationUtils;
 
public class MainActivity extends AppCompatActivity {
 
    private static final String TAG = MainActivity.class.getSimpleName();
    private BroadcastReceiver mRegistrationBroadcastReceiver;
    private TextView txtRegId, txtMessage;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        txtRegId = (TextView) findViewById(R.id.txt_reg_id);
        txtMessage = (TextView) findViewById(R.id.txt_push_message);
 
        mRegistrationBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
 
                // checking for type intent filter
                if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
                    // gcm successfully registered
                    // now subscribe to `global` topic to receive app wide notifications
                    FirebaseMessaging.getInstance().subscribeToTopic(Config.TOPIC_GLOBAL);
 
                    displayFirebaseRegId();
 
                } else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
                    // new push notification is received
 
                    String message = intent.getStringExtra("message");
 
                    Toast.makeText(getApplicationContext(), "Push notification: " + message, Toast.LENGTH_LONG).show();
 
                    txtMessage.setText(message);
                }
            }
        };
 
        displayFirebaseRegId();
    }
 
    // Fetches reg id from shared preferences
    // and displays on the screen
    private void displayFirebaseRegId() {
        SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF, 0);
        String regId = pref.getString("regId", null);
 
        Log.e(TAG, "Firebase reg id: " + regId);
 
        if (!TextUtils.isEmpty(regId))
            txtRegId.setText("Firebase Reg Id: " + regId);
        else
            txtRegId.setText("Firebase Reg Id is not received yet!");
    }
 
    @Override
    protected void onResume() {
        super.onResume();
 
        // register GCM registration complete receiver
        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(Config.REGISTRATION_COMPLETE));
 
        // register new push message receiver
        // by doing this, the activity will be notified each time a new message arrives
        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(Config.PUSH_NOTIFICATION));
 
        // clear the notification area when the app is opened
        NotificationUtils.clearNotifications(getApplicationContext());
    }
 
    @Override
    protected void onPause() {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
        super.onPause();
    }
}

حالا ما یکپارچه سازی با پیامرسانی ابری فایربیس را کامل کردیم. برای بررسی(صحت) آن، پروژه را اجرا کنید. با اجرای برنامه باید آی دی ثبت نام فایربیس را در صفحه ببینید. و همچنین شما باید بتوانید آی دی ثبت نام را در logCat  بیابید. با ادامه مقاله پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP و سیستم پیام‌رسانی ابری‌گوگل همراه ما باشید.

پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP

  1. ارسال پیام از کنسول فایربیس

حالا می خواهیم اولین پیام را از کنسول فایربیس ارسال کنیم. بروید به کنسول فایربیس و برروی  Notifications در منوی سمت چپ کلیک کنید. یک رابط به شما ارائه خواهد شد که می توانید در آن پیام تایپ کنید targeting را انتخاب و پیام را ارسال کنید.  

پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP

  1. ارسال پیام از بک اند پی اچ پی

ارسال  پیام از طریق کنسول فایربیس همیشه و برای بسیاری از برنامه‌ها راه حل خوبی نیست. بسیاری از برنامه‌ها نیاز به این دارند که در صورت رخداد یک رویداد خاص به صورت خودکار کاربر مطلع شود که با استفاده از کنسول فایربیس این کار ممکن نیست. برای غلبه بر این مشکل نیاز به یکپارچه‌سازی api  ی فایربس با بک اند سرور شما وجود دارد.

بیاید با هم یک پروژه‌ی ساده‌ی پی اچ پی برای ارسال پیام از بک اند بسازیم. ما اینطور فرض می‌کنیم که شما دانش ابتدائیه کار با پی اچ پی و wamp  را دارید. با ادامه مقاله پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP و سیستم پیام‌رسانی ابری‌گوگل همراه ما باشید.

5.1 دریافت کلید ای پی آی از سرور فایربیس

فایربیس یک کلید سرور ای پی آی (Server api key) برای تشخیص برنامه‌ی فایربیس شما ایجاد می‌کند. برای گرفتن این کلید به کنسول فایربیستان بروید، پروژه ی مربوطه را انتخاب کنید و به قسمت settings بروید، تب Cloud Messaging  را انتخاب کنید و کلید سرور (Server key) را کپی کنید.

  1. به پوشه‌ی وَمپ تان بروید و یک پوشه‌ی جدید به نام firebase درون htdocs یا www درست کنید. اینجا ما کلید ای‌پی‌آی سرور فایربیس را برای ارسال درخواست به endpoint فایربیس تعریف می‌کنیم.
  2. یک فایل به نام config.php ایجاد کنید و کد زیر را به آن اضافه کنید. اینجا ما کلید سرور فایربیس را برای ارسال درخواست به اندپوینت فایربیس تعریف می‌کنیم.
config.php
<?php
 
// Firebase API Key
define('FIREBASE_API_KEY', 'AAAA4qJeE5A:APA91bGct--6lGrYwgBC8iz5reyx4qPUB7ByXX8MwC7Vcs8u...');
  1. یک فایل با نام push.php ایجاد کنید. این کلاس Json پوش نوتیفیکیشن که برای ارسال به فایربیس نیاز است را درست می‌کند.
push.php
<?php
 
/**
 * @tik4
 * @link URL Tutorial link
 */
class Push {
 
    // push message title
    private $title;
    private $message;
    private $image;
    // push message payload
    private $data;
    // flag indicating whether to show the push
    // notification or not
    // this flag will be useful when perform some opertation
    // in background when push is recevied
    private $is_background;
 
    function __construct() {
         
    }
 
    public function setTitle($title) {
        $this->title = $title;
    }
 
    public function setMessage($message) {
        $this->message = $message;
    }
 
    public function setImage($imageUrl) {
        $this->image = $imageUrl;
    }
 
    public function setPayload($data) {
        $this->data = $data;
    }
 
    public function setIsBackground($is_background) {
        $this->is_background = $is_background;
    }
 
    public function getPush() {
        $res = array();
        $res['data']['title'] = $this->title;
        $res['data']['is_background'] = $this->is_background;
        $res['data']['message'] = $this->message;
        $res['data']['image'] = $this->image;
        $res['data']['payload'] = $this->data;
        $res['data']['timestamp'] = date('Y-m-d G:i:s');
        return $res;
    }
 
}
  1. فایلی به نام firebase.php ایجاد کنید و کد زیر را به آن اضافه کنید. این کلاس شامل توابع مورد نیاز برای ارسال پیام به api فایربیس با ساختن یک درخواست CURL است.
<?php
 
/**
 * @tik4
 * @link URL Tutorial link
 */
class Firebase {
 
    // sending push message to single user by firebase reg id
    public function send($to, $message) {
        $fields = array(
            'to' => $to,
            'data' => $message,
        );
        return $this->sendPushNotification($fields);
    }
 
    // Sending message to a topic by topic name
    public function sendToTopic($to, $message) {
        $fields = array(
            'to' => '/topics/' . $to,
            'data' => $message,
        );
        return $this->sendPushNotification($fields);
    }
 
    // sending push message to multiple users by firebase registration ids
    public function sendMultiple($registration_ids, $message) {
        $fields = array(
            'to' => $registration_ids,
            'data' => $message,
        );
 
        return $this->sendPushNotification($fields);
    }
 
    // function makes curl request to firebase servers
    private function sendPushNotification($fields) {
         
        require_once __DIR__ . '/config.php';
 
        // Set POST variables
        $url = 'https://fcm.googleapis.com/fcm/send';
 
        $headers = array(
            'Authorization: key=' . FIREBASE_API_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 temporarly
        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);
 
        return $result;
    }
}
?>
  1. در نهایت فایلی به نام index.php بسازید و کد زیر را به آن اضافه کنید. با این کار یک رابط کاربری ساده برای دریافت ورودی و ارسال اعلان به دستگاه اندروید ایجاد کرده‌اید.
index.php
<html>
    <head>
        <title>AndroidHive | Firebase Cloud Messaging</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="shortcut icon" href="//www.gstatic.com/mobilesdk/160503_mobilesdk/logo/favicon.ico">
        <link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.6.0/pure-min.css">
 
        <style type="text/css">
            body{
            }
            div.container{
                width: 1000px;
                margin: 0 auto;
                position: relative;
            }
            legend{
                font-size: 30px;
                color: #555;
            }
            .btn_send{
                background: #00bcd4;
            }
            label{
                margin:10px 0px !important;
            }
            textarea{
                resize: none !important;
            }
            .fl_window{
                width: 400px;
                position: absolute;
                right: 0;
                top:100px;
            }
            pre, code {
                padding:10px 0px;
                box-sizing:border-box;
                -moz-box-sizing:border-box;
                webkit-box-sizing:border-box;
                display:block; 
                white-space: pre-wrap;  
                white-space: -moz-pre-wrap; 
                white-space: -pre-wrap; 
                white-space: -o-pre-wrap; 
                word-wrap: break-word; 
                width:100%; overflow-x:auto;
            }
 
        </style>
    </head>
    <body>
        <?php
        // Enabling error reporting
        error_reporting(-1);
        ini_set('display_errors', 'On');
 
        require_once __DIR__ . '/firebase.php';
        require_once __DIR__ . '/push.php';
 
        $firebase = new Firebase();
        $push = new Push();
 
        // optional payload
        $payload = array();
        $payload['team'] = 'India';
        $payload['score'] = '5.6';
 
        // notification title
        $title = isset($_GET['title']) ? $_GET['title'] : '';
         
        // notification message
        $message = isset($_GET['message']) ? $_GET['message'] : '';
         
        // push type - single user / topic
        $push_type = isset($_GET['push_type']) ? $_GET['push_type'] : '';
         
        // whether to include to image or not
        $include_image = isset($_GET['include_image']) ? TRUE : FALSE;
 
 
        $push->setTitle($title);
        $push->setMessage($message);
        if ($include_image) {
            $push->setImage('https://api.androidhive.info/images/minion.jpg');
        } else {
            $push->setImage('');
        }
        $push->setIsBackground(FALSE);
        $push->setPayload($payload);
 
 
        $json = '';
        $response = '';
 
        if ($push_type == 'topic') {
            $json = $push->getPush();
            $response = $firebase->sendToTopic('global', $json);
        } else if ($push_type == 'individual') {
            $json = $push->getPush();
            $regId = isset($_GET['regId']) ? $_GET['regId'] : '';
            $response = $firebase->send($regId, $json);
        }
        ?>
        <div class="container">
            <div class="fl_window">
                <div><img src="https://api.androidhive.info/images/firebase_logo.png" width="200" alt="Firebase"/></div>
                <br/>
                <?php if ($json != '') { ?>
                    <label><b>Request:</b></label>
                    <div class="json_preview">
                        <pre><?php echo json_encode($json) ?></pre>
                    </div>
                <?php } ?>
                <br/>
                <?php if ($response != '') { ?>
                    <label><b>Response:</b></label>
                    <div class="json_preview">
                        <pre><?php echo json_encode($response) ?></pre>
                    </div>
                <?php } ?>
 
            </div>
 
            <form class="pure-form pure-form-stacked" method="get">
                <fieldset>
                    <legend>Send to Single Device</legend>
 
                    <label for="redId">Firebase Reg Id</label>
                    <input type="text" id="redId" name="regId" class="pure-input-1-2" placeholder="Enter firebase registration id">
 
                    <label for="title">Title</label>
                    <input type="text" id="title" name="title" class="pure-input-1-2" placeholder="Enter title">
 
                    <label for="message">Message</label>
                    <textarea class="pure-input-1-2" rows="5" name="message" id="message" placeholder="Notification message!"></textarea>
 
                    <label for="include_image" class="pure-checkbox">
                        <input name="include_image" id="include_image" type="checkbox"> Include image
                    </label>
                    <input type="hidden" name="push_type" value="individual"/>
                    <button type="submit" class="pure-button pure-button-primary btn_send">Send</button>
                </fieldset>
            </form>
            <br/><br/><br/><br/>
 
            <form class="pure-form pure-form-stacked" method="get">
                <fieldset>
                    <legend>Send to Topic `global`</legend>
 
                    <label for="title1">Title</label>
                    <input type="text" id="title1" name="title" class="pure-input-1-2" placeholder="Enter title">
 
                    <label for="message1">Message</label>
                    <textarea class="pure-input-1-2" name="message" id="message1" rows="5" placeholder="Notification message!"></textarea>
 
                    <label for="include_image1" class="pure-checkbox">
                        <input id="include_image1" name="include_image" type="checkbox"> Include image
                    </label>
                    <input type="hidden" name="push_type" value="topic"/>
                    <button type="submit" class="pure-button pure-button-primary btn_send">Send to Topic</button>
                </fieldset>
            </form>
        </div>
    </body>
</html>
  1. از آدرس http://localhost/firebase به پروژه دسترسی دارید. (اگر آپاچی شما در یک پورت خاص حال اجرا باشد، با استفاده از شماره‌ی آن پورت خاص به پروژه دسترسی پیدا می‌کنید)

امیدواریم از مقاله پوش نوتیفیکیشن اندروید با استفاده از FCM & PHP و سیستم پیام‌رسانی ابری‌گوگل بهره کافی را برده باشید. از قسمت دیدگاه ها باما در ارتباط باشید.

دیدگاه‌ خود را بیان کنید

اشتراک در
اطلاع از
guest

این سایت از اکیسمت برای کاهش هرزنامه استفاده می کند. بیاموزید که چگونه اطلاعات دیدگاه های شما پردازش می‌شوند.

0 نظرات
بازخورد (Feedback) های اینلاین
مشاهده همه دیدگاه ها
سبد خرید0
There are no products in the cart!