You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅Android 6及以上三星设备抛出SecurityException问题求助

分析与解决方案:三星Android 6+设备调用getLaunchIntentForPackage抛出SecurityException的问题

首先,从异常堆栈能定位到核心问题:这个SecurityException并不是直接来自getLaunchIntentForPackage本身,而是三星定制ROM在执行ApplicationPackageManager.getHiddenList时,调用Settings.Secure.getInt访问系统设置内容提供者时触发的权限校验失败。

为什么只有三星Android 6+设备会出现这个问题?

Android 6引入运行时权限后,三星在自家的TouchWiz/One UI ROM里对应用隐藏机制做了自定义强化:

  • 原生Android的应用隐藏逻辑不会依赖Settings.Secure的特定字段,但三星额外增加了通过系统设置存储隐藏应用列表的逻辑;
  • 当非系统应用调用PackageManager的相关查询方法(比如getLaunchIntentForPackage、queryIntentActivities)时,三星的ROM会尝试访问这个自定义的系统设置内容提供者,而普通应用没有READ_SECURE_SETTINGS这个系统级权限,因此抛出SecurityException;
  • 不同三星机型的ROM版本(比如S5的Android 6 TouchWiz vs J7的高版本One UI)对权限校验的触发时机不同,导致你在S5加try-catch能解决,但J7的异常会在其他调用PackageManager的位置出现。

不依赖try-catch的解决方案

与其被动捕获异常,不如主动绕过三星的权限校验逻辑,以下是两种可行方案:

方案1:手动构造启动Intent,绕过原生getLaunchIntentForPackage

原生方法内部会触发三星的隐藏应用检查,我们可以直接查询该包名下的Launcher Activity,自己构造启动Intent:

public static Intent getSafeLaunchIntent(Context context, String packageName) {
    PackageManager pm = context.getPackageManager();
    // 查询所有属于LAUNCHER类别的Activity
    Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
    launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    
    List<ResolveInfo> resolveInfos = null;
    try {
        resolveInfos = pm.queryIntentActivities(launcherIntent, PackageManager.MATCH_ALL);
    } catch (SecurityException e) {
        // 兜底捕获,避免极端情况崩溃
        e.printStackTrace();
    }
    
    if (resolveInfos != null) {
        for (ResolveInfo info : resolveInfos) {
            if (info.activityInfo.packageName.equals(packageName)) {
                // 找到目标包的Launcher Activity,构造Intent
                Intent launchIntent = new Intent(Intent.ACTION_MAIN);
                launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
                launchIntent.setComponent(new ComponentName(
                    info.activityInfo.packageName,
                    info.activityInfo.name
                ));
                launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                return launchIntent;
            }
        }
    }
    
    // 如果没找到,再尝试原生方法(加兜底try-catch)
    try {
        return pm.getLaunchIntentForPackage(packageName);
    } catch (SecurityException e) {
        e.printStackTrace();
        return null;
    }
}

方案2:针对三星设备做特殊逻辑判断

可以先检测当前设备是否为三星,再针对性地使用不同的Intent获取逻辑:

public static boolean isSamsungDevice() {
    return "samsung".equalsIgnoreCase(Build.MANUFACTURER);
}

// 在调用时:
Intent launchIntent;
if (isSamsungDevice()) {
    launchIntent = getSafeLaunchIntent(context, packageName);
} else {
    launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
}

补充说明

  • 为什么S5加try-catch有效而J7不行?因为不同三星ROM的权限校验触发点不同:S5的异常只在getLaunchIntentForPackage内部抛出,而J7的异常可能在queryIntentActivities等更早的步骤触发,所以只在一个地方加try-catch覆盖不全;
  • READ_SECURE_SETTINGS权限是系统级权限,普通应用无法通过常规渠道获取,所以不要试图申请这个权限来解决问题。

内容的提问来源于stack exchange,提问作者Mohit Agrawal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:45:10