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

PackageManager.getChangedPackages始终返回NULL,无法监测应用安装更新求助

解决Android Oreo+中getChangedPackages返回null的问题

兄弟,我太懂你这困扰了!Android Oreo之后系统对后台操作和包变更监测的限制真的严了不少,getChangedPackages这个方法确实变得不太靠谱,经常会返回null,我之前踩过这个坑,给你分享几个可行的解决方案:

先说说getChangedPackages为啥会失效

  • 系统后台限制:Oreo开始对后台应用的资源访问做了严格管控,你的定时服务如果是普通后台服务,很可能被系统回收,导致无法持续获取变更记录;就算服务活着,系统也可能不会给后台应用完整的包变更数据。
  • 序列号使用错误:这个方法需要传入上一次调用返回的序列号,要是初始序列号传错(比如一直传0),或者没正确更新后续的序列号,也会直接返回null。

靠谱的替代方案

方案1:动态注册包变更广播

Oreo及以上不允许静态注册ACTION_PACKAGE_ADDED、ACTION_PACKAGE_REPLACED这类广播,但我们可以在服务或Activity里动态注册,这样能实时收到包变更通知:

// 定义广播接收器
private BroadcastReceiver packageChangeReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_PACKAGE_ADDED.equals(action) || Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
            Uri data = intent.getData();
            String packageName = data.getSchemeSpecificPart();
            // 这里处理新增/更新的应用逻辑
            Log.d("PackageMonitor", "检测到应用变更:" + packageName);
        }
    }
};

// 在服务启动时注册广播
@Override
public void onCreate() {
    super.onCreate();
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_PACKAGE_ADDED);
    filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
    filter.addDataScheme("package");
    registerReceiver(packageChangeReceiver, filter);
}

// 服务销毁时务必注销广播,避免内存泄漏
@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(packageChangeReceiver);
}

注意:如果是后台服务,建议改成前台服务,不然很容易被系统杀死。

方案2:用JobScheduler监听包变更(符合Android规范)

从Android N开始,JobScheduler支持监听内容Uri,系统会在包发生变更时自动触发你的JobService,这是最符合Oreo+后台规范的方式:

// 构建JobInfo
ComponentName jobComponent = new ComponentName(this, PackageChangeJob.class);
JobInfo jobInfo = new JobInfo.Builder(1001, jobComponent)
        .setTriggerContentUri(new JobInfo.TriggerContentUri(
                Uri.parse("content://com.android.vending.cursor.myapps"),
                JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
        .build();

// 调度Job
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);

然后实现JobService:

public class PackageChangeJob extends JobService {
    @Override
    public boolean onStartJob(JobParameters params) {
        // 在这里执行包变更检测逻辑
        checkUpdatedApps();
        jobFinished(params, false);
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false; // 不需要重试
    }

    private void checkUpdatedApps() {
        // 这里可以获取所有应用列表对比上次记录,或者直接处理变更
        PackageManager pm = getPackageManager();
        // ... 你的检测逻辑
    }
}

方案3:对比应用列表(兜底方案)

如果上面的方法都有适配问题,那就用最稳妥的方式:每隔一段时间(推荐用WorkManager定时执行)获取所有已安装应用的列表,和上次保存的列表对比,找出新增或更新的应用:

private void checkForAppChanges() {
    PackageManager pm = getPackageManager();
    List<ApplicationInfo> allApps = pm.getInstalledApplications(PackageManager.GET_META_DATA);
    // 从SharedPreferences读取上次保存的应用版本信息
    SharedPreferences sp = getSharedPreferences("AppVersions", MODE_PRIVATE);
    Map<String, ?> lastVersions = sp.getAll();

    for (ApplicationInfo app : allApps) {
        try {
            PackageInfo pkgInfo = pm.getPackageInfo(app.packageName, 0);
            int currentVersion = pkgInfo.versionCode;
            String pkgName = app.packageName;

            if (!lastVersions.containsKey(pkgName)) {
                // 新增应用
                handleNewApp(pkgName);
            } else if ((int) lastVersions.get(pkgName) != currentVersion) {
                // 更新应用
                handleUpdatedApp(pkgName);
            }
            // 保存当前版本号
            sp.edit().putInt(pkgName, currentVersion).apply();
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }
}

这个方法虽然没有实时性,但胜在稳定,适合对实时要求不高的场景。

额外注意事项

  • 权限要求:Android 11及以上,要获取所有应用信息需要声明QUERY_ALL_PACKAGES权限(在Manifest中添加),不过要注意Google Play的审核规则,要是你的应用有明确的需求理由,一般会通过。
  • 后台存活:尽量用WorkManager、JobScheduler这类系统推荐的组件,避免用普通后台服务,不然很容易被系统回收。

内容的提问来源于stack exchange,提问作者The Matrix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:42:54