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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 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源码来实现三个目标:

  • 自定义开机广播:在系统启动完成后发送一个自定义的广播,让感兴趣的应用可以接收并执行相应的操作。
  • 禁止后台服务:取消对后台应用启动服务的限制,让任何应用都可以在后台运行服务。
  • 运行手动安装应用接收开机广播:允许手动安装的应用在未打开的情况下接收系统的开机广播,让它们可以在开机后自动启动。
相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
相关文章
|
1月前
|
存储 消息中间件 人工智能
【03】AI辅助编程完整的安卓二次商业实战-本地构建运行并且调试-二次开发改注册登陆按钮颜色以及整体资源结构熟悉-优雅草伊凡
【03】AI辅助编程完整的安卓二次商业实战-本地构建运行并且调试-二次开发改注册登陆按钮颜色以及整体资源结构熟悉-优雅草伊凡
75 3
|
5月前
|
Android开发 UED 计算机视觉
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
本文介绍了一款受游戏“金铲铲之战”启发的Android自定义View——线条等待动画的实现过程。通过将布局分为10份,利用`onSizeChanged`测量最小长度,并借助画笔绘制动态线条,实现渐变伸缩效果。动画逻辑通过四个变量控制线条的增长与回退,最终形成流畅的等待动画。代码中详细展示了画笔初始化、线条绘制及动画更新的核心步骤,并提供完整源码供参考。此动画适用于加载场景,提升用户体验。
477 5
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
|
1月前
|
存储 API Android开发
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
105 4
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
|
5月前
|
XML Java Android开发
Android自定义view之网易云推荐歌单界面
本文详细介绍了如何通过自定义View实现网易云音乐推荐歌单界面的效果。首先,作者自定义了一个圆角图片控件`MellowImageView`,用于绘制圆角矩形图片。接着,通过将布局放入`HorizontalScrollView`中,实现了左右滑动功能,并使用`ViewFlipper`添加图片切换动画效果。文章提供了完整的代码示例,包括XML布局、动画文件和Java代码,最终展示了实现效果。此教程适合想了解自定义View和动画效果的开发者。
251 65
Android自定义view之网易云推荐歌单界面
|
5月前
|
XML 前端开发 Android开发
一篇文章带你走近Android自定义view
这是一篇关于Android自定义View的全面教程,涵盖从基础到进阶的知识点。文章首先讲解了自定义View的必要性及简单实现(如通过三个构造函数解决焦点问题),接着深入探讨Canvas绘图、自定义属性设置、动画实现等内容。还提供了具体案例,如跑马灯、折线图、太极图等。此外,文章详细解析了View绘制流程(measure、layout、draw)和事件分发机制。最后延伸至SurfaceView、GLSurfaceView、SVG动画等高级主题,并附带GitHub案例供实践。适合希望深入理解Android自定义View的开发者学习参考。
581 84
|
3月前
|
存储 Android开发 数据安全/隐私保护
Thanox安卓系统增加工具下载,管理、阻止、限制后台每个APP运行情况
Thanox是一款Android系统管理工具,专注于权限、后台启动及运行管理。支持应用冻结、系统优化、UI自定义和模块管理,基于Xposed框架开发,安全可靠且开源免费,兼容Android 6.0及以上版本。
235 4
|
5月前
|
前端开发 Android开发 UED
讲讲Android为自定义view提供的SurfaceView
本文详细介绍了Android中自定义View时使用SurfaceView的必要性和实现方式。首先分析了在复杂绘制逻辑和高频界面更新场景下,传统View可能引发卡顿的问题,进而引出SurfaceView作为解决方案。文章通过Android官方Demo展示了SurfaceView的基本用法,包括实现`SurfaceHolder.Callback2`接口、与Activity生命周期绑定、子线程中使用`lockCanvas()`和`unlockCanvasAndPost()`方法完成绘图操作。
126 3
|
Java 调度 Android开发
android体系课-系统启动流程-之zygote进程启动过程源码分析
笔者刚开始学习Android的时候也和大部分同学一样,只会使用一些应用层面的知识,对于一些比较常见的开源框架如<mark>RxJava</mark>,<mark>OkHttp</mark>,<mark>Retrofit</mark>,以及后来谷歌推出的<mark>协程</mark>等,都只在使用层面,对于他们<mark>内部原理</mark>,基本没有去了解觉得够用就可以了,又比如Activity,Service等四大组件的使用原理,系统开机过程,Launcher启动过程等知之甚少,知其然而不知其所以然,结果就是出现某些问题,不知道从哪里找原因,只能依赖万能的百度,但是百度看多了,你会发现自己
|
Java 调度 Android开发
android体系课-系统启动流程-之SystemServer启动过程源码分析
笔者刚开始学习Android的时候也和大部分同学一样,只会使用一些应用层面的知识,对于一些比较常见的开源框架如<mark>RxJava</mark>,<mark>OkHttp</mark>,<mark>Retrofit</mark>,以及后来谷歌推出的<mark>协程</mark>等,都只在使用层面,对于他们<mark>内部原理</mark>,基本没有去了解觉得够用就可以了,又比如Activity,Service等四大组件的使用原理,系统开机过程,Launcher启动过程等知之甚少,知其然而不知其所以然,结果就是出现某些问题,不知道从哪里找原因,只能依赖万能的百度,但是百度看多了,你会发现自己

热门文章

最新文章

下一篇
oss教程