Android:将FCM通知保存到Room DB

时间:2019-04-19 05:13:15

标签: android firebase-cloud-messaging android-sqlite android-room android-mvvm

我正在使用Firebase FCM来获取通知。我希望如果收到通知,该通知应存储在我的RoomDatabase中。稍后,当用户打开应用程序时,所有通知都将显示在通知部分。

我正在使用MVVM,我试图通过 ViewModel 保存,但是它不起作用。这是我目前的代码。

public class MessagingService extends FirebaseMessagingService {

    @Override
    public void onNewToken(String s) {
        super.onNewToken(s);
        Log.d("MessagingService", s);
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        // Check if message contains a notification payload.

        if (remoteMessage.getData().isEmpty()){
            showNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
        } else {
            showNotification(remoteMessage.getData());
        }

    }

    private void showNotification(Map<String, String> data) {


        Bitmap bitmap;

        String title = data.get("title").toString();
        String body = data.get("body").toString();
        String imageUri = data.get("image").toString();
        String TrueOrFalse = data.get("AnotherActivity").toString();

        bitmap = getBitmapfromUrl(imageUri);

        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.putExtra("AnotherActivity", TrueOrFalse);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

       // LibraryViewModel libraryViewModel = ViewModelProviders.of(pendingIntent.get).get(HomeViewModel.class);


        //Notification FCM
        String NOTIFICATION_CHANNEL_ID = "vedicaim.com";

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "ArticleNotification",
                    NotificationManager.IMPORTANCE_DEFAULT);

            notificationChannel.setDescription("VedicAim Channel");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.BLUE);
            notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
            notificationChannel.enableLights(true);
            notificationManager.createNotificationChannel(notificationChannel);

        }

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setDefaults(Notification.DEFAULT_ALL)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.splash_logo)
                .setContentTitle(title)
                .setContentText(body)
                .setSound(defaultSoundUri)
                .setContentInfo("Info")
                .setContentIntent(pendingIntent);

        notificationManager.notify(new Random().nextInt(), notificationBuilder.build());

        FirebaseMessaging.getInstance().subscribeToTopic("article")
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        String msg = "Successfull";
                        if (!task.isSuccessful()) {
                            msg = "Failed";
                        }
                        Log.d("MessagingService", msg);
                    }
                });


    }

    private void showNotification(String title, String body) {
        //Notification FCM
        String NOTIFICATION_CHANNEL_ID = "vedicaim.com";

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "ArticleNotification",
                    NotificationManager.IMPORTANCE_DEFAULT);

            notificationChannel.setDescription("VedicAim Channel");
            notificationChannel.enableLights(true);
            notificationChannel.setLightColor(Color.BLUE);
            notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
            notificationChannel.enableLights(true);
            notificationManager.createNotificationChannel(notificationChannel);

        }

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setDefaults(Notification.DEFAULT_ALL)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.splash_logo)
                .setContentTitle(title)
                .setContentText(body)
                .setContentInfo("Info");

        notificationManager.notify(new Random().nextInt(), notificationBuilder.build());

        FirebaseMessaging.getInstance().subscribeToTopic("article")
                .addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        String msg = "Successfull";
                        if (!task.isSuccessful()) {
                            msg = "Failed";
                        }
                        Log.d("MessagingService", msg);
                    }
                });

    }


    /*
     *To get a Bitmap image from the URL received
     * */
    public Bitmap getBitmapfromUrl(String imageUrl) {
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            Bitmap bitmap = BitmapFactory.decodeStream(input);
            return bitmap;

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;

        }
    }}

2 个答案:

答案 0 :(得分:3)

您可以使用Postman而不是Firebase控制台发送消息。因此,即使应用程序在后台或前台,也始终会调用onMessageReceived()方法。 documentation,然后从Postman发送JSON消息。

You should subscribe your app to an FCM topic

之后,您可以在onMessageReceived()中将消息数据保存到会议室DB。

这是一个例子。我是这样在我的应用中完成的

我的FCMService

public class FCMService extends FirebaseMessagingService {
    private static final String DATABASE_NAME = "db_notification";
    private static int NOTIFICATION_ID = 1;
    private NotificationDatabase notificationDatabase;
    private String body, title, itemId, type;

    @Override
    public void onNewToken(String s) {
        super.onNewToken(s);
    }

    @Override
    public void onMessageReceived(final RemoteMessage remoteMessage) {

        notificationDatabase = Room.databaseBuilder(getApplicationContext(),
                NotificationDatabase.class, DATABASE_NAME)
                .build();

        if (!remoteMessage.getData().isEmpty()) {

            Map<String, String> data = remoteMessage.getData();
            title = data.get("title");
            body = data.get("body");
            itemId = data.get("itemId");
            type = data.get("type");

            Intent intent = new Intent(this, MainActivity.class);
            if (type.equals("review")) {
                intent.putExtra("itemId", itemId);
            }
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);

            //Creating Notification
            Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(this, "2")
                    .setSmallIcon(R.drawable.ic_notifications)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.notification_list))
                    .setContentTitle(title)
                    .setContentText(body)
                    .setAutoCancel(true)
                    .setSound(defaultSoundUri)
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                    .setStyle(new NotificationCompat.BigTextStyle().bigText(body))
                    .setContentIntent(pendingIntent);

            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            if (NOTIFICATION_ID > 1073741824) {
                NOTIFICATION_ID = 0;
            }
            Objects.requireNonNull(notificationManager).notify(NOTIFICATION_ID++, mNotifyBuilder.build());

            //Saving to Room Database
            new Thread(() -> {
                Notification notification = new Notification();
                notification.setNotificationTitle(title);
                notification.setNotificationText(body);
                notification.setItemId(itemId);
                notification.setType(type);
                notificationDatabase.notificationAccess().insertOnlySingleNotification(notification);
            }).start();
        }
    }
}

邮递员的JSON请求

{
    "to" : "/topics/sathyanga",
    "collapse_key" : "type_a",
    "data" : {
        "body" : "Notification Body",
        "title": "Notification Title",
        "type" : "review",//Custom Data
        "itemId" : "Item5"//Custom Data
    }
}

使用这种方式,我们可以确保接收的FCM始终是数据消息。因此,即使应用程序不在前台,它也将运行。

答案 1 :(得分:0)

您必须直接从服务访问数据库。它不是活动或片段,因此您将无法实例化ViewModel。

考虑创建一个单独的存储库单例,它将作为您数据库的访问点。