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

Status:--- Я в равной степени принимаю ответ Каракури и Шарада Мхаске, но, поскольку Шарад Мхаске отвечает после начала щедрости, щедрость должна достаться ему.

Выполнена часть 2: постоянная служба Android для ForeGround, часть 2, которая запускается с помощью пользовательского интерфейса, работает и в спящем режиме, а также при перезагрузке телефона

В stack overflow может быть принят только один ответ. Я считаю оба ответа приемлемыми, но нужно выбрать один (я выбрал наугад).

Зрителям предлагается ответить на вопрос "вверх / вниз", чтобы оценить усилия!, Я проголосовал за ответ Каракури, чтобы компенсировать репутацию.

Scenario:---

  1. Я хочу, чтобы пользователь нажимал кнопку "Пуск / Стоп" и запускал / останавливал службу из-за активности пользовательского интерфейса. Я сделал пользовательский интерфейс, так что мне все равно. Но только логика события нажатия кнопки.

  2. Не хотите, чтобы служба была связана с пользовательским интерфейсом. Если активность закрывается, служба должна продолжать работать.

  3. Хочу приложить максимум усилий, чтобы сервис был постоянным и не останавливался ни в коем случае. Придаст этому вес и побежит как ForGroundSerice как это имеет более высокую иерархию важности. (надеюсь, что все в порядке?)

  4. Если пользовательский интерфейс моих приложений не нажимает кнопку "Стоп", не следует останавливать ее (или перезагружать сам), даже если Android освобождает память. Я и пользователь телефона, оба знают об этом. Сервис является наиболее важным. Даже во сне.

    детали = мое приложение выполняет некоторые операции, спит в течение предоставленного пользователем времени (обычно 15 минут), просыпается и снова выполняет операции. это никогда не заканчивается)

    Если мне нужно AlarmManager Как это реализовать? или любым другим способом? Или просто положить операции в бесконечной while loop and sleep for 15 minuts в конце?

  5. Когда сервис запущен (нажатием на кнопку запуска). Он должен сделать запись, чтобы он автоматически запускался при перезагрузке телефона.

QUESTION:---

Primary Question:

  1. Просто не могу найти оптимальную стратегию для сценария... а также придерживаться небольших кусочков кода, какой использовать и как.

  2. Собранные по кусочкам вопросы на stackru.com, developer.android.com и некоторые результаты Google, но не могут быть реализованы в интеграции.

  3. Пожалуйста, прочитайте раздел запросов.

Secondary Question:

Комментарии в моем коде - те маленькие вопросы.

Research and Code:---

Стратегия:

            want this to happen every time the user opens the UI.

    //Start Button:-----
    //check if ForGroundService is running or not. if not running, make var/settings/etc "serviceStatus" as false 
            <-------(how and where to stare this and below stated  boolean?)
    //start ForGroundService 
            <-------(how?)
    //make "SericeStatus" as true

    //check if "ServiceStartOnBoot" is false
    //Put ForGroundService to start on boot -------(to make it start when ever the phone reboots/restarts) 
            <-------(how?)
    //make "ServiceStartOnBoot" as true
            // the boolean can also be used to check the service status.



    //Stop Button:------
    //makes SericeStatus and ServiceStartOnBoot as false
    //stops service and deletes the on boot entry/strategy

Класс пользовательского интерфейса, который запускает / останавливает службу:

public class SettingsActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);

        //some button here to start / stop and their onClick Listners



    Intent mySericeIntent = new Intent(this, TheService.class);
    }


    private void startMyForGroundService(){

    startService(mySericeIntent);

    }

    private void stopMyForGroundSerice(){
        stopService(mySericeIntent);
                          /////// is this a better approach?. stopService(new Intent(this, TheService.class));          
                          /////// or making Intent mySericeIntent = new Intent(this, TheService.class);
                          /////// and making start and stop methods use the same?

                          /////// how to call stopSelf() here? or any where else? whats the best way?
    }

}

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

  public class TheService extends Service{

      @Override
      public IBinder onBind(Intent arg0) {
          // TODO Auto-generated method stub
          return null;
      }

      @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
          startForeground(1, new Notification());
                                  ////// will do all my stuff here on in the method onStart() or onCreat()?

          return START_STICKY;    ///// which return is better to keep the service running untill explicitly killed. contrary to system kill.
                                  ///// http://developer.android.com/reference/android/app/Service.html#START_FLAG_REDELIVERY

          //notes:-//  if you implement onStartCommand() to schedule work to be done asynchronously or in another thread, 
          //then you may want to use START_FLAG_REDELIVERY to have the system re-deliver an Intent for you so that it does not get lost if your service is killed while processing it
      }

      @Override
        public void onDestroy() {
          stop();
        }

      public void stop(){
          //if running
          // stop
          // make vars as false
          // do some stopping stuff
          stopForeground(true);
                                  /////// how to call stopSelf() here? or any where else? whats the best way?

      }


  }

