feat(app): 禁用应用启动拦截支持接口下发清单并实时刷新
This commit is contained in:
1 parent
1d5d7c790a
commit
82db4c359c
4 files changed
+97
-7
No files matched your search
+2
-2
@@ -18,8 +18,8 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.aoleyun.sn"
|
||||
versionCode 254
|
||||
versionName "1.6.1023"
|
||||
versionCode 256
|
||||
versionName "1.6.1026"
|
||||
|
||||
//There are no CERT files because If the mini sdk version is 23+, the AGP will ignore the V1 scheme signature.
|
||||
minSdkVersion 24
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
package com.aoleyun.sn.hook;
|
||||
|
||||
import android.app.IActivityController;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.aoleyun.sn.comm.CommonConfig;
|
||||
@@ -9,17 +16,101 @@ import com.aoleyun.sn.utils.ApkUtils;
|
||||
import com.hjq.toast.Toaster;
|
||||
import com.tencent.mmkv.MMKV;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class AoleyunActivityController extends IActivityController.Stub {
|
||||
private static final String TAG = "AoleyunActivityController";
|
||||
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
/**
|
||||
* 当前需要禁止启动的包名:本地默认禁用({@link ApkUtils#DEFAULT_DISABLE_APP_MAP})
|
||||
* + 接口下发禁用(getSnAppAttr 在线禁用、getIconControl 应用管控禁用),
|
||||
* 统一由 {@link ApkUtils#getKeepDisablePkgs(Context)} 汇总。
|
||||
* <p>
|
||||
* activityStarting 每次启动 activity 都会被系统同步回调,这里做进程内缓存,
|
||||
* 避免每次都跨进程读 Settings.Global;清单变化由 Settings 的 ContentObserver 刷新。
|
||||
*/
|
||||
private volatile Set<String> mDisablePkgs = Collections.emptySet();
|
||||
|
||||
/**
|
||||
* 禁用清单变化时刷新缓存(清单由本进程写入 Settings.Global,写入后系统会通知这里)
|
||||
*/
|
||||
private final ContentObserver mDisablePkgsObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
refreshDisablePkgs();
|
||||
}
|
||||
};
|
||||
|
||||
public AoleyunActivityController(Context context) {
|
||||
mContext = context == null ? null : context.getApplicationContext();
|
||||
refreshDisablePkgs();
|
||||
registerDisablePkgsObserver();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新需要禁止启动的包名
|
||||
*/
|
||||
private void refreshDisablePkgs() {
|
||||
if (mContext == null) {
|
||||
return;
|
||||
}
|
||||
Set<String> pkgs = new HashSet<>(ApkUtils.getKeepDisablePkgs(mContext));
|
||||
//内置的禁用应用(disableSystemapp)同样不允许启动
|
||||
pkgs.addAll(ApkUtils.disableSystemapp);
|
||||
mDisablePkgs = Collections.unmodifiableSet(pkgs);
|
||||
Log.e(TAG, "refreshDisablePkgs: " + pkgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听禁用清单对应的 Settings 项
|
||||
*/
|
||||
private void registerDisablePkgsObserver() {
|
||||
if (mContext == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
resolver.registerContentObserver(Settings.Global.getUriFor(CommonConfig.AOLE_ACTION_DISABLE_APP),
|
||||
false, mDisablePkgsObserver);
|
||||
resolver.registerContentObserver(Settings.Global.getUriFor(CommonConfig.AOLE_ACTION_HIDE_DESKTOP_ICON),
|
||||
false, mDisablePkgsObserver);
|
||||
resolver.registerContentObserver(Settings.Global.getUriFor(CommonConfig.AOLE_ACTION_SHOW_DESKTOP_ICON),
|
||||
false, mDisablePkgsObserver);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "registerDisablePkgsObserver: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提示应用已被禁用。
|
||||
* <p>
|
||||
* activityStarting 运行在 binder 线程上,Toast 对该线程有 Looper 要求,
|
||||
* 因此这里兜底捕获异常,避免拦截失败变成进程异常。
|
||||
*/
|
||||
private void showDisableTip() {
|
||||
try {
|
||||
Toaster.show("应用已被禁用");
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "showDisableTip: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean activityStarting(Intent intent, String pkg) {
|
||||
Log.e(TAG, "activityStarting: " + pkg + ", intent= " + intent);
|
||||
|
||||
if (ApkUtils.disableSystemapp.contains(pkg)) {
|
||||
Toaster.show("应用已被禁用");
|
||||
if (TextUtils.isEmpty(pkg)) {
|
||||
return true;
|
||||
}
|
||||
//本地默认禁用应用 + 接口下发的禁用应用,禁止启动
|
||||
if (mDisablePkgs.contains(pkg)) {
|
||||
Log.e(TAG, "activityStarting: 应用已被禁用,拦截启动 " + pkg);
|
||||
showDisableTip();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -72,4 +163,3 @@ public class AoleyunActivityController extends IActivityController.Stub {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ public class MainService extends BaseService implements NetworkUtils.OnNetworkSt
|
||||
|
||||
IActivityManager activityManager = ActivityManagerNative.getDefault();
|
||||
try {
|
||||
activityManager.setActivityController(new AoleyunActivityController(), false);
|
||||
activityManager.setActivityController(new AoleyunActivityController(MainService.this), false);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "setActivityController: " + e.getMessage());
|
||||
}
|
||||
|
||||
@@ -393,7 +393,7 @@ public class ApkUtils {
|
||||
this.add("org.chromium.chrome");
|
||||
this.add("com.onyx.appmarket");
|
||||
this.add("com.onyx.aiassistant");
|
||||
this.add("com.onyx.android.production.test");
|
||||
// this.add("com.onyx.android.production.test");
|
||||
this.add("com.onyx.dict");
|
||||
this.add("com.onyx.mail");
|
||||
this.add("com.onyx.musicplayer");
|
||||
|
||||
Reference in new issue
Block a user