11

Status:---同样接受 Karakuri 和 Sharad Mhaske 的回答,但是由于 Sharad Mhaske是在赏金开始回答的,所以赏金应该给他。

第 2 部分制作:第 2部分由 UI 启动的持久前台 android 服务,也可以在睡眠模式下工作,也可以在手机重启时启动

stack overflow,只能接受一个答案。我认为这两个答案都是可以接受的,但必须选择一个(我是随机选择的)。

邀请观众对答案/问题进行投票/否决以感谢您的努力!. 我赞成 Karakuri 的回答以补偿声誉。

Scenario:---

  1. 我想让用户单击启动/停止按钮并从 UI 活动启动/停止服务。我已经制作了 UI,所以不在乎。但只是按钮点击事件的逻辑。

  2. 希望服务绑定到 UI 活动。如果活动关闭,服务应该继续运行。

  3. 要尽最大努力使服务保持持久并且在任何情况下都不会停止。将给予它最大的权重并运行它,ForGroundSerice因为它具有更高的重要性等级。(希望没问题?)

  4. 除非我的应用程序 UI单击停止按钮,否则即使 android 回收内存,也不希望它停止(或应该重新启动)。我和手机的用户,都/将会知道它。服务是最重要的。甚至在睡觉时。

    details= 我的应用程序执行一些操作,在用户提供的时间(通常为 15 分钟)内休眠,唤醒并再次执行操作。这永远不会结束)

    如果我需要AlarmManager,如何实现?或任何其他方式?或者只是把操作放在while loop and sleep for 15 minuts最后?

  5. 服务启动时(通过单击启动按钮)。它应该输入一个条目,以便在手机重新启动时自动启动。

QUESTION:---

Primary Question:

  1. 只是无法为该场景找到最佳策略......并且还停留在一小段代码上,使用哪一个以及如何使用。

  2. 从 stackoverflow.com 问题、developer.android.com 和一些谷歌结果中收集的点点滴滴,但无法在集成中实现。

  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

启动/停止服务的 Activity UI 类:

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

我认为这个问题对于大多数处理服务的人来说是一种正常的做法。在该愿景中,请仅在您有场景经验并且能够以最大示例代码作为完整版本全面解释方面和策略的情况下回答,这样对社区也有帮助。

对答案进行上下投票(负责任地),因为这对我很重要,谁分享了他们的观点、时间和经验,并帮助了我和社区。

4

3 回答 3

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

问:如果我需要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:当服务启动时(通过点击启动按钮)。它应该输入一个条目,以便在手机重新启动时自动启动。

答:使用广播接收器来监听 onboot 完成的意图。

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);
        }
    }
}

//需要在 manifest.xml 文件中为 Action_BOOTCOMPLETED 意图注册此接收器 希望这可以帮助您清除问题:)

于 2013-06-15T11:49:49.837 回答
2

如果使用 启动服务startService(),即使 Activity 关闭,它也会继续运行。它只会在您调用时停止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禁用它相同的方法。

于 2013-06-09T03:07:25.043 回答
0

我自己做了这样的事情,但我在开发它的过程中学到了很多东西,并发现让服务运行一整天耗尽你的电池并不是完全必要的。我所做的是以下内容:

实现对事件做出反应的服务。特别是我想自动化我的 Wifi 和移动数据连接。所以我会对 wifi 连接和断开连接、屏幕打开和关闭等事件做出反应。因此,此服务执行响应此事件需要执行的操作,然后停止,如果需要,使用 AlarmManager 安排任何进一步的操作。

现在,这个事件可以像你自己说的那样每 15 分钟做一些事情并睡觉,这听起来你真的不希望服务 24/7 运行,而只是每 15 分钟执行一次。这完全可以通过 AlarmManager 实现,而无需让您的服务永远运行。

我建议实施源自commonsware 的 WakefulIntentService 的服务

这个类已经为你处理了wakeLock,这样即使手机睡着了你也可以执行代码。它只会唤醒执行并重新进入睡眠状态。

现在。关于您关于启动和停止服务的活动的问题。您可以在按钮中实现它启动或取消AlarmManager 警报。您还可以使用 sharedPreferences 存储一个简单的布尔值,告诉您它是否已启用,以便下次服务运行时它可以读取该值并知道它应该继续还是停止。

如果您按照我所说的将它实现为事件反应式服务,您的按钮甚至可以对广播意图做出反应,这样您的活动甚至不必直接调用服务,只需广播一个意图,服务就可以像其他事件一样选择它。为此使用广播接收器。

我会尝试举一些例子,但要小心你要问的是很多代码把它放在一个地方......

引导接收器:

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>
于 2013-06-11T19:11:19.093 回答