Невозможно вставить запись в базу данных SQLite из службы сообщений Firebase, когда приложение находится в фоновом или закрытом состоянии
Я пробую уведомления Firebase. Мне удалось заставить Уведомление работать должным образом, используя эту документацию. Сообщение было получено, и я смог отправить уведомление в панель уведомлений из MyFirebaseMessagingService
класс обслуживания. Это происходит, даже когда приложение находится в фоновом режиме или закрыто.
Мне нужно собрать данные, отправленные в уведомлении, и вставить их в базу данных 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");
}
}
2 ответа
Уведомления будут доставлены в ваше приложение onMessageReceived
только когда приложение находится на переднем плане. Когда приложение работает в фоновом режиме или не работает, система обработает уведомление и отобразит его в системном трее.
Документация Firebase объясняет это как:
Уведомление - FCM автоматически отображает сообщение для устройств конечного пользователя от имени клиентского приложения. Уведомительные сообщения имеют предопределенный набор видимых пользователю ключей.
Сообщение данных - клиентское приложение отвечает за обработку сообщений данных. Сообщения данных имеют только пользовательские пары ключ-значение.
Поскольку вы хотите, чтобы ваш код всегда вызывался, вам нужно будет отправлять сообщения с данными. Вы не можете отправлять сообщения с данными из консоли Firebase. Но если вы уже отправляете сообщения с сервера приложений, процесс отправки сообщений с данными и уведомлений там одинаков. Единственная разница заключается в структуре JSON, где сообщения данных не имеют notification
объект. Из документации на сообщения данных
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data" : {
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
},
}
Чтобы сохранить данные, полученные с помощью onMessgeReceived(), в базу данных SQLite, даже если ваше приложение находится в фоновом режиме (без активности), вы можете сделать следующее:
1) Создайте класс, который расширяет IntentService, например:
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, например:
@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