需求:編寫一個程式能夠監聽到一些app曾經打開并且在程式裡面顯示是否打開過,比如com.liulishuo.engzo(英語流利說app)的打開;
思路:
首先要有一個Service在背景能夠知道任務棧頂端程式是否是com.liulishuo.engzo這樣的包名;
如果指定的一個app中包含任務棧頂端的包名,那麼就把這個包名和true值存儲在SharedPreferences中;
這些app的包名用bindService方式動态傳遞Service中;
涉及到的知識點:正在running的任務棧知識、Service的bind知識;
WatchDogService.java
public class WatchDogService extends Service {
private List<String> packageList = new ArrayList<>();
private static final String TAG = "WatchDogService";
private static boolean flag = true;// 線程退出的标記
private ActivityManager am;
private SharedPreferences isOpenSP;
private SharedPreferences.Editor editor;
@Override
public void onCreate() {
super.onCreate();
// 服務一旦啟動要在背景監視任務棧最頂端應用
am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
isOpenSP = getSharedPreferences("isOpen", Context.MODE_PRIVATE);
editor = isOpenSP.edit();
new Thread() {
@Override
public void run() {
super.run();
while (flag) {
synchronized (WatchDogService.class) {
List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks();
ActivityManager.RunningTaskInfo runningTaskInfo = runningTasks.get();
ComponentName topActivity = runningTaskInfo.topActivity;
String packageName = topActivity.getPackageName();
if (packageList.contains(packageName)) {
// 判斷packageName是否已打開
boolean isOpen = isOpenSP.getBoolean(packageName, false);
if (!isOpen) {
editor.putBoolean(packageName, true);
editor.apply();
Log.i(TAG, packageName + "正在存儲");
}
}
SystemClock.sleep();
}
Log.i(TAG, "服務在循環");
}
}
}.start();
}
@Override
public void onDestroy() {
super.onDestroy();
flag = false;
}
public class MyBinder extends Binder implements IMyBinder {
@Override
public void setPackageNames(List<String> packageNames) {
packageList.clear();
packageList.addAll(packageNames);
}
}
MyBinder myBinder = new MyBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView textView1;
private SharedPreferences isOpennSP;
private IMyBinder iMyBinder;
private List<String> packageList = new ArrayList<>();
private MyServiceConnection connection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView1 = (TextView) findViewById(R.id.tv1);
isOpennSP = getSharedPreferences("isOpen", Context.MODE_PRIVATE);
initData();
connection = new MyServiceConnection();
bindService(new Intent(this, WatchDogService.class), connection, Context.BIND_AUTO_CREATE);
}
private void renderView() {
textView1.setText(isOpennSP.getBoolean(packageList.get(), false) ? packageList.get() + "已打開" : packageList.get() + "未打開");
}
@Override
protected void onResume() {
super.onResume();
renderView();
}
private void initData() {
packageList.clear();
packageList.add("com.liulishuo.engzo");
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
public class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
iMyBinder = (IMyBinder) iBinder;
iMyBinder.setPackageNames(packageList);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
}
IMyBinder.java
public interface IMyBinder {
void setPackageNames(List<String> packageNames);
}
MyApplication.java
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
startService(new Intent(this, WatchDogService.class));
}
}
MainActivity中的bindService方法中攜帶了connection對象,一旦綁定成功會回調MyServiceConnection類中onServiceConnected方法,我們代碼中用到的是第二個參數iBinder對象,這個對象是WatchDogService傳回給我們的;
public class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
iMyBinder = (IMyBinder) iBinder;
iMyBinder.setPackageNames(packageList);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
再看WatchDogService中的onBind方法中傳回了MyBinder對象
public class MyBinder extends Binder implements IMyBinder {
@Override
public void setPackageNames(List<String> packageNames) {
packageList.clear();
packageList.addAll(packageNames);
}
}
MyBinder myBinder = new MyBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
這個myBinder對象就是從onBind方法中傳回的,給了Activity中的MyServiceConnection 中的onServiceConnected方法的第二個參數,我們就是通過這個參數在Activity中去給Service中的packageNames集合指派的。