diff --git a/res/values/strings.xml b/res/values/strings.xml index 9702a58763..a0b805b1dd 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -371,6 +371,9 @@ It looks like you don\'t have any apps to share to. Friends don\'t let friends chat unencrypted. + + Working in the background... + Failed to send New safety number @@ -477,6 +480,9 @@ The version of Google Play Services you have installed is not functioning correctly. Please reinstall Google Play Services and try again. + + Retrieving a message... + Rate this app If you enjoy using this app, please take a moment to help us by rating it. @@ -556,6 +562,9 @@ Contacts Messages + + Sending a message... + Add to Contacts Invite to Signal diff --git a/src/org/thoughtcrime/securesms/jobmanager/Job.java b/src/org/thoughtcrime/securesms/jobmanager/Job.java index 3bf88bf82d..179d3f28a1 100644 --- a/src/org/thoughtcrime/securesms/jobmanager/Job.java +++ b/src/org/thoughtcrime/securesms/jobmanager/Job.java @@ -5,10 +5,13 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import org.thoughtcrime.securesms.ApplicationContext; +import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent; +import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequirement; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.service.GenericForegroundService; import java.io.Serializable; import java.util.UUID; @@ -26,6 +29,7 @@ public abstract class Job extends Worker implements Serializable { static final String KEY_RETRY_COUNT = "Job_retry_count"; static final String KEY_RETRY_UNTIL = "Job_retry_until"; static final String KEY_SUBMIT_TIME = "Job_submit_time"; + static final String KEY_REQUIRES_NETWORK = "Job_requires_network"; static final String KEY_REQUIRES_MASTER_SECRET = "Job_requires_master_secret"; static final String KEY_REQUIRES_SQLCIPHER = "Job_requires_sqlcipher"; @@ -58,10 +62,19 @@ public abstract class Job extends Worker implements Serializable { initialize(new SafeData(data)); + boolean foregroundRunning = false; + try { if (withinRetryLimits(data)) { if (requirementsMet(data)) { + if (needsForegroundService(data)) { + Log.i(TAG, "Running a foreground service with description '" + getDescription() + "' to aid in job execution." + logSuffix()); + GenericForegroundService.startForegroundTask(getApplicationContext(), getDescription()); + foregroundRunning = true; + } + onRun(); + log("Successfully completed." + logSuffix()); return Result.SUCCESS; } else { @@ -79,6 +92,11 @@ public abstract class Job extends Worker implements Serializable { } warn("Failing due to an exception." + logSuffix(), e); return cancel(); + } finally { + if (foregroundRunning) { + Log.i(TAG, "Stopping the foreground service." + logSuffix()); + GenericForegroundService.stopForegroundTask(getApplicationContext()); + } } } @@ -95,6 +113,14 @@ public abstract class Job extends Worker implements Serializable { onAdded(); } + /** + * @return A string that represents what the task does. Will be shown in a foreground notification + * if necessary. + */ + protected String getDescription() { + return getApplicationContext().getString(R.string.Job_working_in_the_background); + } + /** * Called after a run has finished and we've determined a retry is required, but before the next * attempt is run. @@ -158,7 +184,7 @@ public abstract class Job extends Worker implements Serializable { return Result.SUCCESS; } - private boolean requirementsMet(Data data) { + private boolean requirementsMet(@NonNull Data data) { boolean met = true; if (data.getBoolean(KEY_REQUIRES_MASTER_SECRET, false)) { @@ -172,7 +198,7 @@ public abstract class Job extends Worker implements Serializable { return met; } - private boolean withinRetryLimits(Data data) { + private boolean withinRetryLimits(@NonNull Data data) { int retryCount = data.getInt(KEY_RETRY_COUNT, 0); long retryUntil = data.getLong(KEY_RETRY_UNTIL, 0); @@ -183,6 +209,13 @@ public abstract class Job extends Worker implements Serializable { return System.currentTimeMillis() < retryUntil; } + private boolean needsForegroundService(@NonNull Data data) { + NetworkRequirement networkRequirement = new NetworkRequirement(getApplicationContext()); + boolean requiresNetwork = data.getBoolean(KEY_REQUIRES_NETWORK, false); + + return requiresNetwork && !networkRequirement.isPresent(); + } + private void log(@NonNull String message) { log(message, null); } diff --git a/src/org/thoughtcrime/securesms/jobmanager/JobManager.java b/src/org/thoughtcrime/securesms/jobmanager/JobManager.java index c408d742ed..b87c0afbe0 100644 --- a/src/org/thoughtcrime/securesms/jobmanager/JobManager.java +++ b/src/org/thoughtcrime/securesms/jobmanager/JobManager.java @@ -41,6 +41,7 @@ public class JobManager { Data.Builder dataBuilder = new Data.Builder().putInt(Job.KEY_RETRY_COUNT, jobParameters.getRetryCount()) .putLong(Job.KEY_RETRY_UNTIL, jobParameters.getRetryUntil()) .putLong(Job.KEY_SUBMIT_TIME, System.currentTimeMillis()) + .putBoolean(Job.KEY_REQUIRES_NETWORK, jobParameters.requiresNetwork()) .putBoolean(Job.KEY_REQUIRES_MASTER_SECRET, jobParameters.requiresMasterSecret()) .putBoolean(Job.KEY_REQUIRES_SQLCIPHER, jobParameters.requiresSqlCipher()); Data data = job.serialize(dataBuilder); diff --git a/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java index a8d4331b2a..f552ec6dc4 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.jobs; import android.content.Context; import android.support.annotation.NonNull; +import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.jobmanager.JobParameters; import org.thoughtcrime.securesms.jobmanager.SafeData; @@ -43,6 +44,11 @@ public class PushNotificationReceiveJob extends PushReceivedJob implements Injec return dataBuilder.build(); } + @Override + protected String getDescription() { + return context.getString(R.string.PushNotificationReceiveJob_retrieving_a_message); + } + @Override public void onRun() throws IOException { receiver.retrieveMessages(new SignalServiceMessageReceiver.MessageReceivedCallback() { diff --git a/src/org/thoughtcrime/securesms/jobs/SendJob.java b/src/org/thoughtcrime/securesms/jobs/SendJob.java index 70e807e2a3..6b229668ed 100644 --- a/src/org/thoughtcrime/securesms/jobs/SendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/SendJob.java @@ -4,6 +4,7 @@ import android.content.Context; import android.support.annotation.NonNull; import org.thoughtcrime.securesms.BuildConfig; +import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.TextSecureExpiredException; import org.thoughtcrime.securesms.attachments.Attachment; import org.thoughtcrime.securesms.crypto.MasterSecret; @@ -31,6 +32,11 @@ public abstract class SendJob extends MasterSecretJob { super(context, parameters); } + @Override + protected String getDescription() { + return context.getString(R.string.SendJob_sending_a_message); + } + @Override public final void onRun(MasterSecret masterSecret) throws Exception { if (Util.getDaysTillBuildExpiry() <= 0) {