Файл Менифеста:

      <?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" />
      <uses-permission android:name="android.permission.INTERNET" />

      <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>

      </application>

      </manifest>

References:---

Android - реализация startForeground для сервиса? указывающий ответ 1, пример кода.

Попытка запустить сервис при загрузке на Android

Android: запустить сервис при загрузке?

http://developer.android.com/guide/components/services.html

http://developer.android.com/reference/android/app/Service.html

http://developer.android.com/training/run-background-service/create-service.html не предложенный мной.

http://developer.android.com/guide/components/processes-and-threads.html моя отправная точка исследования

Requests:---

Я думаю, что этот вопрос является нормальной практикой для большинства людей, которые имеют дело с услугами. В этом видении, пожалуйста, отвечайте, только если у вас есть опыт в сценарии, и вы можете всесторонне объяснить аспекты и стратегию с максимальным количеством примеров кода в качестве полной версии, чтобы это также помогло бы сообществу.

Голосуйте "за" и "вниз" (с ответственностью) за ответы, так как это важно для меня, кто поделился своими взглядами, временем и опытом и помог мне и сообществу.

3 ответа

Решение

Que: Хочу приложить максимум усилий, чтобы сервис был постоянным и не останавливался ни в коем случае. Придаст этому значению вес и запустит его как ForGroundSerice, так как он имеет более высокую иерархию важности. (надеюсь, что все в порядке?)

Ответ: вам нужно запустить сервис с использованием START_STICKY флага Intent.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}

Que: Если мне нужен AlarmManager, как это реализовать? или любым другим способом? Или просто положить операции в бесконечный цикл while и спать в течение 15 минут в конце?

Ответ: вам необходимо зарегистрировать AlarmManager в сервисе на некоторое время после выполнения какой-либо задачи. // зарегистрируем диспетчер аварий в сервисе.

PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new         Intent("com.xxxxx.tq.TQServiceManager"), PendingIntent.FLAG_UPDATE_CURRENT);

        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

    alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000 , 30 * 1000 , pendingIntent);

// теперь есть радиовещательный приемник для получения этого намерения.

class Alarmreceiver extends Broadcastreceiver
{
   //u can to task in onreceive method of receiver.
}

// зарегистрировать этот класс в манифесте для действия получателя тревоги.

Que: Когда сервис запущен (нажатием на кнопку запуска). Он должен сделать запись, чтобы он автоматически запускался при перезагрузке телефона.

Ответ: используйте широковещательный ресивер, чтобы прослушать завершение загрузки.

public class StartAtBootServiceReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        try {           
            if( "android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {                

                ComponentName comp = new ComponentName(context.getPackageName(), LicensingService.class.getName());
                ComponentName service = context.startService(new Intent().setComponent(comp));
                if (null == service){
                    // something really wrong here
                    //Log.Write("Could not start service " + comp.toString(),Log._LogLevel.NORAML);
                }
            }
            else {
                //Log.Write("Received unexpected intent " + intent.toString(),Log._LogLevel.NORAML);   
            }
        } catch (Exception e) {
            //Log.Write("Unexpected error occured in Licensing Server:" + e.toString(),Log._LogLevel.NORAML);
        }
    }
}

// необходимо зарегистрировать этот получатель для намерения Action_BOOTCOMPLETED в файле manifest.xml. Надеюсь, это поможет вам разобраться с вещами:)

Если вы начинаете службу с startService(), он продолжит работать, даже когда активность закроется. Он будет остановлен только при звонке stopService()или если это когда-либо называет stopSelf() (или если система убивает ваш процесс, чтобы восстановить память).

Чтобы запустить службу при загрузке, создайте BroadcastReceiver, который просто запускает службу:

