Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | package org.mozilla.gecko.background; |
michael@0 | 6 | |
michael@0 | 7 | import java.lang.reflect.InvocationTargetException; |
michael@0 | 8 | import java.lang.reflect.Method; |
michael@0 | 9 | |
michael@0 | 10 | import org.mozilla.gecko.background.common.log.Logger; |
michael@0 | 11 | |
michael@0 | 12 | import android.app.AlarmManager; |
michael@0 | 13 | import android.app.IntentService; |
michael@0 | 14 | import android.app.PendingIntent; |
michael@0 | 15 | import android.content.Context; |
michael@0 | 16 | import android.content.Intent; |
michael@0 | 17 | import android.net.ConnectivityManager; |
michael@0 | 18 | import android.net.NetworkInfo; |
michael@0 | 19 | import android.os.Build; |
michael@0 | 20 | |
michael@0 | 21 | public abstract class BackgroundService extends IntentService { |
michael@0 | 22 | private static final String LOG_TAG = BackgroundService.class.getSimpleName(); |
michael@0 | 23 | |
michael@0 | 24 | protected BackgroundService() { |
michael@0 | 25 | super(LOG_TAG); |
michael@0 | 26 | } |
michael@0 | 27 | |
michael@0 | 28 | protected BackgroundService(String threadName) { |
michael@0 | 29 | super(threadName); |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | public static void runIntentInService(Context context, Intent intent, Class<? extends BackgroundService> serviceClass) { |
michael@0 | 33 | Intent service = new Intent(context, serviceClass); |
michael@0 | 34 | service.setAction(intent.getAction()); |
michael@0 | 35 | service.putExtras(intent); |
michael@0 | 36 | context.startService(service); |
michael@0 | 37 | } |
michael@0 | 38 | |
michael@0 | 39 | /** |
michael@0 | 40 | * Returns true if the OS will allow us to perform background |
michael@0 | 41 | * data operations. This logic varies by OS version. |
michael@0 | 42 | */ |
michael@0 | 43 | @SuppressWarnings("deprecation") |
michael@0 | 44 | protected boolean backgroundDataIsEnabled() { |
michael@0 | 45 | ConnectivityManager connectivity = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); |
michael@0 | 46 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { |
michael@0 | 47 | return connectivity.getBackgroundDataSetting(); |
michael@0 | 48 | } |
michael@0 | 49 | NetworkInfo networkInfo = connectivity.getActiveNetworkInfo(); |
michael@0 | 50 | if (networkInfo == null) { |
michael@0 | 51 | return false; |
michael@0 | 52 | } |
michael@0 | 53 | return networkInfo.isAvailable(); |
michael@0 | 54 | } |
michael@0 | 55 | |
michael@0 | 56 | protected AlarmManager getAlarmManager() { |
michael@0 | 57 | return getAlarmManager(this.getApplicationContext()); |
michael@0 | 58 | } |
michael@0 | 59 | |
michael@0 | 60 | protected static AlarmManager getAlarmManager(Context context) { |
michael@0 | 61 | return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | protected void scheduleAlarm(long pollInterval, PendingIntent pendingIntent) { |
michael@0 | 65 | Logger.info(LOG_TAG, "Setting inexact repeating alarm for interval " + pollInterval); |
michael@0 | 66 | if (pollInterval <= 0) { |
michael@0 | 67 | throw new IllegalArgumentException("pollInterval " + pollInterval + " must be positive"); |
michael@0 | 68 | } |
michael@0 | 69 | final AlarmManager alarm = getAlarmManager(); |
michael@0 | 70 | final long firstEvent = System.currentTimeMillis(); |
michael@0 | 71 | alarm.setInexactRepeating(AlarmManager.RTC, firstEvent, pollInterval, pendingIntent); |
michael@0 | 72 | } |
michael@0 | 73 | |
michael@0 | 74 | protected void cancelAlarm(PendingIntent pendingIntent) { |
michael@0 | 75 | final AlarmManager alarm = getAlarmManager(); |
michael@0 | 76 | alarm.cancel(pendingIntent); |
michael@0 | 77 | // For testing - allows us to see if the intent, and thus the alarm, has been cancelled. |
michael@0 | 78 | pendingIntent.cancel(); |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | /** |
michael@0 | 82 | * To avoid tight coupling to Fennec, we use reflection to find |
michael@0 | 83 | * <code>GeckoPreferences</code>, invoking the same code path that |
michael@0 | 84 | * <code>GeckoApp</code> uses on startup to send the <i>other</i> |
michael@0 | 85 | * notification to which we listen. |
michael@0 | 86 | * |
michael@0 | 87 | * Invoke this to handle one of the system intents to which we listen to |
michael@0 | 88 | * launch our service without the browser being opened. |
michael@0 | 89 | * |
michael@0 | 90 | * All of this is neatly wrapped in <code>try…catch</code>, so this code |
michael@0 | 91 | * will run safely without a Firefox build installed. |
michael@0 | 92 | */ |
michael@0 | 93 | protected static void reflectContextToFennec(Context context, String className, String methodName) { |
michael@0 | 94 | // Ask the browser to tell us the current state of the preference. |
michael@0 | 95 | try { |
michael@0 | 96 | Class<?> geckoPreferences = Class.forName(className); |
michael@0 | 97 | Method broadcastSnippetsPref = geckoPreferences.getMethod(methodName, Context.class); |
michael@0 | 98 | broadcastSnippetsPref.invoke(null, context); |
michael@0 | 99 | return; |
michael@0 | 100 | } catch (ClassNotFoundException e) { |
michael@0 | 101 | Logger.error(LOG_TAG, "Class " + className + " not found!"); |
michael@0 | 102 | return; |
michael@0 | 103 | } catch (NoSuchMethodException e) { |
michael@0 | 104 | Logger.error(LOG_TAG, "Method " + className + "/" + methodName + " not found!"); |
michael@0 | 105 | return; |
michael@0 | 106 | } catch (IllegalArgumentException e) { |
michael@0 | 107 | Logger.error(LOG_TAG, "Got exception invoking " + methodName + "."); |
michael@0 | 108 | } catch (IllegalAccessException e) { |
michael@0 | 109 | Logger.error(LOG_TAG, "Got exception invoking " + methodName + "."); |
michael@0 | 110 | } catch (InvocationTargetException e) { |
michael@0 | 111 | Logger.error(LOG_TAG, "Got exception invoking " + methodName + "."); |
michael@0 | 112 | } |
michael@0 | 113 | } |
michael@0 | 114 | } |