How to insert your own activity after Setup Wizard finishes

The basic idea is that your new activity is going to call itself a Homeactivity and give itself a priority between that of Setup Wizard and thereal Home activity. Setup Wizard, with the highest priority among the three,will get launched first upon bootup. Then, when it's done, it will disableitself to prevent being launched again on subsequent bootups and launchthe next Home activity in turn. That will be yours, and when it completes,it will need to do the same thing Setup Wizard did: disable itself andthen launch the next Home, which in this case will finally be our Launcher.
1. Give your activity an intent filter something like this. The prioritycan be anything from 1 to 4, since Setup Wizard is 5 and the "real"Home activity is 0.
           <intent-filterandroid:priority="3">
               <actionandroid:name="android.intent.action.MAIN" />
               <categoryandroid:name="android.intent.category.HOME" />
               <categoryandroid:name="android.intent.category.DEFAULT" />
           </intent-filter>
2. As your activity finishes, do something like this:
           // disableourselves so we won't ever get launched as a HOME activity again
           PackageManagerpm = getPackageManager();
           ComponentNamename = new ComponentName(this, ThisActivity.class);
           pm.setComponentEnabledSetting(name,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                   PackageManager.DONT_KILL_APP);
           // Startthe real home activity (or the one with the next highest priority, anyway)
           startActivity(newIntent(Intent.ACTION_MAIN, null)
                   .addCategory(Intent.CATEGORY_HOME)
                   .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                           |Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED));
3. When Setup Wizard completes, it sets a flag that indicates to the restof the system that it's done, which enables certain phone functions thatwe don't want occurring during Setup Wizard, such as incoming phone calls.You might want to clear that flag again, just to prevent your activityfrom being interrupted. (This is not ideal, since there will be that briefsliver of time between our setting the flag and your clearing it wheremaybe an incoming call could slip in. We'll try to address this in thefuture.) Here's the code Setup Wizard uses to set the flag. If you decideto clear it at the start of your activity (by setting it to 0) make sureyou set it again before you exit!
       Settings.Secure.putInt(getContentResolver(),Settings.Secure.DEVICE_PROVISIONED, 1);
4. Setup Wizard disables the entire status bar (with the possible exceptionof the Back key in some circumstances) during all the time it's running,so that nothing can appear there that might allow the user to leave SetupWizard and then not be able to get back to it. You should probably do thesame thing. Unfortunately, both of the possible ways of doing this arebased on hidden APIs, so you'll have to find them through reflection. Here'ssample code for one possible method that includes all the reflection stuff:
   private static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
   private static final int STATUS_BAR_DISABLE_EXPAND =0x00010000;
   private static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS= 0x00020000;
   private static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS= 0x00040000;
   private static final int STATUS_BAR_DISABLE_SYSTEM_INFO= 0x00100000;
   private static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
   private static final int STATUS_BAR_DISABLE_RECENT =0x01000000;
   private static Method findMethod(Class c, String name,Class param) {
       try {
           if (c== null) {
               returnnull;
           }
           returnc.getMethod(name, param);
       } catch (NoSuchMethodExceptionunused) {
           Log.i(GLSUser.TAG,"Method not found " + name);
       }
       return null;
   }
   private static final Method sViewSetSystemUiVisibility=
       findMethod(View.class, "setSystemUiVisibility",
               Integer.TYPE);
   private static void viewSetSystemUiVisibility(FrameLayoutfl, int v) {
       if (sViewSetSystemUiVisibility!= null) {
           try {
               sViewSetSystemUiVisibility.invoke(fl,v);
           } catch(Throwable e) {
               //ignore
           }
       }
   }
   View outerView = // get the outer view of your layout(Note: I see that what we're doing is creating this outer view dynamicallyin our onCreate() and then loading the layout into it. I'm not sure ifthis was required to make this status bar disabling technique work or ifit was done for other, unrelated reasons, but just be aware you might haveto do something like that yourself.)
   viewSetSystemUiVisibility(outerView, STATUS_BAR_DISABLE_EXPAND
                   |STATUS_BAR_DISABLE_NOTIFICATION_ICONS
                   |STATUS_BAR_DISABLE_NOTIFICATION_ALERTS
                   |STATUS_BAR_DISABLE_SYSTEM_INFO
                   |STATUS_BAR_DISABLE_HOME
                   |STATUS_BAR_DISABLE_RECENT
                   |STATUS_BAR_DISABLE_BACK);      // Note: if youneed the Back key for your activity, you can leave this out
If your activity is really multiple activities, you'll need to do thisfor each of them. Its effect only applies to the view it's done for.
If you don't want to mess with grabbing your outer view, you can also disablethe status bar directly through the status bar manager, though that's ahidden API, too. But you can use the same reflection tricks as above tocall it yourself. Here's the direct Setup Wizard code:
           mStatusBarManager= (StatusBarManager)getSystemService(Context.STATUS_BAR_SERVICE);
           mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND
                   |StatusBarManager.DISABLE_NOTIFICATION_ICONS
                   |StatusBarManager.DISABLE_NOTIFICATION_ALERTS
                   |StatusBarManager.DISABLE_SYSTEM_INFO
                   |StatusBarManager.DISABLE_HOME
                   |StatusBarManager.DISABLE_RECENT
                   |StatusBarManager.DISABLE_BACK);      // Note:if you need the Back key for your activity, you can leave this out

This one only needs to be done once, and it will remain in effect as longas your process is still running. In that respect, it's better than thefirst method. Also, it will also continue to keep the status bar disabledshould you launch some external activity you have no control of, sinceyour process will still be running underneath it at that point. (However,if the system decides to temporarily shut down your process for memorymanagement purposes, the status bar will be re-enabled. I think this isa bug we need to fix.) With the first method, once a view that hasn't disabledthe status bar appears on top of yours, the status bar will be re-enabled.


总结如下:manifest:

<intent-filter android:priority="3" >
                <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

执行完成之后下次启动的时候不再执行本程序:

public void disableOurselves(){
		// disable ourselves so we won't ever get launched as a HOME activity again
        PackageManager pm = this.context.getPackageManager();
        ComponentName name = new ComponentName(this.context, LenovoOOBEActivity.class);
        pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
        this.context.startActivity(new Intent(Intent.ACTION_MAIN, null)
                .addCategory(Intent.CATEGORY_HOME)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED));
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值