Android檢測(cè)Activity或者Service是否運(yùn)行的方法
需求:假設(shè)我們的APP有3個(gè)頁(yè)面AActivity,BActivity,CActivity,我們的APP需要一直運(yùn)行在前臺(tái)(特殊設(shè)備),要求實(shí)現(xiàn)一個(gè)監(jiān)控服務(wù),來(lái)監(jiān)視APP是否運(yùn)行,如果有3個(gè)頁(yè)面都不運(yùn)行了就說(shuō)明這個(gè)APP已經(jīng)掛掉了,否則說(shuō)明APP在運(yùn)行狀態(tài),不做處理,掛掉之后,我們需要重新啟動(dòng)App來(lái)讓它繼續(xù)處理運(yùn)行狀態(tài),對(duì)外暴露一個(gè)來(lái)停止監(jiān)控服務(wù)的廣播,這樣我們想停止監(jiān)控服務(wù)時(shí),發(fā)送一個(gè)廣播即可。
思路:實(shí)現(xiàn)一個(gè)雙進(jìn)程的監(jiān)控服務(wù),服務(wù)中寫(xiě)一個(gè)定時(shí)器 Timer 來(lái)重復(fù)進(jìn)行檢測(cè)是否正在運(yùn)行,如果否就直接重新啟動(dòng)APP。
1.定義一個(gè)監(jiān)控服務(wù)
package com.anloq.nfcservice; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.util.Log; import com.anloq.MyApplication; import com.anloq.activity.AdActivity; import com.anloq.utils.DetectionASUtils; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; /** * Created by xpf on 2017/6/3 :) * 檢測(cè)APP頁(yè)面是否一直運(yùn)行,不運(yùn)行就直接啟動(dòng) */ public class MonitoringService extends Service { private final static String TAG = "MonitoringService"; private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if ("kill_self".equals(intent.getAction())) { Log.e(TAG, "onReceive:殺死自己的進(jìn)程!"); killMyselfPid(); // 殺死自己的進(jìn)程 } } }; private Timer timer = new Timer(); private TimerTask task = new TimerTask() { @Override public void run() { checkIsAlive(); } }; /** * 檢測(cè)應(yīng)用是否活著 */ private void checkIsAlive() { String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(new Date()); Log.e(TAG, "CustodyService Run: " + format); boolean AIsRunning = CheckUtil.isClsRunning( MonitoringService.this, "com.xpf.monitor", "com.xpf.monitor.activity.AActivity"); boolean BIsRunning = CheckUtil.isClsRunning( MonitoringService.this, "com.xpf.monitor", "com.xpf.monitor.activity.BActivity"); boolean b = (AIsRunning || BIsRunning); boolean CIsRunning = CheckUtil.isClsRunning( MonitoringService.this, "com.xpf.monitor", "com.xpf.monitor.activity.CActivity"); Log.e(TAG, "AIsRunning || BIsRunning is running:" + b + ",CIsRunning:" + CIsRunning); if (!CIsRunning) { if (!b) { //如果界面掛掉直接啟動(dòng)AActivity Intent intent = new Intent(); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClass(MonitoringService.this, AActivity.class); startActivity(intent); } } } @Override public void onCreate() { super.onCreate(); Log.e(TAG, "onCreate: 啟動(dòng)監(jiān)控服務(wù)! "); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("kill_self"); registerReceiver(broadcastReceiver, intentFilter); timer.schedule(task, 0, 10000);// 設(shè)置檢測(cè)的時(shí)間周期(毫秒數(shù)) } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } @Override public IBinder onBind(Intent arg0) { return null; } /** * 殺死自身的進(jìn)程 */ private void killMyselfPid() { int pid = android.os.Process.myPid(); String command = "kill -9 " + pid; Log.e(TAG, "killMyselfPid: " + command); stopService(new Intent(MonitoringService.this, MonitoringService.class)); try { Runtime.getRuntime().exec(command); System.exit(0); } catch (Exception e) { e.printStackTrace(); } } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(broadcastReceiver); if (task != null) { task.cancel(); } if (timer != null) { timer.cancel(); } } }
2.注冊(cè)雙進(jìn)程Service
<service android:name="com.xpf.monitor.MonitoringService" android:enabled="true" android:label="MonitoringService" android:process=":gray"> <intent-filter> <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" /> </intent-filter> </service>
3.檢測(cè)是否活著的工具類CheckUtil
public class CheckUtil { //檢測(cè)service是否在運(yùn)行 public static boolean isServiceWorked(Context context, String serviceName) { ActivityManager myManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ArrayList<ActivityManager.RunningServiceInfo> runningService = (ArrayList<ActivityManager.RunningServiceInfo>) myManager.getRunningServices(Integer.MAX_VALUE); for (int i = 0; i < runningService.size(); i++) { if (runningService.get(i).service.getClassName().toString().equals(serviceName)) { return true; } } return false; } //檢測(cè)activity是否存在再棧頂 public static boolean isForeground(Context context, String PackageName) { ActivityManager myManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> task = myManager.getRunningTasks(1); ComponentName componentInfo = task.get(0).topActivity; if (componentInfo.getPackageName().equals(PackageName)) return true; return false; } /** * 判斷某個(gè)app進(jìn)程是否在運(yùn)行 * * @param context * @param appInfo * @return */ public static boolean isRunningProcess(Context context, String appInfo) { ActivityManager myManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> runningAppPs = myManager.getRunningAppProcesses(); if (runningAppPs != null && runningAppPs.size() > 0) { if (runningAppPs.contains(appInfo)) { return true; } } return false; } /** * 判斷一個(gè)Activity是否正在運(yùn)行 * * @param pkg pkg為應(yīng)用包名 * @param cls cls為類名eg * @param context * @return */ public static boolean isClsRunning(Context context, String pkg, String cls) { ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1); ActivityManager.RunningTaskInfo task = tasks.get(0); if (task != null) { return TextUtils.equals(task.topActivity.getPackageName(), pkg) && TextUtils.equals(task.topActivity.getClassName(), cls); } return false; } }
4.MainActivity中啟動(dòng)監(jiān)控服務(wù)
Intent intent = new Intent(MainActivity.this, MonitoringService.class); intent.setAction("android.intent.action.RESPOND_VIA_MESSAGE"); startService(intent);
5.停止監(jiān)控服務(wù)
發(fā)送一個(gè)殺死進(jìn)程廣播即可,action值如下
Intent intent = new Intent(); intent.setAction("kill_self"); sendOrderedBroadcast(intent, null);
好了,今天就分享到這里了。。。
以上這篇Android檢測(cè)Activity或者Service是否運(yùn)行的方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Android開(kāi)發(fā)MediaCodec和lamemp3多段音頻截取拼接
這篇文章主要為大家介紹了Android開(kāi)發(fā)使用MediaCodec和lamemp3實(shí)現(xiàn)多段音頻截取拼接的編程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04Android 多國(guó)語(yǔ)言value文件夾命名的方法
這篇文章主要介紹了Android 多國(guó)語(yǔ)言value文件夾命名的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03Android彈出DatePickerDialog并獲取值的方法
這篇文章主要為大家詳細(xì)介紹了Android彈出DatePickerDialog并獲取值的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05詳解Android應(yīng)用中DialogFragment的基本用法
Android App中建議使用DialogFragment作為對(duì)話框的容器,DialogFragment類提供了創(chuàng)建對(duì)話框并管理其外觀需要的所有控件,本文主要內(nèi)容便為詳解Android應(yīng)用中DialogFragment的基本用法,而不再需要調(diào)用Dialog的方法需要的朋友可以參考下2016-05-05Android手勢(shì)控制實(shí)現(xiàn)縮放、移動(dòng)圖片
這篇文章主要為大家詳細(xì)介紹了Android手勢(shì)控制實(shí)現(xiàn)縮放、移動(dòng)圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-02-02Android 使用 RxJava2 實(shí)現(xiàn)倒計(jì)時(shí)功能的示例代碼
本篇文章主要介紹了Android 使用 RxJava2 實(shí)現(xiàn)倒計(jì)時(shí)功能的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03Android Splash界面白屏、黑屏問(wèn)題的解決方法
這篇文章主要為大家詳細(xì)介紹了Android Splash界面白屏、黑屏問(wèn)題的解決方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Retrofit網(wǎng)絡(luò)請(qǐng)求和響應(yīng)處理重點(diǎn)分析講解
這篇文章主要介紹了Retrofit網(wǎng)絡(luò)請(qǐng)求和響應(yīng)處理重點(diǎn)分析,在使用?Retrofit發(fā)起網(wǎng)絡(luò)請(qǐng)求時(shí),我們可以通過(guò)定義一個(gè)接口并使用Retrofit的注解來(lái)描述這個(gè)接口中的請(qǐng)求,Retrofit會(huì)自動(dòng)生成一個(gè)實(shí)現(xiàn)該接口的代理對(duì)象2023-03-03Android用戶輸入自動(dòng)提示控件AutoCompleteTextView使用方法
這篇文章主要為大家詳細(xì)介紹了Android用戶輸入自動(dòng)提示控件AutoCompleteTextView的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Android仿微信進(jìn)度彈出框的實(shí)現(xiàn)方法
最近公司項(xiàng)目需要實(shí)現(xiàn)類似微信進(jìn)度條彈出框效果,其實(shí)現(xiàn)方法并不難,下面給大家介紹下Android仿微信進(jìn)度彈出框的實(shí)現(xiàn)方法,需要的朋友參考下吧2017-01-01