当应用程序处于后台或关闭状态时,无法将记录从 Firebase 消息服务插入 SQLite 数据库

Unable to insert record into SQLite Database from Firebase Message Service when app is in background or closed state

我正在试用 Firebase 通知。我能够使用 this 文档使通知正常工作。消息已收到,我能够从 MyFirebaseMessagingService 服务 class 中向通知栏发送通知。即使应用程序处于后台或关闭时也会发生这种情况。

我需要的是收集通知中发送的数据并将其插入到 SQLite 数据库中。如果应用程序在前台,我写的代码可以正常工作,但如果它关闭或在后台,它就不起作用。这是我为插页写的内容。

DbHelper dbh=new DbHelper(this,"sample.sqlite",null,1);
SQLiteDatabase sdb=dbh.getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put("id","1");
cv.put("name","testname");
sdb.insert("test",null,cv);
sdb.close();
dbh.close();

感谢对此的任何帮助。提前致谢。

<service android:name=".MyFirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

<service android:name=".MyFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
    </intent-filter>
</service>

public class MyFirebaseMessagingService extends FirebaseMessagingService
{
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        //Displaying data in log
        //It is optional
        Log.i("Tag","inside message" );
        Log.i(StaticInfo.INFO, "From: " + remoteMessage.getFrom());
        Log.i(StaticInfo.INFO, "Notification Message Title  : " + remoteMessage.getNotification().getTitle());
        Log.i(StaticInfo.INFO, "Notification Message Body   : " + remoteMessage.getNotification().getBody());

        insertPromotion();
        sendNotification(remoteMessage.getNotification().getBody());
    }

    private void sendNotification(String messageBody) 
    {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Firebase Push Notification")
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

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

        notificationManager.notify(0, notificationBuilder.build());
    }

    private void insertPromotion() 
    {
        DbHelper dbh = new DbHelper(this, "sample.sqlite", null, 1);
        SQLiteDatabase sdb = dbh.getWritableDatabase();
        ContentValues cv=new ContentValues();
        cv.put("id","1");
        cv.put("name","testname");
        sdb.insert("test", null, cv);
        sdb.close();
        dbh.close();

        Log.i("Tag","db closed");
    }

}

只有当应用程序在前台时,通知才会传送到您的应用程序的 onMessageReceived。当您的应用程序是否处于后台时运行,系统将处理通知并将其显示在系统托盘中。

Firebase documentation 解释为:

Notification message - FCM automatically displays the message to end-user devices on behalf of the client app. Notification messages have a predefined set of user-visible keys.

Data message - Client app is responsible for processing data messages. Data messages have only custom key-value pairs.

由于您希望始终调用您的代码,因此您需要发送数据消息。您无法从 Firebase 控制台发送数据消息。但是,如果您已经从应用服务器发送消息,那么发送数据消息和通知消息的过程是相同的。唯一的区别在于 JSON 结构,其中数据消息没有 notification 对象。来自 documentation on data messages

{
   "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
   "data" : {
     "Nick" : "Mario",
     "body" : "great match!",
     "Room" : "PortugalVSDenmark"
   },
}

要将 onMessgeReceived() 上接收到的数据保存到 SQLite 数据库,即使您的应用程序处于后台(无 activity 运行),您可以执行以下操作:

1) 创建一个扩展 IntentService 的 class,例如:

public class SQLService extends IntentService {
    private final static String MESSAGE_ID = "message_id";

    private MySQLiteDbAdapter mySQLiteAdapter;

    public SQLService() {
        super("test-service");
    }

    @Override
    public void onCreate() {
        super.onCreate();

        // initialize SQLite adapter here using getApplicationContext()
        this.mySQLiteAdapter = new MySQLiteDbAdapter(getApplicationContext());

    }

    @Override
    protected void onHandleIntent(Intent intent) {

        // fetch data to save from intent
        Message message = new Message();
        Message.setMessage_id(intent.getStringExtra(MESSAGE_ID));
        ...
        // save 
        this.mySQLiteAdapter.add(message);

    }
}

2) 从 onMessageReceived() 方法或 Firebase 服务扩展中的方法启动服务 class,例如:

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        if (remoteMessage.getData() != null) {

            Intent intent = new Intent(this, SQLService.class);
            // add data to intent
            intent.putExtra(MESSAGE_ID, remoteMessage.getData().get(MESSAGE_ID));
            ...
            // start the service
            startService(intent);

        }
    }

3) 在您的 AndroidManifest.xml 中注册服务:

<application
  ...
        <service
            android:name=".SQLService"
            android:exported="false"/>
  ...

有关更深入的解释,请参阅 https://guides.codepath.com/android/Starting-Background-Services