Android KK应用开机自启动的几种方法

56 篇文章 0 订阅
51 篇文章 2 订阅

方法一.开机自启动,注册广播的方式,这种方式比较慢,一般需要很久

原理:监听接收 android.intent.action.BOOT_COMPLETED 广播

添加开机广播接收器

public class BootReceiver extends BroadcastReceiver{
    public void onReceive(Context context,Intent intent){
        Intent mIntent = new Intent(context,MainActivity.class);
        startActivity(mIntent);
    }
}

在 AndroidManifest.xml 文件中添加权限

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

在 AndroidManifest.xml 文件中注册开机广播接收器

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

方法二.在开机向导之后开机自启动

原理:在开机向导结束之后会修改数据库将 Settings.Secure.USER_SETUP_COMPLETE 的值修改为 1,Google开机向导和OOBE开机向导都会修改这个值,具体代码如下:
//OOBE
mediatek/packages/apps/OOBE/src/com/mediatek/oobe/basic/MainActivity.java

private void finishOOBE() {
    ...
    Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
    ...
}

//SetupWizard
com/google/android/setupwizard/BaseActivity.java

protected void onSetupComplete(boolean paramBoolean){
    ...
    Settings.Secure.putInt(getContentResolver(), "user_setup_complete", 1);
    ...
}

//在SystemUI中已经有了对 Settings.Secure.USER_SETUP_COMPLETE 的监听
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java 中有

private void resetUserSetupObserver() {
    ...
    mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), true, mUserSetupObserver, mCurrentUserId);
    ...
}
private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) {
    @Override
    public void onChange(boolean selfChange) {
        final boolean userSetup = 0 != Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0 , mCurrentUserId);
        if (mSettingsButton != null && mHasFlipSettings) {
            mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
        }
        if (mSettingsPanel != null) {
            mSettingsPanel.setEnabled(userSetup);
        }
        if (userSetup != mUserSetup) {
            mUserSetup = userSetup;
            if (!mUserSetup && mStatusBarView != null){
                animateCollapseQuickSettings();
            }
        }
    }
};

初步修改后的代码如下

boolean isFirstBoot = Settings.Secure.getInt(mContext.getContentResolver(), "isFirstBoot", 0) == 0;            //设置标志位,只有在恢复出厂设置的时候启动一次
if(userSetup && isFirstBoot){
    try{
        Intent intent = new Intent();
        intent.setComponent(new android.content.ComponentName("za.co.axon.mdas.roid","za.co.axon.mdas.roid.Splash"));
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
        mContext.startActivity(intent);
        Settings.Secure.putInt(mContext.getContentResolver(), "isFirstBoot", 1);                            //将标志为设置为1,表示启动成功
    } catch(Exception e) {
        e.printStackTrace();        //这里加try,catch防止内置的APK face2face 丢失
    }
}

但经过强度测试之后发现了一个小问题,概率性的出现应用程序不启动的现象?
从Log中可以看出:

正常启动的Log:

