如何防止在Android系统中运行的服务再次运行?

44

1
与之相关的内容:https://dev59.com/62sz5IYBdhLWcg3wQFe2 - Ciro Santilli OurBigBook.com
5个回答

92

一个服务只会运行一次,因此您可以多次调用startService(Intent)

您将在服务中收到onStartCommand()。请记住这一点。

来源: 请注意,多次调用Context.startService()不会嵌套(虽然它们会导致多个相应的onStartCommand()调用),因此无论启动多少次服务,一旦调用Context.stopService()stopSelf(),服务将停止;但是,服务可以使用它们的stopSelf(int)方法,以确保在处理启动意图之前不会停止服务。

来自:http://developer.android.com/reference/android/app/Service.html 话题:Service Lifecycle


谢谢您的快速回复。您的评论对我很有帮助,但是如果服务正在运行,我不想再次调用这些方法。还有其他的想法吗? - Atul Bhardwaj
13
调用 startService() 始终会触发 onStartCommand()。因此,要么不调用 startService(),要么编写一个更加智能的 onStartCommand() 函数以应对多次调用。 - CommonsWare

29

使用startService()。 启动服务将调用onStartCommand(),如果服务尚未启动,则会调用onCreate()。在onCreate()中初始化变量和/或启动线程。


1
这是正确的答案。onCreate()被忽略了。 - likejudo
2
我们想要启动服务 onCreate 调用多少次才能只调用一次? - Noor Hossain
1
@NoorHossain 正确。 - Atul Bhardwaj

7

绑定您的服务; 在启动时调用:

Intent bindIntent = new Intent(this,ServiceTask.class);
    startService(bindIntent);
    bindService(bindIntent,mConnection,0);

然后检查你的服务是否在工作状态中,可以使用以下类似的方法:

    public static boolean isServiceRunning(String serviceClassName){ 
             final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);     
             final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);      
           for (RunningServiceInfo runningServiceInfo : services) {         
             if (runningServiceInfo.service.getClassName().equals(serviceClassName)){             
                return true;         
             }     
           }     
         return false; 
        }

这段代码仅当我将服务绑定到活动时才能工作吗?我认为将服务绑定到活动将持续到应用程序运行结束。请评论。 - Atul Bhardwaj
2
这并不总是有效。它没有考虑到“服务停止”的情况。而且它主要用于显示运行中的服务UI。我曾经使用过它,但在KitKat中并不总是有效。相反,你可以始终使用startService,并利用service onCreate和onStartCommand来完成你的任务。这才是正确的方法。 - Bharath Mg
3
为什么这里需要一个绑定服务?我们不能只用一个启动服务吗? - IgorGanapolsky
2
getRunningServices已被弃用。 - Achraf Amil

5
无论我们从任何活动开始任何服务,Android系统都会调用服务的onStartCommand()方法。如果服务尚未运行,则系统首先调用onCreate(),然后调用onStartCommand()。
也就是说,Android服务只在其生命周期中启动一次,并保持运行直到停止。如果任何其他客户端想要再次启动它,那么只有onStartCommand()方法会被每次调用。

有没有文档来源? - Noor Hossain

0

因此,为了避免一遍又一遍地重新启动任务,您可以使用布尔值来表示任务已经开始或正在进行。将该方法放置在oncreate和onstartCommand中,并使用布尔值进行检查:

 boolean isTimerTaskRunning = false;
private boolean isServiceKeepRunning(){
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
        return settings.getBoolean("silentModeKeepRunning", true);
    }

@Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate: Called");
        Log.i(TAG, "onCreate: keepRunning "+isServiceKeepRunning());
        if(!isTimerTaskRunning) {
            startTimerTask();
            isTimerTaskRunning = true;
        }
        //startForeground(REQUEST_CODE /* ID of notification */, notificationbuilder().build());

    }

 @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        localData = new LocalData(this);
      //  return super.onStartCommand(intent, flags, startId);
        Log.i(TAG, "onStartCommand: Called");
        Log.i(TAG, "onStartCommand: keepRunning "+isServiceKeepRunning());

        Toast.makeText(this, "This is The Mode For Silent. ", Toast.LENGTH_LONG).show();

        if(!isTimerTaskRunning) {
            Log.i(TAG, "TimerTask was not Running - started from onStartCommand");
           startTimerTask();
           isTimerTaskRunning = true;

        }else {
            Log.i(TAG, "TimerTask was already Running - checked from onStartCommand");

        }
        //return START_REDELIVER_INTENT;
        startForeground(REQUEST_CODE /* ID of notification */, notificationbuilder().build());

        return  START_STICKY;
}

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