android-开机自启动

原文地址 zhuanlan.zhihu.com

残枫cps残枫cps

​目录收起跳过锁屏界面直接显示到界面广播判断包名所对应的应用是否安装在SD卡上获取自启动管理页面的Intent

由于安全原因,自2021年开始,所有的EMUI都不再支持 "应用启动 "设置的意图了

Android 10 (API 级别 29) 及更高版本对后台应用可启动 Activity进行限制。Android10中, 当App的Activity不在前台时,其启动Activity会被系统拦截,导致无法启动。
向用户申请 SYSTEM_ALERT_WINDOW权限,系统就不会拦截该程序后台启动的Activity。
示例代码如下:

//AndroidManifest中

//检查是否已经授予权限

if (!Settings.canDrawOverlays(this)) {
//若未授权则请求权限
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
}

其中,Settings.canDrawOverlays(this)方法是在API level 23也就是Android M中新加入的用于检查当前是否拥有出现在“出现在其他应用上”权限的方法。在6.0以前的系统版本,悬浮窗权限是默认开启的,直接使用即可。

跳过锁屏界面直接显示到界面

int flags = WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
getWindow().addFlags(flags);

添加组件

ComponentName localComponentName = new ComponentName(MyApplication.getContext(), BootReceiver.class);
int i = MyApplication.getContext().getPackageManager().getComponentEnabledSetting(localComponentName);
Log.e("自启动 >>>>", "onCreate: " + i);

以下是直接打开系统页面。若是有的android系统找不到应用设置页面(如定制系统)

Intent intent = ApplicationUtil.getAutostartSettingIntent(this);
tartActivity(intent);

/**
* 获取自启动管理页面的Intent
*
* @param context context
* @return 返回自启动管理页面的Intent
*/
public static Intent getAutostartSettingIntent(Context context) {
ComponentName componentName = null;
String brand = Build.MANUFACTURER;
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
switch (brand.toLowerCase()) {
case "samsung"😕/三星
componentName = new ComponentName("com.samsung.android.sm", "com.samsung.android.sm.app.dashboard.SmartManagerDashBoardActivity");
break;
case "huawei"😕/华为
Log.e("自启动管理 >>>>", "getAutostartSettingIntent: 华为");
// componentName = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity");
componentName = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity");//目前看是通用的
break;
case "xiaomi"😕/小米
// componentName = new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity");
componentName = new ComponentName("com.android.settings","com.android.settings.BackgroundApplicationsManager");
break;
case "vivo"😕/VIVO
// componentName = new ComponentName("com.iqoo.secure", "com.iqoo.secure.safaguard.PurviewTabActivity");
componentName = new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity");
break;
case "oppo"😕/OPPO
// componentName = new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity");
componentName = new ComponentName("com.coloros.oppoguardelf", "com.coloros.powermanager.fuelgaue.PowerUsageModelActivity");
break;
case "yulong":
case "360"😕/360
componentName = new ComponentName("com.yulong.android.coolsafe", "com.yulong.android.coolsafe.ui.activity.autorun.AutoRunListActivity");
break;
case "meizu"😕/魅族
componentName = new ComponentName("com.meizu.safe", "com.meizu.safe.permission.SmartBGActivity");
break;
case "oneplus"😕/一加
componentName = new ComponentName("com.oneplus.security", "com.oneplus.security.chainlaunch.view.ChainLaunchAppListActivity");
break;
case "letv"😕/乐视
intent.setAction("com.letv.android.permissionautoboot");
default://其他
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
break;
}
intent.setComponent(componentName);
return intent;
}

广播

安卓实现开机自启动的思路就是注册广播。
(1)首先清单文件AndroidManifest.xml中添加权限:
广播的权限

**注册广播** (2)其次注册广播:


app安装到内部存储

请检查你的手机是不是设置了app安装首选位置是sd卡,据说安装到sd卡的话,因为手机启动成功后(发送了启动完成的广播后)才加载sd卡,所以app接收不到广播。如果是的话,把app安装到内部存储试试。如果不懂得设置的话,那么直接在AndroidManifest.xml文件中设置安装路径,在manifest的根节点中加入android:installLocation="internalOnly"。如下:

遇到问题:
一切准备就绪,然后接下来就开始遇到各种问题了,代码都没问题但是如果app依旧无法自启动,可以从以下几点找问题:
(1)广播必须要静态注册
(2)网上有的人说app无法自启是因为Receiver类和activity类不在一个包下,移到一个包下就可以了,但是我没遇到这种情况。
(3)应用安装到了sd卡内,安装在sd卡内的应用是收不到BOOT_COMPLETED广播的。
具体可以使用以下方法进行验证:

判断包名所对应的应用是否安装在SD卡上

