Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播

简介: Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播

Android 高版本引入了一些限制和变化,不像以前7.1以下的方便,对我们客制化搬砖效率和用户都有一定的影响。例如,Android 8+限制了后台应用启动活动的能力,增加了后台位置访问权限的要求,以及禁止了手动安装的应用在未打开的情况下接收开机广播。

本文将介绍如何通过修改Android源码来实现以下三个目标:

  • 自定义开机广播:在系统启动完成后发送一个自定义的广播,让自定义的应用可以接收并执行相应的操作。
  • 禁止后台服务:取消对后台应用启动服务的限制,让任何应用都可以在后台运行服务。
  • 运行手动安装应用接收开机广播:允许手动安装的应用在未打开的情况下接收系统的开机广播,让它们可以在开机后自动启动。

自定义开机广播

背景知识

开机广播是一种特殊的系统广播,它在系统启动完成后发送给所有注册了android.intent.action.BOOT_COMPLETED过滤器的应用。开机广播可以让应用在开机后执行一些初始化或定期的任务,例如更新数据,启动服务,设置闹钟等。

修改方法

要实现自定义开机广播,我们需要修改两个文件:

  • frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:这个文件是ActivityManagerService类的源码,它负责管理系统中所有活动、进程、服务和广播等组件。我们需要修改它的broadcastIntentLocked方法,这个方法是用来发送广播的核心方法。
  • frameworks/base/services/core/java/com/android/server/am/UserController.java:这个文件是UserController类的源码,它负责管理系统中所有用户和用户相关的操作。我们需要修改它的finishUserUnlockedCompleted方法,这个方法是在用户解锁完成后调用的。

具体的修改步骤如下:

  1. ActivityManagerService.java中找到broadcastIntentLocked方法,在第15846行添加一行代码:
|| "com.ln28.intent.action.BOOT_COMPLETED".equals(action)

这样就可以让我们自定义的开机广播通过系统的保护检查,不被拒绝发送。

  1. 在同一个文件中,在第15906行注释掉以下代码:
if (callerApp != null) {
    Log.wtf(TAG, "Sending non-protected broadcast " + action
                    + " from system " + callerApp.toShortString() + " pkg " + callerPackage,
            new Throwable());
} else {
    Log.wtf(TAG, "Sending non-protected broadcast " + action
                    + " from system uid " + UserHandle.formatUid(callingUid)
                    + " pkg " + callerPackage,
            new Throwable());
}

这样就可以避免发送我们自定义的开机广播时产生不必要的警告日志。

  1. UserController.java中找到finishUserUnlockedCompleted方法,在第729行添加以下代码:
///ln28 add custom broadcast cast  
final Intent custombootIntent = new Intent("com.ln28.intent.action.BOOT_COMPLETED", null);
custombootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
custombootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
            | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
            | Intent.FLAG_RECEIVER_OFFLOAD);
final int callinguid = Binder.getCallingUid();
final int callingpid = Binder.getCallingPid();
FgThread.getHandler().post(() -> {
    mInjector.loadUserRecents(userId);
});
FgThread.getHandler().post(() -> {
    mInjector.broadcastIntent(custombootIntent,
            null, null, 0, null, null,
            null, AppOpsManager.OP_NONE,
            null, true, false, MY_PID, SYSTEM_UID, callinguid,
            callingpid, userId);
}); 
///ln28 add custom broadcast cast

这样就可以在用户解锁完成后发送我们自定义的开机广播,其中com.ln28.intent.action.BOOT_COMPLETED是我们自定义的广播的动作,userId是当前用户的ID,callinguidcallingpid是调用者的UID和PID,MY_PIDSYSTEM_UID是系统的PID和UID,其他参数可以参考broadcastIntentLocked方法的注释。

修改效果

修改完成后,我们需要重新编译并刷入系统。可以在任何应用中注册一个广播接收器,用来接收我们自定义的开机广播。例如,我们可以在AndroidManifest.xml中添加以下代码:

<receiver android:name=".CustomBootReceiver">
    <intent-filter>
        <action android:name="com.ln28.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

然后,在CustomBootReceiver类中实现onReceive方法,用来处理我们自定义的开机广播。例如,我们可以在onReceive方法中打印一条日志:

public class CustomBootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("CustomBootReceiver", "Received custom boot completed broadcast");
    }
}

这样,当我们开机并解锁后,就可以在日志中看到以下信息:

08-07 17:00:11.062  1229  1229 D CustomBootReceiver: Received custom boot completed broadcast

