【问题标题】:How can I restart a service in android programatically?如何以编程方式重新启动android中的服务?
【发布时间】:2016-07-11 06:35:09
【问题描述】:

在 Android 中,我有一个具有不同活动和服务的应用程序。这些活动用于直接的用户交互,用户可以在其中更改数据、更新数据、输入数据等。

该应用程序还使用用户输入的数据(股票数据)运行(后台)服务。该服务会定期检查股票价格(例如每 12 小时)并在某些条件匹配时向用户发出通知。

但是,作为用户,我希望能够更改此服务的设置。我启动应用程序,并且可以在存储在SharedPreference 中的应用程序活动之一中输入更新间隔。我可以更改该值,例如,让服务每隔 3 小时检查一次库存数据。

然后我是否必须“重新启动”服务?据我了解操作系统中的“服务”,该服务一直运行直到被某个事件停止。但是如果服务没有停止,服务就不会“注意到”更新间隔发生了变化!因此,在我的主应用程序的活动中,我需要某种方式来“重新启动”服务,因此它会在 3 小时内而不是 12 小时内检查股票价格!

知道如何做到这一点吗?谷歌搜索并没有真正帮助。也许我找错了关键字...?

【问题讨论】:

  • 服务是否与您的应用程序在同一进程中运行?您可以在服务中注册一个共享的偏好更改侦听器,并在偏好更改时采取相应的行动,而无需重新启动服务。
  • 在同一个Manifest文件中。
  • 另外,我完全不知道“注册共享偏好更改侦听器”是什么意思。一个示例代码会很棒......
  • 它将始终在同一个清单文件中。只要您不使用服务上的android:process 和可能的android:isolatedProcess 属性,以使用OnSharedPreferenceChangeListener 将服务放入自己的进程的方式应该适合您。
  • 使用起来非常简单。你可以找到一个例子here

标签: android


【解决方案1】:

使活动与服务通信的标准方法是通过使用 AIDL 的接口。 在 AIDL 中,您定义对服务的调用以及来自服务的回调。 这样,该服务的行为就像您可以调用其方法的另一个类。有documentation here

【讨论】:

  • 嗯,什么?请阅读您提供的链接中的第一句话(尤其是结尾)。现在再次阅读 OP 所说的内容,并尽可能解释两者的连接方式。
  • 这怎么不清楚? Alex 想要改变服务的行为。 Aidl 提供了一种以直接方式完成此操作的方法。你可以让它调用 stopself,然后重新启动它,如果这是你想要的。
  • 问题是这里绝对不需要使用AIDL,因为OP没有说服务在单独的进程中运行。 OP 只是认为您需要“重新启动”服务,而不是在服务中实现一些逻辑,例如 sharedpref 更改侦听器。
  • @Wukash 你仍然可以使用 AIDL 在同一个进程中工作,它真的不能只在不同的进程中工作
  • 我可能来自另一个星球,但我认为“使活动与服务通信的标准方法是通过绑定”,而不是 AIDL
【解决方案2】:

由于您的服务与您的应用程序在同一进程中运行,因此对此的简单解决方案是在您的服务的 onCreate 方法中将 OnSharedPreferenceChangeListener 注册到活动正在更新的同一 SharedPreferences

然后,每次偏好更改时onSharedPreferenceChanged(...) 都会在您的服务中调用。您可以检查更新间隔首选项何时发生变化,并相应地更新您的服务,而无需重新启动它。

【讨论】:

    【解决方案3】:

    您可以使用Intents 将数据和操作发送到您的服务。只需在您的 Service 类中创建一个 BroadcastReceiver 并将其注册到服务生命周期。现在您可以更新服务中的值。一个例子:

    您的服务

    public class CustomService extends Service {
    
        private BroadcastReceiver mReceiver;
    
        @Override
        public void onCreate() {
            mReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                  // get the action from the intent
                }
            }
            registerReceiver(wifiChangedState, new IntentFilter("CUSTOM");
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            return START_NOT_STICKY;
        }
    
        @Override
        public void onDestroy() {
            unregisterReceiver(mReceiver);
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    

    现在您可以创建您的自定义Intent 以从Activity 发送BroadcastReceiver 可以接收和应用的操作。

    【讨论】:

      【解决方案4】:

      您可以使用自定义Binder 创建Service

          public class CustomService extends Service {
      
              public IBinder onBind(Intent intent) {
                  return new CustomBinder(this);
              }
      
              public void doSomething(){
                  //Do somthing with service
              }
      
          }
      
          public class CustomBinder extends Binder {
      
              private CustomService mCustomService;
      
              public MyBinder(CustomService service) {
                  mCustomService = service;
              }
      
              public CustomService getCustomService() {
                  return mCustomService;
              }
          }
      

      此时您可以通过ServiceConnection绑定到CustomService(由于我的声誉,我无法链接ServiceConnection......)实现了您在服务中需要的所有功能。

          Intent customServiceIntent = new Intent(context, CustomService.class);
          context.bindService(
                  customServiceIntent, 
                  mServiceConnection, 
                  Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
          );
      
          private ServiceConnection mServiceConnection = new ServiceConnection() {
              public void onServiceConnected(ComponentName name, IBinder service) {
                  CustomBinder binder = (CustomBinder) service;
                  binder.getCustomService().doSomething();
              }
              public void onServiceDisconnected(ComponentName name) {
                  /* Do something when service disconnect */
              }
          };
      

      此方法不适用于进程之上的服务。 (多个应用程序)查看 AIDL 文件以实现这一目标。

      为了确保“工作”及时执行,您可以使用 AlarmManager 启动您的服务。

          /* define when intent will be send */
          long wakeUpTimeInMillis = Calendar.getInstance().getTimeInMillis() + 1000 * 30 ; // now + 30second 
      
          AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
          Intent intent = new Intent(context, CustomService.class);
          PendingIntent pending = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE);
          alarmManager.set(AlarmManager.RTC_WAKEUP, wakeUpTimeInMillis, pending);
      

      您可以向 intent 添加一些额外的参数,并通过在 CustomService 中覆盖 onStartCommand(Intent intent, int flags, int startId) 来捕获它

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-08
        • 2010-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多