Часть-2 постоянная foreGround служба Android, которая начинается с пользовательского интерфейса, работает в спящем режиме, также запускается при перезагрузке телефона

Status: Очень благодарен всем, кто помогал и руководил здесь и в части-1! Я сделал код из исследования и предоставил помощь и поместил этот рабочий код в EDIT-1 . Критики приветствуются, чтобы сделать код лучше.

Scenario:

Я задал вопрос в части 1, но по какой-то причине я могу настойчиво не создавать дизайн и исправлять стратегию с кодом, который имеет истинную интеграцию и здравомыслие.

Это был длительный вопрос, и вопрос и ответ могли быть завершены или завершены только в одном эпизоде, поэтому я сделал эту вторую часть в качестве краткого обзора.

Может быть, я некомпетентен или просто обеспокоен тем, что читаю так много документированных документов и ответов разных стратегий, или ответы имеют разные взгляды / стили кодирования.

Часть 1: 1-я стойкая служба foreGround android, которая начинается с пользовательского интерфейса, также работает в спящем режиме, также запускается при перезагрузке телефона

Question:

Вот что я хотел и, наконец, закончил, наблюдая разные ответы:

Необходимо запускать код каждые 15 минут ( даже если телефон находится в режиме сна ). Я думаю, нужны ли блокировки слежения.

  //AT boot, check shared preferences to see boolean "serviceEnabled"? //if true, set alarm manager to run a service every 15 minuts. //if false, do nothing. //On "enable" button clicked. //make "serviceEnabled" boolean true in shared preferences. //start alarm manager to run a service every 15 minuts. //on "Disable" button clicked. //make "serviceEnabled" boolean false in shared preferences. //stop alarm manager and deregister it to run ever. 

Может ли кто-нибудь рассказать … какой код я должен использовать …? Я смиренно благодарен полной головной болью исследований.

Requests:

Пожалуйста, ответьте только, если вы уверенно и с опытом знаете, что делаете.

EDIT-1-Start:

Вот что я сделал до сих пор. Пожалуйста, не стесняйтесь комментировать или критиковать.

