OOBE是开机向导,普通的理解就是一个界面跳另一个界面再跳下一个界面,OOBE却不是这么实现的。下面分析OOBE界面跳转实现:
打开OOBE目录,找到入口是WizardActivity.java,该Activity随后跳转到MainActivity.java。OOBE界面跳转逻辑都在MainActivity.java里实现。
对于一个陌生的Activity,我们先看它的onCreate方法:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("xsslog","OOBE MainActivity onCreate() ----------111");
this.getWindow().setFlags(FLAG_HOMEKEY_DISPATCHED, FLAG_HOMEKEY_DISPATCHED);//forbid homeKey
mSimExist = isSimExist();
Xlog.d(TAG, "onCreate mSimExist = " + mSimExist);
if (savedInstanceState != null) {
mCurrentStep = savedInstanceState.getInt("currentStep");
mTotalStep = savedInstanceState.getInt("totalSteps");
Log.i("xsslog", "restore saved instance state mCurrentStep=" + mCurrentStep + "mTotalStep="
+ mTotalStep);
setActivityList();
}
//Diable window rotate for phone.
setWindowRotation(false);
//disable quick start guide for tablet
//disableQSG();
mIsFirstRun = Settings.System.getInt(getContentResolver(), Utils.OOBE_HAS_RUN_KEY, 0) == 0;
Log.i("xsslog","OOBE MainActivity onCreate() -----222-----mIsFirstRun="+mIsFirstRun);
if (mIsFirstRun) {
Settings.System.putInt(getContentResolver(),
Settings.System.OOBE_DISPLAY, Settings.System.OOBE_DISPLAY_ON);
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
enableStatusBar(false);
}
mBootMode = getBootMode();
if (mIsFirstRun && mBootMode != BOOT_MODE_ADV_META && !Utils.isWifiOnly(this)) {
mHandler.sendEmptyMessageDelayed(EVENT_MONITOR_SIM_TIME_OUT, TIME_MONITOR_SIM);
Log.i("xsslog","OOBE MainActivity ()=========");
//showDialog(DIALOG_WAITING_SIM);
} else {
mHandler.sendEmptyMessage(EVENT_SIM_DETECTING_READY);
}
mSIMIntentFilter = new IntentFilter(TelephonyIntents.ACTION_SIM_INFO_UPDATE);
registerReceiver(mSIMStateReceiver, mSIMIntentFilter);
pm = getPackageManager();
name = new ComponentName(this, WizardActivity.class);
if(pm != null)//added by lzp
state = pm.getComponentEnabledSetting(name);
/* mVelocityTracker = VelocityTracker.obtain();
mScreenOffReceiverFilter = new IntentFilter();
mScreenOffReceiverFilter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(mScreenOffReceiver,mScreenOffReceiverFilter);
*/
}
其中mCurrentStep是指当前界面数,mTotalStep是指OOBE总界面数。mIsFirstRun判断是否第一次进入OOBE,做相应处理
这里的重点是看setActivityList();
protected void setActivityList() {
boolean mIphoneFlag = Settings.System.getInt(this.getContentResolver(), Settings.System.ISIPHONE, 0) == 1;//added by lzp
boolean noIphoneChars = "1".equals(SystemProperties.get("ro.cenon_setting_no_iPhone"));//added by lzp
boolean switchPagesByLogo = "1".equals(SystemProperties.get("cenon.switch_oobe_pages_by_logo"));//added by lzp
Xlog.d(TAG, "setActivityList() mIphoneFlag="+mIphoneFlag);
mStepActivityies.clear();
if((!switchPagesByLogo && !noIphoneChars) || mIphoneFlag) {
mStepActivityies.add(mLanguageSettings);
mStepActivityies.add(mCountrySettings);
mStepActivityies.add(iMessageAndFaceTime);// add by csc for ios 10
mStepActivityies.add(mInputMethodSettings);
mStepActivityies.add(mWifiSettings);
mStepActivityies.add(mfinishOobe);
} else {//added by lzp
mStepActivityies.add(mLanguageSettings);
mStepActivityies.add(mCountrySettings);
mStepActivityies.add(mInputMethodSettings);
mStepActivityies.add(mfinishOobe);
}
mTotalStep = mStepActivityies.size();
}
可以看到每个界面都被加到了mStepActivityies里面,mTotalStep就是在这里得出
private List<OobeActivityInfo> mStepActivityies = new ArrayList<OobeActivityInfo>();
我们发现里面有个mHandler处理,于是我们跳到该mHandler:
private Handler mHandler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case EVENT_MONITOR_SIM_TIME_OUT:
Xlog.v(TAG, "handler wait SIM time out");
break;
case EVENT_SIM_DETECTING_READY:
Xlog.v(TAG, "handler SIM initialization finish");
mHandler.removeMessages(EVENT_MONITOR_SIM_TIME_OUT);
break;
case EVENT_PREPAREING_END_OOBE:
mHandler.removeMessages(EVENT_PREPAREING_END_OOBE);
finish();
break;
default:
break;
}
initStep();
//removeDialog(DIALOG_WAITING_SIM);
};
};
可以看到有EVENT_MONITOR_SIM_TIME_OUT,EVENT_SIM_DETECTING_READY,EVENT_PREPAREING_END_OOBE等情况的处理,我们主要研究OOBE界面是如何进行跳转的,上面的就不细做分析了。然后就注意到initStep()方法
private void initStep() {
if (mIsStepInitiated) {
return;
}
mIsStepInitiated = true;
setActivityList();
if (mCurrentStep == -1) {
nextActivity(true);
}
}
setActivityList()上面说了把界面都放入list,重点看nextActivity方法
protected void nextActivity(boolean nextStep) {
if (nextStep) {
if(mCurrentStep<0)
{
mCurrentStep++;
Intent lockScreenIntent = new Intent(ACTION_LOCK_SCREEN);
startActivityForResult(lockScreenIntent, REQUEST_CODE_ADVANCED_SETTINGS);
return;
}
else mCurrentStep++;
} else {
mCurrentStep--;
}
if (mCurrentStep >= 0 && mCurrentStep < mStepActivityies.size()) {
Intent intent = mStepActivityies.get(mCurrentStep).getIntent();
intent.putExtra(Utils.OOBE_BASIC_STEP_TOTAL, mTotalStep);
intent.putExtra(Utils.OOBE_BASIC_STEP_INDEX, mCurrentStep + 1);
intent.putExtra(EXTRA_IS_OOBE, true);
startActivityForResult(intent, mCurrentStep);
if (nextStep) {
overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out);
//overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
} else {
overridePendingTransition(R.anim.slide_left_in, R.anim.slide_right_out);
//overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
}
}
}
nextStep用来判断下一步还是上一步,mCurrentStep是要跳转界面的值,知道这个前一部分代码就好理解了
Intent intent = mStepActivityies.get(mCurrentStep).getIntent();
intent.putExtra(Utils.OOBE_BASIC_STEP_TOTAL, mTotalStep);
intent.putExtra(Utils.OOBE_BASIC_STEP_INDEX, mCurrentStep + 1);
intent.putExtra(EXTRA_IS_OOBE, true);
startActivityForResult(intent, mCurrentStep);
根据mCurrentStep从mStepActivityies取出该界面的包名,用startActivityForResult方法进行跳转,我们可以看下回传的参数用来干嘛
其他界面点击上一步或者下一步的时候就调用finishActivityByResult(Utils.RESULT_CODE_TO_NO_STEP);
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.back_settings_btn:
finishActivityByResult(Utils.RESULT_CODE_TO_NO_STEP);
break;
case R.id.next_settings_btn:
/* Intent intent = new Intent();
intent.setClass(OobeLoginiCloudActivity.this,OobeTermsAndConditionsActivity.class);
intent.putExtra("GOTO_BY_ICLOUD",true);
startActivity(intent);
finish();*/
finishActivityByResult(Utils.RESULT_CODE_TO_TWO_STEP);
break;
}
}
private void finishActivityByResult(int resultCode) {
Intent intent = new Intent();
setResult(resultCode, intent);
finish();
}
然后把这个是跳上一步还是下一步传回MainActivity,由MainActivity进行统一跳转,而不是从当前界面直接往下跳。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
Xlog.d(TAG, "onActivityResult resultCode = " + resultCode);
switch (resultCode) {
case Utils.RESULT_CODE_BACK:
if (0 == mCurrentStep) {
finish();
} else {
nextActivity(false);
}
break;
case Utils.RESULT_CODE_NEXT:
nextActivity(true);
break;
case Utils.RESULT_CODE_FINISH:
finishOOBE();
break;
case Utils.RESULT_CODE_TO_ONE_STEP:// add by csc for ios 10
mCurrentStep++;
nextActivity(true);
break;
case Utils.RESULT_CODE_TO_TWO_STEP:// add by csc for ios 10
mCurrentStep=mCurrentStep+2;
nextActivity(true);
break;
case Utils.RESULT_CODE_TO_LOGIN_ICLOUD:// add by csc for ios 10
intent = new Intent();
intent.setClass(MainActivity.this,OobeLoginiCloudActivity.class);
startActivityForResult(intent, 1001);
break;
case Utils.RESULT_CODE_TO_FORGET_PASSWORD:
intent = new Intent();
intent.setClass(MainActivity.this,OobeForgetPasswordActivity.class);
startActivityForResult(intent, 1001);
break;
case Utils.RESULT_CODE_TO_CREATE_APPLE_ID:// add by csc for ios 10
intent = new Intent();
intent.setClass(MainActivity.this,OobeCreateAppleIdActivity.class);
startActivityForResult(intent, 1001);
break;
case Utils.RESULT_CODE_TO_FORGET_APPLE_ID:// add by csc for ios 10
intent = new Intent();
intent.setClass(MainActivity.this,OobeForgetAppleIDActivity.class);
startActivityForResult(intent, 1001);
break;
case Utils.RESULT_CODE_TO_NO_STEP:// add by csc for ios 10
mCurrentStep--;
nextActivity(true);
break;
case 100:
{
/**Begin: added by lzp **/
if(mCurrentStep < 0) {
mHandler.sendEmptyMessage(EVENT_SIM_DETECTING_READY);
return;
}
/**End: added by lzp **/
Intent backIntent = mStepActivityies.get(mCurrentStep).getIntent();
backIntent.putExtra(Utils.OOBE_BASIC_STEP_TOTAL, mTotalStep);
backIntent.putExtra(Utils.OOBE_BASIC_STEP_INDEX, mCurrentStep + 1);
backIntent.putExtra(EXTRA_IS_OOBE, true);
startActivityForResult(backIntent, mCurrentStep);
overridePendingTransition(R.anim.slide_left_in, R.anim.slide_right_out);
//overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
}
break;
case Utils.RESULT_SCREEN_OFF:
{
Intent lockScreenIntent = new Intent(ACTION_LOCK_SCREEN);
startActivityForResult(lockScreenIntent, REQUEST_CODE_ADVANCED_SETTINGS);
overridePendingTransition(R.anim.slide_left_in, R.anim.slide_right_out);
//overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
}
break;
default:
break;
}
}
到这里就完成了OOBE的界面跳转。