Bug 1473518 - Abide by Android Oreo background execution limits [Leanplum after upgrade] r=nalexander

Refactored existing LeanplumPushInstanceIDService to support Oreo background
execution limits in Leanplum after upgrade.

MozReview-Commit-ID: JjUlrOv34KR
***

--HG--
extra : amend_source : df46ff00a671a02dc1c6fda3d0402d9216d7e84f
This commit is contained in:
Andrei Lazar 2018-07-06 13:21:27 +03:00
parent 65f0721e90
commit fc8235eccf
4 changed files with 127 additions and 6 deletions

View file

@ -9,6 +9,17 @@
<service android:name="com.leanplum.LeanplumLocalPushListenerService" android:exported="false"
android:enabled="true" />
<service android:name="com.leanplum.LeanplumPushListenerService" android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="@ANDROID_PACKAGE_NAME@" />
</intent-filter>
</service>
<!-- Leanplum GCM Registration Job Service. -->
<service android:name="com.leanplum.LeanplumGcmRegistrationJobService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
<!-- Leanplum GCM Instance ID Service -->
<service android:name="com.leanplum.LeanplumPushInstanceIDService" android:exported="false"
android:enabled="true">

View file

@ -0,0 +1,25 @@
package com.leanplum;
import android.annotation.TargetApi;
import android.app.job.JobParameters;
import android.app.job.JobService;
/**
* Leanplum GCM registration Job Service to start registration service.
*
* @author Anna Orlova
*/
@TargetApi(21)
public class LeanplumGcmRegistrationJobService extends JobService {
public static final int JOB_ID = -63722755;
@Override
public boolean onStartJob(JobParameters jobParameters) {
LeanplumNotificationHelper.startPushRegistrationService(this, "GCM");
return false;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
return false;
}
}

View file

@ -24,14 +24,17 @@ package com.leanplum;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.util.TypedValue;
@ -42,7 +45,10 @@ import com.leanplum.internal.JsonConverter;
import com.leanplum.internal.Log;
import com.leanplum.utils.BuildUtil;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeSet;
/**
* LeanplumNotificationHelper helper class for push notifications.
@ -81,6 +87,79 @@ class LeanplumNotificationHelper {
}
}
/**
* Starts push registration service to update GCM/FCM InstanceId token.
*
* @param context Current application context.
* @param providerName Name of push notification provider.
*/
static void startPushRegistrationService(Context context, String providerName) {
try {
if (context == null) {
return;
}
Log.i("Updating " + providerName + " InstanceId token.");
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
Intent intent = new Intent(context, LeanplumPushRegistrationService.class);
context.startService(intent);
} catch (Throwable t) {
Log.e("Couldn't update " + providerName + " InstanceId token.", t);
}
}
/**
* Schedule JobService to JobScheduler.
*
* @param context Current application context.
* @param clazz JobService class.
* @param jobId JobService id.
*/
@TargetApi(21)
static void scheduleJobService(Context context, Class clazz, int jobId) {
if (context == null) {
return;
}
ComponentName serviceName = new ComponentName(context, clazz);
JobScheduler jobScheduler =
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
if (jobScheduler != null) {
jobId = verifyJobId(jobScheduler.getAllPendingJobs(), jobId);
JobInfo startMyServiceJobInfo = new JobInfo.Builder(jobId, serviceName)
.setMinimumLatency(10).build();
jobScheduler.schedule(startMyServiceJobInfo);
}
}
/**
* Verifies that jobId don't present on JobScheduler pending jobs. If jobId present on
* JobScheduler pending jobs generates a new one.
*
* @param allPendingJobs List of current pending jobs.
* @param jobId JobService id.
* @return jobId if jobId don't present on JobScheduler pending jobs
*/
@TargetApi(21)
private static int verifyJobId(List<JobInfo> allPendingJobs, int jobId) {
if (allPendingJobs != null && !allPendingJobs.isEmpty()) {
TreeSet<Integer> idsSet = new TreeSet<>();
for (JobInfo jobInfo : allPendingJobs) {
idsSet.add(jobInfo.getId());
}
if (idsSet.contains(jobId)) {
if (idsSet.first() > Integer.MIN_VALUE) {
jobId = idsSet.first() - 1;
} else if (idsSet.last() < Integer.MIN_VALUE) {
jobId = idsSet.last() + 1;
} else {
while (idsSet.contains(jobId)) {
jobId = new Random().nextInt();
}
}
}
}
return jobId;
}
/**
* If notification channels are supported this method will try to create
* Notification.Builder with default notification channel if default channel id is provided.

View file

@ -21,7 +21,7 @@
package com.leanplum;
import android.content.Intent;
import android.os.Build;
import com.google.android.gms.iid.InstanceIDListenerService;
import com.leanplum.internal.Log;
@ -39,9 +39,15 @@ public class LeanplumPushInstanceIDService extends InstanceIDListenerService {
*/
@Override
public void onTokenRefresh() {
Log.i("GCM InstanceID token needs an update");
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
Intent intent = new Intent(this, LeanplumPushRegistrationService.class);
startService(intent);
try {
if (Build.VERSION.SDK_INT < 26) {
LeanplumNotificationHelper.startPushRegistrationService(this, "GCM");
} else {
LeanplumNotificationHelper.scheduleJobService(this,
LeanplumGcmRegistrationJobService.class, LeanplumGcmRegistrationJobService.JOB_ID);
}
} catch (Throwable t) {
Log.e("Failed to update GCM token.", t);
}
}
}