如何在Android程序中编程重新启动服务?

4
在Android中,我有一个应用程序,其中包含不同的活动和服务。这些活动是用于直接用户交互的,用户可以更改数据、更新数据、输入数据等。
该应用程序还有一个(后台)服务正在运行,使用用户输入的数据(股票数据)。该服务定期检查股票价格(例如每12小时),如果某些条件匹配,则向用户发出通知。
然而,作为用户,我希望能够更改此服务的设置。我启动应用程序,并在其中一个应用程序的活动中输入更新间隔,该间隔存储在SharedPreference中。我能够更改值,例如将服务检查股票数据的时间间隔更改为3个小时。
那么我是否需要“重新启动”服务呢?据我所知,在操作系统中,“服务”会一直运行直到被某些事件停止。但是,如果服务没有停止,则服务不会“注意到”更新间隔已更改!因此,在我的主要应用程序中的活动中,我需要一种方法来“重新启动”服务,以便它在3小时内检查股票价格,而不是在12小时内检查!
您有什么想法如何实现这一点吗?谷歌搜索并没有真正帮助我。也许我寻找了错误的关键字...?

服务是否在您的应用程序相同的进程中运行?您可以在服务中注册共享首选项更改侦听器,并在首选项更改时采取相应措施,而无需重新启动服务。 - George Mulligan
此外,我完全不知道“注册共享首选项更改侦听器”的含义。如果有示例代码那就太好了... - Alex
那么如何使用它呢?我应该提一个新问题吗?还是你可以提供一些示例代码...? - Alex
1
使用起来非常简单。您可以在这里找到一个示例。 - George Mulligan
让我们在聊天中继续这个讨论 - Alex
显示剩余2条评论
4个回答

1

与服务通信的标准方式是通过使用AIDL接口。在AIDL中,您定义对服务的调用以及来自服务的回调。这样,服务就像可以调用方法的另一个类一样行事。这里有文档


嗯,什么?请阅读您提供的链接中的第一句话(特别是结尾)。现在再次阅读OP所说的话,如果可能的话,请解释两者之间的联系。 - Wukash
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Christine
@Wukash,你仍然可以使用AIDL在同一进程中工作,它并不只是被设计用于与不同的进程交互。 - pskink
请停止评论,我将只粘贴文档中的内容:注意:仅当您允许来自不同应用程序的客户端访问您的服务进行IPC并且想要在您的服务中处理多线程时,才需要使用AIDL。如果您不需要在不同应用程序之间执行并发IPC,则应通过实现Binder来创建您的接口。 - Wukash
@Wukash 然后查看生成的代码,你就会知道它是如何工作的。 - pskink
显示剩余5条评论

0

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

然后,每当首选项发生更改时,您的服务将调用onSharedPreferenceChanged(...)。您可以检查特定的更新间隔首选项何时发生更改,并相应地更新您的服务,而无需重新启动它。


0

您可以使用Intent向服务发送数据和操作。只需在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可以接收并应用。

0

您可以使用自定义绑定器创建服务

    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)来捕获它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接