public class MyReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Intent service = new Intent(context, MyService.class);
        context.startService(service);
    }
}

Затем добавьте их в свой манифест:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application ... >

    <receiver android:name="MyReceiver" 
        android:enabled="false" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
</application>

Обратите внимание, что приемник сначала не включен. Когда пользователь запускает ваш сервис, используйте PackageManager, чтобы включить приемник. Когда пользователь останавливает ваш сервис, используйте PackageManager, чтобы отключить приемник. В вашей деятельности:

PackageManager pm = getPackageManager();
ComponentName receiver = new ComponentName(this, MyReceiver.class);
pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,  PackageManager.DONT_KILL_APP);

Используйте тот же метод с PackageManager.COMPONENT_ENABLED_STATE_DISABLED отключить это.

Я сам сделал что-то подобное, но я многому научился при его разработке и обнаружил, что не обязательно, чтобы служба работала весь день, разряжая вашу батарею. я сделал следующее:

Реализуйте Сервис, который реагирует на события. В частности, я хотел автоматизировать Wi-Fi и мобильное соединение для передачи данных. поэтому я реагирую на такие события, как подключение и отключение Wi-Fi, включение и выключение экрана и т. д. Таким образом, эта служба выполняет все, что когда-либо должно быть выполнено, отвечая на это событие, а затем останавливается, планируя любые дальнейшие действия с AlarmManager, если это необходимо.

теперь эти события могут быть такими, как вы сами говорили каждые 15 минут, что-то делает и спит, мне кажется, что вы действительно не хотите, чтобы служба работала круглосуточно, а просто выполняла что-то каждые 15 минут. это вполне достижимо с AlarmManager, не позволяя вашему сервису работать вечно.

Я рекомендую реализовать этот сервис, полученный из WakefulIntentService от commonsware.

Этот класс уже обрабатывает wakeLock для вас, так что вы можете превысить код, даже если телефон спит. он просто активируется и снова ложится спать.

Сейчас. О вашем вопросе относительно активности запуска и остановки сервиса. Вы можете ввести в кнопку, что она запускает или отменяет тревогу AlarmManager. Также вы можете использовать sharedPreferences для хранения простого логического значения, которое сообщает вам, включено ли оно или нет, при следующем запуске службы оно может прочитать значение и узнать, следует ли продолжить или остановить.

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

Я попытаюсь привести примеры, но будьте осторожны, потому что вы спрашиваете много кода, чтобы поместить его в одно место...

BootReceiver:

public class BootReceiver extends BroadcastReceiver
{
  private static final String TAG = BootReceiver.class.getSimpleName();

  @Override
  public void onReceive(final Context context, final Intent intent)
  {
    final Intent in = new Intent(context, ActionHandlerService.class);
    in.setAction(Actions.BOOT_RECEIVER_ACTION);  //start the service with a flag telling the event that triggered
    Log.i(TAG, "Boot completed. Starting service.");
    WakedIntentService.sendWakefulWork(context, in);
  }
}

Обслуживание:

public class ActionHandlerService extends WakedIntentService
{
  private enum Action
  {
    WIFI_PULSE_ON, WIFI_PULSE_OFF, DATA_PULSE_ON, DATA_PULSE_OFF, SCREEN_ON, SCREEN_OFF, WIFI_CONNECTS, WIFI_DISCONNECTS, WIFI_CONNECT_TIMEOUT, WIFI_RECONNECT_TIMEOUT, START_UP, BOOT_UP
  }

  public ActionHandlerService()
  {
    super(ActionHandlerService.class.getName());
  }

  @Override
  public void run(final Intent intent)
  {
    mSettings = PreferenceManager.getDefaultSharedPreferences(this);
    mSettingsContainer.enabled = mSettings.getBoolean(getString(R.string.EnabledParameter), false);
    if (intent != null)
    {
      final String action = intent.getAction();
      if (action != null)
      {
        Log.i(TAG, "received action: " + action);
        if (action.compareTo(Constants.Actions.SOME_EVENT) == 0)
        {
          //Do what ever you want
        }
        else
        {
          Log.w(TAG, "Unexpected action received: " + action);
        }
      }
      else
      {
        Log.w(TAG, "Received null action!");
      }
    }
    else
    {
      Log.w(TAG, "Received null intent!");
    }
  }
}

И твой Манифест может пойти примерно так:

<?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>
Другие вопросы по тегам