这说明我们成功地实现了自定义开机广播的功能。

注意: 测试发现自定义开机广播比系统自带的开机广播 要早1分钟!!

禁止后台服务和

背景知识

后台服务是一种在后台运行的组件,它可以执行一些不需要用户交互的长时间运行的任务。后台服务通常通过调用startServicebindService方法来启动。

但是,从Android 8.0(API级别26)开始,系统对后台服务的启动做了一些限制。具体来说,当应用处于后台时(即没有任何可见的活动),它不能直接启动服务。如果它尝试这样做,系统会抛出一个IllegalStateException异常,并显示以下错误信息:

java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.xxx/.MyService }: app is in background uid UidRecord{...}

为了避免这个异常,应用需要使用以下两种方式之一来启动服务:

  • 使用前台服务:前台服务是一种显示一个通知栏图标的服务,它表明该服务正在执行一些用户关心的操作。要使用前台服务,应用需要在服务启动后调用startForeground方法,并传递一个有效的通知对象。
  • 使用作业调度器:作业调度器是一种让应用在满足一定条件时执行一些任务的机制。要使用作业调度器,应用需要创建一个继承自JobService的类,并在其中实现任务的逻辑。然后,应用需要使用JobScheduler类来创建一个JobInfo对象,并指定任务的触发条件和执行策略。最后,应用需要使用schedule方法来提交任务给系统

修改方法

要实现禁止后台服务的功能,我们只需要修改一个文件:

  • frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:这个文件是ActivityManagerService类的源码,它负责管理系统中所有活动、进程、服务和广播等组件。我们需要修改它的appRestrictedInBackgroundLocked方法,这个方法是用来检查应用是否可以在后台启动服务的。

具体的修改步骤如下:

  1. ActivityManagerService.java中找到appRestrictedInBackgroundLocked方法,在第6275行注释掉以下代码:
if (packageTargetSdk >= Build.VERSION_CODES.O) {
    if (DEBUG_BACKGROUND_CHECK) {
        Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
    }
    return ActivityManager.APP_START_MODE_DELAYED_RIGID;
}

这样就可以取消对目标SDK为O+的应用的后台服务启动限制。

修改效果

修改完成后,我们需要重新编译并刷入系统。然后,我们可以在任何应用中创建一个后台服务,并在AndroidManifest.xml中声明它。例如,我们可以创建一个MyService类,继承自Service,并在其中打印一条日志:

public class MyService extends Service {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("MyService", "Service started");
        return START_STICKY;
    }
}

然后,在AndroidManifest.xml中添加以下代码:

<service android:name=".MyService" />

这样,当我们在应用中调用以下代码时:

startService(new Intent(this, MyService.class));

就可以在日志中看到以下信息:

08-07 17:41:14.125  1229  1229 D MyService: Service started

这说明我们成功地实现了禁止后台服务的功能。

运行手动安装应用接收开机广播

背景知识

手动安装应用是指通过非官方渠道(例如APK文件)安装的应用,它们通常不受系统的信任和管理。手动安装应用在Android 11中受到了一些限制,例如不能在后台访问剪贴板,不能请求敏感权限,以及不能在未打开的情况下接收开机广播。

开机广播是一种特殊的系统广播,它在系统启动完成后发送给所有注册了android.intent.action.BOOT_COMPLETED过滤器的应用。开机广播可以让应用在开机后执行一些初始化或定期的任务,例如更新数据,启动服务,设置闹钟等。

修改方法

要实现运行手动安装应用接收开机广播的功能,我们需要修改一个文件:

  • frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:这个文件是ActivityManagerService类的源码,它负责管理系统中所有活动、进程、服务和广播等组件。

具体的修改步骤如下:

  1. 在同一个文件中,在第15957行注释掉以下代码:
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

并在下一行添加以下代码:

intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);

这样就可以让后台服务启动时发送的广播包含已停止的应用,让它们可以接收到广播并启动服务。

这样就可以让所有应用都不受安装来源的限制,无论它们是不是即时应用。

修改效果

修改完成后,我们需要重新编译并刷入系统。可以在任何手动安装的应用中注册一个广播接收器,用来接收系统的开机广播。例如,我们可以在AndroidManifest.xml中添加以下代码:

<receiver android:name=".BootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

然后,在BootReceiver类中实现onReceive方法,用来处理系统的开机广播。例如,我们可以在onReceive方法中打印一条日志:

public class BootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("SystemBootReceiver", "Received boot completed broadcast");
    }
}