/**

  • 判断包名所对应的应用是否安装在SD卡上
  • @param packageName
  • @return, true if install on SD card
    */
    public static boolean isInstallOnSDCard(String packageName,Context mcontext) {
    PackageManager pm = mcontext.getPackageManager();
    ApplicationInfo appInfo;
    try {
    appInfo = pm.getApplicationInfo(packageName, 0);

if ((appInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
return true;
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}

return false;
}

(4)系统开启了Fast Boot刷机模式,这种模式下系统启动并不会发送BOOT_COMPLETED广播
(5)app安装后,需要首先启动一次,否则是收不到任何广播的。
(6)检查你的手机或平板,在设置-权限管理-找到你的应用-开启应用自动启动(如果你的手机有这个选项的话请按照此步骤开启)我的是以华为平板为例。

(7)查看你的手机或者平板,是否安装有手机管家之类软件,如果有的话打开关键软件查看是否有自启管理的选项,如果有的话,点击自启管理,在应用列表中找到你要自启的app,然后设置允许。
(8)开发过程中,一直无法实现自启,我还有考虑过会不会是安卓8.0以后取消大部分静态注册广播的原因,后来查了资料发现并不是。
Android 8.0新特性-取消大部分静态注册广播

这套代码在华为手机(安卓4.4.4系统)、华为平板(安卓7.0系统),以及电视(TV端安卓9.0系统)上都是可以实现的。
n
关于TV app开机自启动
关于开发电视app开机自启动方案整理如下:

方案一:使用当贝助手或者氧气桌面
网上很多这种设置教程,但是我买回来的电视盒子,安装了当贝和氧气之后 ,当贝助手设置了我需要的app开机自启,但是没有作用,氧气桌面设置里面直接找不到所谓的自启选项,这个方案应该是有的电视是可以的,有的不行。这个可能也是跟电视盒子的系统有关,这个只是我的推测,没有具体验证。
方案二:找卖家定制系统
常见的电视盒子,有的系统设置里面支持app开机自启动,有的则没有。
我买了电视盒子回来发现,自带的电视系统根本不支持设置开机自启,于是找到卖家,表示后续可能会大量购进一批电视盒子,然后卖家二话不说给我重新发了一个刷机软件还有系统包
方案三:就是文章一开始的,使用代码实现开机自启动
但是问题是在安卓9.0系统上,使用开机广播实现app自启动的话,会比较慢,从显示桌面到打开app,大概要用到一分钟到一分半的时间,如果不介意这个时间差的话,代码实现还是可以的,方案二里面是显示了桌面就立马自启了,所以如果要求比较严格的话可以使用方案二,但方案二的问题是,有的时候可能商家会不给你,或者是要求你出钱定制系统,之前问的一家商家就是告诉我要定制系统,并且要购买够一定的量,所以具体的就靠你跟商家battle了

获取自启动管理页面的Intent

 ComponentName localComponentName = new ComponentName(DemoApp.getContext(), BootReceiver.class);
        int i = DemoApp.getContext().getPackageManager().getComponentEnabledSetting(localComponentName);
 Log.e("自启动 >>>>", "onCreate: " + i);

 Intent intent = getAutostartSettingIntent(this);
 startActivity(intent);




/**
     * 获取自启动管理页面的Intent
     *
     * @param context context
     * @return 返回自启动管理页面的Intent
     */
    public static Intent getAutostartSettingIntent(Context context) {
 ComponentName componentName = null;
 String brand = Build.MANUFACTURER;
 Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 switch (brand.toLowerCase()) {
 case "samsung"://三星
                componentName = new ComponentName("com.samsung.android.sm", "com.samsung.android.sm.app.dashboard.SmartManagerDashBoardActivity");
 break;
 case "huawei"://华为
 Log.e("自启动管理 >>>>", "getAutostartSettingIntent: 华为");
                componentName = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity");
//            componentName = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity");//目前看是通用的
 break;
 case "xiaomi"://小米
//                componentName = new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity");
                componentName = new ComponentName("com.android.settings","com.android.settings.BackgroundApplicationsManager");
 break;
 case "vivo"://VIVO
//            componentName = new ComponentName("com.iqoo.secure", "com.iqoo.secure.safaguard.PurviewTabActivity");
                componentName = new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity");
 break;
 case "oppo"://OPPO
//            componentName = new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity");
                componentName = new ComponentName("com.coloros.oppoguardelf", "com.coloros.powermanager.fuelgaue.PowerUsageModelActivity");
 break;
 case "yulong":
 case "360"://360
                componentName = new ComponentName("com.yulong.android.coolsafe", "com.yulong.android.coolsafe.ui.activity.autorun.AutoRunListActivity");
 break;
 case "meizu"://魅族
                componentName = new ComponentName("com.meizu.safe", "com.meizu.safe.permission.SmartBGActivity");
 break;
 case "oneplus"://一加
                componentName = new ComponentName("com.oneplus.security", "com.oneplus.security.chainlaunch.view.ChainLaunchAppListActivity");
 break;
 case "letv"://乐视
                intent.setAction("com.letv.android.permissionautoboot");
 default://其他
                intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
                intent.setData(Uri.fromParts("package", context.getPackageName(), null));
 break;
 }
        intent.setComponent(componentName);
 return intent;
 }

编辑于 2023-04-21 11:02・IP 属地山东Android 开发Android 后台Android​赞同​添加评论​分享​喜欢​收藏​设置

posted @ 2023-04-21 11:07  cps666  阅读(260)  评论(0编辑  收藏  举报