feat(app): 禁用应用启动拦截支持接口下发清单并实时刷新

This commit is contained in:
tongtong committed 2026-10-27 11:10:47 +08:00
1 parent 1d5d7c790a
commit 82db4c359c
4 files changed
+97 -7

No files matched your search

+2 -2
View File
@@ -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");