Вам нужно использовать Firebase JobDispatcher
. Вы можете найти некоторую информацию здесь и здесь код. По сути, держите сервис, чтобы запустить его, когда это возможно, даже когда приложение убито.
Работает так:
Это ваш FirebaseService
заявленный в manifest
:
<service android:name=".services.FirebaseCloudMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
И реализация:
public class FirebaseCloudMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
Log.i("PUSH", data.toString());
if (ApplicationContextProvider.isInBackground()) {
//***********************
//This is the most important portion of code
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(getApplicationContext()));
Job myJob = dispatcher.newJobBuilder()
.setService(SyncAppInBackgroundService.class) // the JobService that will be called
.setTag("my-unique-tag") // uniquely identifies the job
.build();
dispatcher.mustSchedule(myJob);
//***********************
} else {
// This code manage the PushNotification when the user is in the app
int notificationType = Integer.valueOf(data.get("type"));
switch (notificationType) {
case Constants.PushNotification.TYPE_NEW_MESSAGE:
case Constants.PushNotification.TYPE_CHECK_MESSAGE:
if (Chat.TABLE.getByServerId(Long.valueOf(data.get("idChat"))) != null) {
new SyncAppHandler(null).execute(SyncAppHandler.SynchronizeTaskType.SynchronizeTaskTypeMessages);
break;
}
case Constants.PushNotification.TYPE_NEW_GROUP:
case Constants.PushNotification.TYPE_EDIT_CHAT_USER:
new SyncAppHandler(null).execute(SyncAppHandler.SynchronizeTaskType.SynchronizeTaskTypeChats);
break;
}
}
}
}
Теперь нам нужно создать JobService
для планирования:
public class SyncAppInBackgroundService extends JobService implements SyncAppDelegate {
private JobParameters params;
private SyncAppHandler syncAppHandler;
private SynchronizeTaskType lastTask = SynchronizeTaskType.SynchronizeTaskTypeLogin;
@Override
public boolean onStartJob(JobParameters job) {
// Do some work here
params = job;
syncAppHandler = new SyncAppHandler(this);
syncAppHandler.execute(lastTask);
return true; // Answers the question: "Is there still work going on?"
}
@Override
public boolean onStopJob(JobParameters job) {
return true;// Answers the question: "Should this job be retried?"
}
@Override
public void didFinishExecutingTaskWithResult(SynchronizeTaskType type, int result) {
//handle the sync and if you finished, call:
jobFinished(params, true);
}
}
Не добавляйте его в манифест:
<service
android:name=".services.SyncAppInBackgroundService"
android:exported="false">
<intent-filter>
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
</intent-filter>
</service>
Все, что вам нужно сейчас, - это создать SyncAppHandler
. Этот класс мой, не расширяет ни один класс Android или библиотеку. Просто внедрите там свой бизнес-код или переговоры для синхронизации.
EXTRA:
Мой способ узнать, находится ли приложение в фоновом режиме. Возвращает false
только если приложение находится на переднем плане, во всех других случаях, таких как телефон заблокирован, приложение убито ... возвращает true
.
public static boolean isInBackground() {
RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
ActivityManager.getMyMemoryState(myProcess);
if (myProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
return true;
KeyguardManager keyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
return keyguardManager.inKeyguardRestrictedInputMode(); // app is in foreground, but if screen is locked show notification anyway
}