01-01 00:01:19.656195   719  1095 I am_create_activity: [0,1113075664,4,za.co.axon.mdas.roid/.Splash,NULL,NULL,NULL,272629760
01-01 00:01:19.656700   719  1095 I wm_task_created: [4,1
01-01 00:01:19.656803   719  1095 I wm_task_moved: [4,1,2
01-01 00:01:19.700131   719  1157 I am_proc_died: [0,1169,com.google.android.setupwizard
01-01 00:01:19.705203   719  1157 I am_destroy_service: [0,1107535152,1254
01-01 00:01:19.732961   719  1157 I am_finish_activity: [0,1110412608,2,com.google.android.setupwizard/.NoAccountTosActivity,proc died without state saved
01-01 00:01:19.847742   719  1157 I am_finish_activity: [0,1112688672,2,com.google.android.setupwizard/.NoAccountTosActivity,proc died without state saved
01-01 00:01:19.940255   719  1157 I am_proc_start: [0,2045,10039,za.co.axon.mdas.roid,activity,za.co.axon.mdas.roid/.Splash
01-01 00:01:20.019586   719   730 I am_proc_bound: [0,2045,za.co.axon.mdas.roid
01-01 00:01:20.253625   719   730 I am_restart_activity: [0,1113075664,4,za.co.axon.mdas.roid/.Splash
01-01 00:01:20.315298   719   742 I notification_enqueue: [com.mediatek.mtklogger,2130837522,NULL,0,Notification(pri=0 contentView=com.mediatek.mtklogger/0x109006b vibrate=null sound=null defaults=0x0 flags=0x60 kind=[null])
01-01 00:01:20.316353   719   719 I notification_cancel: [com.mediatek.mtklogger,2130837522,NULL,0,0,0
01-01 00:01:20.532800  2045  2045 I am_on_resume_called: [0,za.co.axon.mdas.roid.Splash
01-01 00:01:20.571890   719  1157 I wm_task_moved: [4,1,2
01-01 00:01:20.572002   719  1157 I am_create_activity: [0,1110419464,4,za.co.axon.mdas.roid/.About,NULL,NULL,NULL,0
01-01 00:01:20.582907   719  1157 I am_pause_activity: [0,1113075664,za.co.axon.mdas.roid/.Splash
01-01 00:01:20.593922   719  1014 I am_finish_activity: [0,1113075664,4,za.co.axon.mdas.roid/.Splash,app-request
01-01 00:01:20.636227  2045  2045 I am_on_paused_called: [0,za.co.axon.mdas.roid.Splash
01-01 00:01:20.667373   719  2043 I am_restart_activity: [0,1110419464,4,za.co.axon.mdas.roid/.About
01-01 00:01:20.723902   719  1157 I am_create_service: [0,1114379064,.SIMProcessorService,10003,1781
01-01 00:01:20.785342   719  1563 I am_create_service: [0,1114110688,.DownloadService,10005,1489
01-01 00:01:20.847981   719   735 I notification_cancel_all: [com.android.providers.downloads,0,0,64
01-01 00:01:20.915881  2045  2045 I am_on_resume_called: [0,za.co.axon.mdas.roid.About

异常不启动的Log:

01-01 00:01:12.916516   720  1170 I am_create_activity: [0,1113616608,3,za.co.axon.mdas.roid/.Splash,NULL,NULL,NULL,272629760
01-01 00:01:12.916972   720  1170 I wm_task_created: [3,1
01-01 00:01:12.917066   720  1170 I wm_task_moved: [3,1,1
01-01 00:01:12.917903   720  1170 I am_pause_activity: [0,1107807432,com.google.android.setupwizard/.NoAccountTosActivity
01-01 00:01:12.944667   720  1147 I am_create_task: [0,4
01-01 00:01:12.944957   720  1147 I am_create_activity: [0,1111200792,4,com.android.launcher3/.Launcher,android.intent.action.MAIN,NULL,NULL,270532608
01-01 00:01:12.945345   720  1147 I wm_task_created: [4,0
01-01 00:01:12.945431   720  1147 I wm_task_moved: [4,1,2
01-01 00:01:13.121927   720  1122 I am_create_service: [0,1109984720,.SIMProcessorService,10003,1652
01-01 00:01:13.201850   720   732 I am_proc_died: [0,1188,com.google.android.setupwizard
01-01 00:01:13.203463   720   732 I am_destroy_service: [0,1110166664,1302
01-01 00:01:13.210043   720   732 I am_finish_activity: [0,1107807432,2,com.google.android.setupwizard/.NoAccountTosActivity,proc died without state saved
01-01 00:01:13.242921   720   732 I am_finish_activity: [0,1108071280,2,com.google.android.setupwizard/.DateTimeSetupActivity,proc died without state saved
01-01 00:01:13.263721   157   157 I sf_frame_dur: [com.google.android.setupwizard/com.google.android.setupwizard.NoAccountTosActivity,2,3,0,0,2,0,0
01-01 00:01:13.329596   720   732 I am_proc_start: [0,1924,10012,com.android.launcher3,activity,com.android.launcher3/.Launcher
01-01 00:01:13.339900   720  1090 I am_create_service: [0,1113635320,.DownloadService,10005,1208
01-01 00:01:13.420749   720   736 I am_proc_bound: [0,1924,com.android.launcher3
01-01 00:01:13.481537   720   968 I notification_cancel_all: [com.android.providers.downloads,0,0,64
01-01 00:01:14.885420   720   736 I am_restart_activity: [0,1111200792,4,com.android.launcher3/.Launcher
01-01 00:01:14.903973   720  1090 I am_destroy_service: [0,1113635320,1208
01-01 00:01:14.912448   720   743 I am_finish_activity: [0,1113616608,3,za.co.axon.mdas.roid/.Splash,no-history        //za.co.axon.mdas.roid.Splash 被莫名其妙地 finish 掉了
01-01 00:01:14.918549   720   743 I am_destroy_activity: [0,1113616608,3,za.co.axon.mdas.roid/.Splash,finish-imm

根据这种情况,再次做了修改

private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) {
    @Override
    public void onChange(boolean selfChange) {
        ...
        if (userSetup != mUserSetup) {
            mUserSetup = userSetup;
            boolean isFirstBoot = Settings.Secure.getInt(mContext.getContentResolver(), "isFirstBoot", 0) == 0;
            if(userSetup && isFirstBoot){
                try{
                    Intent intent = new Intent();
                    intent.setComponent(new android.content.ComponentName("za.co.axon.mdas.roid","za.co.axon.mdas.roid.Splash"));
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
                    mContext.startActivity(intent);
                    Settings.Secure.putInt(mContext.getContentResolver(), "isFirstBoot", 1);
                    new Thread(new Runnable(){                    //在这个地方启动一个线程,再次启动这个应用
                        public void run(){
                            try{
                                while(!isStartSuccess){
                                    Thread.sleep(2000);
                                    handler.sendEmptyMessage(1);
                                }
                            }catch(Exception e){
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
            ...
        }
    }
};
private boolean isStartSuccess = false;
Handler handler = new Handler(){
    public void handleMessage(Message msg){
        switch(msg.what){
            case 1:
                String topActivityName = getTopActivityName(mContext);
                if(topActivityName != null && topActivityName.contains("za.co.axon.mdas.roid")){
                    isStartSuccess = true;
                } else {
                    Intent intent = new Intent();
                    intent.setComponent(new android.content.ComponentName("za.co.axon.mdas.roid","za.co.axon.mdas.roid.Splash"));
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    mContext.startActivity(intent);
                }
                break;
            default:
                break;
        }
    }
};

/**获取栈顶Activity的名称*/
private String getTopActivityName(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<android.app.ActivityManager.RunningTaskInfo> runningTaskInfos = activityManager.getRunningTasks(1);
    if (runningTaskInfos != null) {
        return (runningTaskInfos.get(0).topActivity).toString();
    } else {
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值