如何查看后台服务是否正在运行?
我想要一个切换服务状态的Android活动——它让我打开它,如果它是关闭的,如果它是关闭的。
如何查看后台服务是否正在运行?
我想要一个切换服务状态的Android活动——它让我打开它,如果它是关闭的,如果它是关闭的。
当前回答
一个小补语是:
我的目标是知道一个服务是否在运行,如果它没有运行。
调用bindService或调用一个可以被服务捕获的意图不是一个好主意,因为它会在服务未运行时启动服务。
因此,正如miracle2k所建议的,最好是在服务类中有一个静态字段,以知道服务是否已经启动。
为了使它更简洁,我建议用非常非常懒惰的抓取来转换单例中的服务:也就是说,通过静态方法完全没有实例化单例实例。service/singleton的静态getInstance方法只返回已经创建的单例实例。但它并不实际启动或实例化单例本身。服务只能通过正常的服务启动方法启动。
然后,修改单例设计模式,将令人困惑的getInstance方法重命名为类似isInstanceCreated(): boolean方法的方法会更加清晰。
代码如下所示:
public class MyService extends Service
{
private static MyService instance = null;
public static boolean isInstanceCreated() {
return instance != null;
}//met
@Override
public void onCreate()
{
instance = this;
....
}//met
@Override
public void onDestroy()
{
instance = null;
...
}//met
}//class
这个解决方案很优雅,但只有当你可以访问服务类时才有意义,而且只适用于服务的应用程序/包旁边的类。如果你的类在服务应用程序/包之外,那么你可以用Pieter-Jan Van Robays强调的限制来查询ActivityManager。
其他回答
这更适用于Intent Service调试,因为它们会生成一个线程,但也适用于常规服务。我找到这个线程感谢宾
在我的例子中,我摆弄了调试器并找到了线程视图。它看起来有点像微软Word里的项目符号图标。无论如何,您不必在调试器模式下使用它。单击该流程并单击该按钮。任何Intent服务都会在运行时显示出来,至少在模拟器上是这样。
得到它!
你必须调用startService()为你的服务正确注册和传递BIND_AUTO_CREATE是不够的。
Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);
现在是ServiceTools类:
public class ServiceTools {
private static String LOG_TAG = ServiceTools.class.getName();
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;
}
}
这是我提出的一个很好的解决方案,但它只适用于运行在单独进程中的服务。这可以通过在manifest中添加一个android:process属性来实现。
<service
android:name=".ExampleService"
android:process="com.example.service"
...
现在,您的服务将运行在具有给定名称的单独进程中。从你的应用程序你可以打电话
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
activityManager.runningAppProcesses.any { it.processName == "com.example.service" }
如果服务正在运行,则返回true,否则返回false。
重要提示:请注意,它将显示您的服务是何时启动的,但当您禁用它时(即在系统从它解除绑定后),该进程仍然是活跃的。所以你可以简单地强制移除它:
override fun onUnbind(intent: Intent?): Boolean {
stopSelf()
return super.onUnbind(intent)
}
override fun onDestroy() {
super.onDestroy()
killProcess(Process.myPid())
}
然后它就完美地工作了。
放轻松,伙计们……:)
我认为最合适的解决方案是在SharedPreferences中保存一个关于服务是否正在运行的键-值对。
逻辑是很直接的;在你的服务等级的任何理想职位;输入一个布尔值,作为服务是否正在运行的标志。然后在应用程序中任意位置读取这个值。
我在我的应用程序中使用的示例代码如下:
在我的服务类(音频流服务),我执行以下代码时,服务是起;
private void updatePlayerStatus(boolean isRadioPlaying)
{
SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(getString(R.string.str_shared_file_radio_status_key), isRadioPlaying);
editor.commit();
}
然后在我的应用程序的任何活动中,我在以下代码的帮助下检查服务的状态;
private boolean isRadioRunning() {
SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);
return sharedPref.getBoolean(getString(R.string.str_shared_file_radio_status_key), false);
}
没有特殊权限,没有循环……简单的方法,干净的解决方案:)
如果您需要更多的信息,请参考链接
希望这能有所帮助。
/**
* Check if the service is Running
* @param serviceClass the class of the Service
*
* @return true if the service is running otherwise false
*/
public boolean checkServiceRunning(Class<?> serviceClass){
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
{
if (serviceClass.getName().equals(service.service.getClassName()))
{
return true;
}
}
return false;
}