这样,当我们开机并解锁后,就可以在日志中看到以下信息:

08-07 17:01:14.175  1229  1229 D SystemBootReceiver: Received system boot completed broadcast

这说明我们成功地实现了运行手动安装应用接收开机广播的功能。

总结

本文介绍了如何通过修改Android源码来实现三个目标:

  • 自定义开机广播:在系统启动完成后发送一个自定义的广播,让感兴趣的应用可以接收并执行相应的操作。
  • 禁止后台服务:取消对后台应用启动服务的限制,让任何应用都可以在后台运行服务。
  • 运行手动安装应用接收开机广播:允许手动安装的应用在未打开的情况下接收系统的开机广播,让它们可以在开机后自动启动。
相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
11月前
|
存储 消息中间件 人工智能
【03】AI辅助编程完整的安卓二次商业实战-本地构建运行并且调试-二次开发改注册登陆按钮颜色以及整体资源结构熟悉-优雅草伊凡
【03】AI辅助编程完整的安卓二次商业实战-本地构建运行并且调试-二次开发改注册登陆按钮颜色以及整体资源结构熟悉-优雅草伊凡
308 3
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
796 64
|
11月前
|
存储 API Android开发
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
1006 4
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
|
11月前
|
Linux 测试技术 语音技术
【车载Android】模拟Android系统的高负载环境
本文介绍如何将Linux压力测试工具Stress移植到Android系统,用于模拟高负载环境下的CPU、内存、IO和磁盘压力,帮助开发者优化车载Android应用在多任务并发时的性能问题,提升系统稳定性与用户体验。
895 6
|
11月前
|
Java 数据库 Android开发
基于Android的电子记账本系统
本项目研究开发一款基于Java与Android平台的开源电子记账系统,采用SQLite数据库和Gradle工具,实现高效、安全、便捷的个人财务管理,顺应数字化转型趋势。
|
存储 Android开发 数据安全/隐私保护
Thanox安卓系统增加工具下载,管理、阻止、限制后台每个APP运行情况
Thanox是一款Android系统管理工具,专注于权限、后台启动及运行管理。支持应用冻结、系统优化、UI自定义和模块管理,基于Xposed框架开发,安全可靠且开源免费,兼容Android 6.0及以上版本。
1515 4
|
移动开发 安全 Android开发
构建高效Android应用:Kotlin协程的实践与优化策略
【5月更文挑战第30天】 在移动开发领域,性能优化始终是关键议题之一。特别是对于Android开发者来说,如何在保证应用流畅性的同时,提升代码的执行效率,已成为不断探索的主题。近年来,Kotlin语言凭借其简洁、安全和实用的特性,在Android开发中得到了广泛的应用。其中,Kotlin协程作为一种新的并发处理机制,为编写异步、非阻塞性的代码提供了强大工具。本文将深入探讨Kotlin协程在Android开发中的应用实践,以及如何通过协程优化应用性能,帮助开发者构建更高效的Android应用。
|
API 调度 Android开发
打造高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第27天】在移动开发领域,性能优化和响应速度是衡量应用质量的关键因素。随着Kotlin语言的普及,协程作为其核心特性之一,为Android开发者提供了一种全新的并发处理方式。本文深入探讨了Kotlin协程在Android应用开发中的优势,并通过实例演示如何在实际项目中有效利用协程提升应用性能和用户体验。
|
移动开发 Android开发 开发者
构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第21天】在移动开发领域,性能优化和流畅的用户体验是至关重要的。随着Kotlin语言在Android平台的广泛采纳,其并发处理的强大工具—协程(Coroutines),已成为提升应用响应性和效率的关键因素。本文将深入分析Kotlin协程的核心原理,探讨其在Android开发中的优势,并通过实例演示如何有效利用协程来优化应用性能,打造更加流畅的用户体验。
247 4
|
物联网 区块链 Android开发
构建高效Android应用:Kotlin与Jetpack的实践之路未来技术的融合潮流:区块链、物联网与虚拟现实的交汇点
【5月更文挑战第30天】 在移动开发领域,效率和性能始终是开发者追求的核心。随着技术的不断进步,Kotlin语言以其简洁性和现代化特性成为Android开发的新宠。与此同时,Jetpack组件为应用开发提供了一套经过实践检验的库、工具和指南,旨在简化复杂任务并帮助提高应用质量。本文将深入探索如何通过Kotlin结合Jetpack组件来构建一个既高效又稳定的Android应用,并分享在此过程中的最佳实践和常见陷阱。

热门文章

最新文章