Класс загрузчика, который запускается при загрузке.

 public class Booter extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { Log.e("boot-status","BOOT_COMPLETED================================================="); // SharedPreferences prefs = context.getSharedPreferences("$MYPACKAGE_preferences",0); // if (prefs.getBoolean("startatboot",false)) { if(true){ Intent updateIntent = new Intent(); updateIntent.setClass(context, TheService.class); PendingIntent pendingIntent = PendingIntent.getService(context, 0, updateIntent, 0); AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, java.lang.System.currentTimeMillis()+5000,5000, pendingIntent); } } } } 

Класс обслуживания

 public class TheService extends Service{ @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } PowerManager pm; PowerManager.WakeLock wl; @Override public int onStartCommand(Intent intent, int flags, int startId) { pm = (PowerManager) getSystemService(Context.POWER_SERVICE); wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag"); wl.acquire(); startForeground(1, new Notification()); ////// will do all my stuff here on in the method onStart() or onCreat()? Log.e("app-status","ping ===================================================="); new Thread(new Runnable() { @Override public void run() { wl.release(); stopSelf(); } }).start(); return START_STICKY; } @Override public void onDestroy() { stop(); } public void stop(){ //if running // stop // make vars as false // do some stopping stuff stopForeground(true); } } 

GUI для запуска / остановки

 public class SettingsActivity extends Activity { // some code to initialize things buttonStop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent updateIntent = new Intent(); updateIntent.setClass(SettingsActivity.this, TheService.class); PendingIntent pendingIntent = PendingIntent.getService(SettingsActivity.this, 0, updateIntent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager)SettingsActivity.this.getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(pendingIntent); //make sharepred boolean as false } }); buttonStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent updateIntent = new Intent(); updateIntent.setClass(SettingsActivity.this, TheService.class); PendingIntent pendingIntent = PendingIntent.getService(SettingsActivity.this, 0, updateIntent, 0); AlarmManager alarmManager = (AlarmManager)SettingsActivity.this.getSystemService(Context.ALARM_SERVICE); alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, java.lang.System.currentTimeMillis()+5000,5000, pendingIntent); //make shared prefs boolean as true } }); 

Menifiest

  <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> // irrelevent here <uses-permission android:name="android.permission.INTERNET" /> // my app uses these though in service class. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application android:allowBackup="true" android:debuggable="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.myapp.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.example.myapp.SettingsActivity" android:label="@string/title_activity_settings" > </activity> <service android:name=".TheService" /> <receiver android:name=".Booter" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <category android:name="android.intent.category.HOME" /> </intent-filter> </receiver> </application> </manifest> 

EDIT-1-END.

Если вам нужно всего лишь запустить этот код каждые 15 минут. То вам действительно не нужно поддерживать работу 24/7. На самом деле, не делай этого, это плохая идея. Вам нужно сделать следующее:

  1. Используйте AlarmManager для планирования тревоги каждые 15 минут. Эта тревога затем захватывается с помощью BroadcastReceiver. Этот сигнал тревоги должен быть RTC_WAKE_UP, чтобы он разбудил телефон, если он находится в глубоком сне, и он должен быть в режиме реального времени, так как он будет использовать таймер глубокого сна.

  2. Трансляционный приемник должен будет запустить службу. Теперь этот вызов службы должен быть выполнен следующим образом:

    • 2.1. Получите wakelock в BroadcastReceiver и приобретете () его.
    • 2.2 запустите IntenetService (этот тип сервисов начинается и заканчивается после завершения работы)
    • 2.3. Выпуск wakelock в сервисе

Существует хороший пример того, как реализовать это здесь: WakefulIntentService commonsware . Вам не нужно использовать его как есть, вы можете сделать свой собственный сервис и широковещательный приемник. Не забывайте приобретать блокировку перед вызовом службы и ее освобождением при выполнении услуги, иначе услуга не может быть вызвана.

  1. Ваша служба делает все, что вы хотите выполнить каждые 15 минут. Затем вы можете перепланировать другой вызов еще на 15 минут. Вы также можете проверить, включена ли служба через общие настройки перед выполнением и перепланировкой.

Что касается вашей деятельности, контролирующей ваш сервис:

  1. Когда кнопка нажата, проверьте состояние общего предпочтения и сохраните противоположное.
  2. Затем отправьте широковещательную рассылку на тот же приемник, который запустит вашу службу, если они включили ее (или планируют позже).
  3. Если он был отключен, отмените любые расписания для службы.

Что касается вашего требования к загрузке:

  1. Объявите в своем манифесте, что тот же приемник, который запускает вашу службу, вызывается, когда вызывается действие android.intent.action.BOOT_COMPLETED.
  2. Объявить разрешение: android.permission.RECEIVE_BOOT_COMPLETED

Пример манифеста:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.yourcompany.yourapp" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <application android:allowBackup="false" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.yourcompany.yourapp.activities.HomeActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="com.yourcompany.yourapp.services.ActionHandlerService" /> <receiver android:name="com.yourcompany.yourapp.receivers.BootReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <category android:name="android.intent.category.HOME" /> </intent-filter> </receiver> </application> </manifest> 

Пример отмены и планирования аварийных сигналов:

 public synchronized static void disableTimers(final Context context) { Log.i(TAG, "Canceling Alarms"); final Intent in = new Intent(Constants.Actions.TIMER_ACTION); final PendingIntent pi = PendingIntent.getBroadcast(context, 0, in, PendingIntent.FLAG_UPDATE_CURRENT); ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).cancel(pi); } public synchronized static void enableTimer(final Context context) { Log.i(TAG, "Enabling Alarm"); final Intent in = new Intent(Constants.Actions.TIMER_ACTION); final PendingIntent pi = PendingIntent.getBroadcast(context, 0, in, PendingIntent.FLAG_UPDATE_CURRENT); ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + FIFTEEN_MINUTES, pi); } 

Пример запуска службы при загрузке:

 @Override public void onReceive(final Context context, final Intent intent) { final Intent in = new Intent(context, MyService.class); in.setAction(Actions.BOOT_RECEIVER_ACTION); Log.i(TAG, "Boot completed. Starting service."); MyService.acquireLock(); context.startService(in); } 

А на сервисе отпустите блокировку

 private static volatile WakeLock mStaticWakeLock = null; private synchronized static WakeLock getLock(final Context context) { if (mStaticWakeLock == null) { final PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mStaticWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_PARAMETER); mStaticWakeLock.setReferenceCounted(true); } return mStaticWakeLock; } @Override protected final void onHandleIntent(final Intent intent) { try { run(intent); } finally { final WakeLock lock = getLock(getApplicationContext()); if (lock.isHeld()) { lock.release(); Log.i(TAG, "Releasing WakeLock"); } } } 

Вот и все.