Android的框架设计有考虑到开机向导这一场景,因此我们实现开机向导参考Android的Provision.apk
Provision: MSM8976/repo/packages/apps/Provision
它的主要作用是作为开机引导用户进行一些基本设置.在原生的 android 系统中,provision非常的简单,只有一个空白的 activity,这个主要就是留给 厂商自己定制开机向导(像 OPPO,VIVO,小米等厂商会让你登陆和注册其账号帐号,连接WiFi等),因此我们得理解Android的设计意图而进行定制.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.tomorrow_p.setupwizard"><!--android:sharedUserId="android.uid.system"--><original-package android:name="com.android.provision" /><!-- For miscellaneous settings --><uses-permission android:name="android.permission.WRITE_SETTINGS" /><!--<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />--><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/setupwizard_AppTheme"><activityandroid:name=".DefaultActivity"android:excludeFromRecents="true"><intent-filter android:priority="1"><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.HOME" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name="com.tomorrow_p.setupwizard.SimActivity"><intent-filter><action android:name="com.android.provision.SimActivity"></action><category android:name="android.intent.category.DEFAULT"></category></intent-filter></activity><activity android:name="com.tomorrow_p.setupwizard.OpenActivity"><intent-filter><action android:name="com.android.provision.OpenActivity"></action><category android:name="android.intent.category.DEFAULT"></category></intent-filter></activity></application>
</manifest>
1. DefaultActivity是原生系统Provision中唯一的activity;配置了category.HOME属性,category.HOME是桌面程序的标记(Launcher程序都会配置);priority=1,配置优先级,这样就会在系统的Launcher之前启动.
2. Provision中的关键代码:
// Add a persistent setting to allow other apps to know the device has been provisioned.Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);// remove this activity from the package manager.PackageManager pm = getPackageManager();ComponentName name = new ComponentName(this, WelcomeActivity.class);pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);
这里代码主要设置DEVICE_PROVISIONED标记同时禁止本身Activity组件的功能
API:
void setComponentEnabledSetting (ComponentName componentName, int newState, int flags) 
componentName:组件名称 
newState:组件新的状态,可以设置三个值,分别是如下: 
不可用状态:COMPONENT_ENABLED_STATE_DISABLED 
可用状态:COMPONENT_ENABLED_STATE_ENABLED 
默认状态:COMPONENT_ENABLED_STATE_DEFAULT 
flags:行为标签,值可以是DONT_KILL_APP或者0. 0说明杀死包含该组件的app 
主要代码:

以下代码有注释掉跳转到注册和登录账户模块以及调用系统的WiFi设置向导模块

同时需要配置系统签名以及系统应用标识
package com.tomorrow_p.setupwizard;import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Locale;public class DefaultActivity extends BaseActivity implements View.OnClickListener {private static final String[] PLANETS = new String[]{"English", "简体中文", "繁体中文"};private String mCurrentStatus = PLANETS[1];@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);getActionBar().hide();setContentView(R.layout.setupwizard_activity_default);WheelView mWheelView = (WheelView) findViewById(R.id.wheelview);mWheelView.setOffset(1);mWheelView.setSeletion(1);mWheelView.setItems(Arrays.asList(PLANETS));mWheelView.setOnWheelViewListener(new WheelView.OnWheelViewListener() {@Overridepublic void onSelected(int selectedIndex, String item) {mCurrentStatus = item;}});Button next = (Button) findViewById(R.id.next);next.setOnClickListener(this);}@Overridepublic void onClick(View view) {switch (mCurrentStatus) {case "English":updateLanguage(Locale.US);break;case "简体中文":updateLanguage(Locale.SIMPLIFIED_CHINESE);break;case "繁体中文":updateLanguage(Locale.TRADITIONAL_CHINESE);break;}
//        startWifiActivity();startActivity(new Intent(this,SimActivity.class));finish();}private void startWifiActivity() {Intent startActivity = new Intent();startActivity.setComponent(new ComponentName("com.android.settings", "com.android.settings.wifi.WifiSetupActivity"));startActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(startActivity);//        Intent intent = new Intent();//        intent.setAction("android.net.wifi.PICK_WIFI_NETWORK");//        intent.putExtra("extra_prefs_show_button_bar", true);//        intent.putExtra("extra_prefs_set_next_text", "完成");//        intent.putExtra("extra_prefs_set_back_text", "返回");//        intent.putExtra("wifi_enable_next_on_connect", true);//        startActivity(intent);}private void updateLanguage(Locale locale) {try {Class classActivityManagerNative = Class.forName("android.app.ActivityManagerNative");Method getDefault = classActivityManagerNative.getDeclaredMethod("getDefault");// IActivityManager iActMag = ActivityManagerNative.getDefault();Object objIActivityManager = getDefault.invoke(classActivityManagerNative);Class classIActivityManager = Class.forName("android.app.IActivityManager");// Configuration config = iActMag.getConfiguration();Method getConfiguration = classIActivityManager.getDeclaredMethod("getConfiguration");Configuration config = (Configuration) getConfiguration.invoke(objIActivityManager);config.locale = locale;// 此处需要声明权限:android.permission.CHANGE_CONFIGURATION// 会重新调用 onCreate();Class[] clzParams = {Configuration.class};Method updateConfiguration = classIActivityManager.getDeclaredMethod("updateConfiguration", clzParams);// iActMag.updateConfiguration(config);updateConfiguration.invoke(objIActivityManager, config);} catch (Exception e) {e.printStackTrace();}}
}
package com.tomorrow_p.setupwizard;import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;public class OpenActivity extends BaseActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);getActionBar().hide();setContentView(R.layout.setupwizard_activity_open);Button user = (Button) findViewById(R.id.btn_user);user.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {init();finish();}});}private void init() {// Add a persistent setting to allow other apps to know the device has been provisioned.Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
//        Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);// remove this activity from the package manager.PackageManager pm = getPackageManager();ComponentName name = new ComponentName(this, DefaultActivity.class);pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);}
}
package com.tomorrow_p.setupwizard;import android.app.ActionBar;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;public class SimActivity extends BaseActivity implements View.OnClickListener {private static final String TAG = "SimActivity";protected ActionBar mActionBar;protected static final String SHOW_SKIP = "show_skip";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.setupwizard_activity_sim);initActionBar();Button mContinue = (Button) findViewById(R.id.btn_continue);Button mShutdown = (Button) findViewById(R.id.btn_shutdown);mShutdown.setOnClickListener(this);mContinue.setOnClickListener(this);}private void initActionBar() {mActionBar = getActionBar();mActionBar.setElevation(0);mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);View customView = LayoutInflater.from(this).inflate(R.layout.setupwizard_actionbar, null);TextView actionBarTitle = (TextView) customView.findViewById(R.id.title);customView.findViewById(R.id.iv_back).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent startActivity = new Intent();startActivity.setComponent(new ComponentName("com.android.settings", "com.android.settings.wifi.WifiSetupActivity"));startActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(startActivity);finish();}});actionBarTitle.setText(getResources().getString(R.string.check_sim));mActionBar.setCustomView(customView, new ActionBar.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, android.app.ActionBar.LayoutParams.MATCH_PARENT));}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.btn_continue:try {Intent startActivity = new Intent("com.qucii.usercenter.register.RegCheckMobileActivity");startActivity.putExtra(SHOW_SKIP, true);startActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(startActivity);} catch (Exception e) {Log.e(TAG, e.getMessage());startActivity(new Intent(this, OpenActivity.class));}finish();break;case R.id.btn_shutdown:try {Intent shutdown = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN");shutdown.putExtra("android.intent.action.EXTRA_KEY_CONFIRM", false);shutdown.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(shutdown);} catch (Exception e) {e.printStackTrace();}break;}}
}
package com.tomorrow_p.setupwizard;import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;import java.util.ArrayList;
import java.util.List;public class WheelView extends ScrollView {public static final String TAG = WheelView.class.getSimpleName();public static class OnWheelViewListener {public void onSelected(int selectedIndex, String item) {}}private Context context;
//    private ScrollView scrollView;private LinearLayout views;public WheelView(Context context) {super(context);init(context);}public WheelView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public WheelView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context);}//    String[] items;List<String> items;private List<String> getItems() {return items;}public void setItems(List<String> list) {if (null == items) {items = new ArrayList<String>();}items.clear();items.addAll(list);// 前面和后面补全for (int i = 0; i < offset; i++) {items.add(0, "");items.add("");}initData();}public static final int OFF_SET_DEFAULT = 1;int offset = OFF_SET_DEFAULT; // 偏移量(需要在最前面和最后面补全)public int getOffset() {return offset;}public void setOffset(int offset) {this.offset = offset;}int displayItemCount; // 每页显示的数量int selectedIndex = 1;private void init(Context context) {this.context = context;//        scrollView = ((ScrollView)this.getParent());
//        Log.d(TAG, "scrollview: " + scrollView);Log.d(TAG, "parent: " + this.getParent());
//        this.setOrientation(VERTICAL);this.setVerticalScrollBarEnabled(false);views = new LinearLayout(context);views.setOrientation(LinearLayout.VERTICAL);this.addView(views);scrollerTask = new Runnable() {public void run() {int newY = getScrollY();if (initialY - newY == 0) { // stoppedfinal int remainder = initialY % itemHeight;final int divided = initialY / itemHeight;
//                    Log.d(TAG, "initialY: " + initialY);
//                    Log.d(TAG, "remainder: " + remainder + ", divided: " + divided);if (remainder == 0) {selectedIndex = divided + offset;onSeletedCallBack();} else {if (remainder > itemHeight / 2) {WheelView.this.post(new Runnable() {@Overridepublic void run() {WheelView.this.smoothScrollTo(0, initialY - remainder + itemHeight);selectedIndex = divided + offset + 1;onSeletedCallBack();}});} else {WheelView.this.post(new Runnable() {@Overridepublic void run() {WheelView.this.smoothScrollTo(0, initialY - remainder);selectedIndex = divided + offset;onSeletedCallBack();}});}}} else {initialY = getScrollY();WheelView.this.postDelayed(scrollerTask, newCheck);}}};}int initialY;Runnable scrollerTask;int newCheck = 50;public void startScrollerTask() {initialY = getScrollY();this.postDelayed(scrollerTask, newCheck);}private void initData() {displayItemCount = offset * 2 + 1;for (String item : items) {views.addView(createView(item));}refreshItemView(0);}int itemHeight = 0;private TextView createView(String item) {TextView tv = new TextView(context);tv.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));tv.setSingleLine(true);tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);tv.setText(item);tv.setGravity(Gravity.CENTER);int padding = dip2px(15);tv.setPadding(padding, padding, padding, padding);if (0 == itemHeight) {itemHeight = getViewMeasuredHeight(tv);Log.d(TAG, "itemHeight: " + itemHeight);views.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, itemHeight * displayItemCount));LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) this.getLayoutParams();this.setLayoutParams(new LinearLayout.LayoutParams(lp.width, itemHeight * displayItemCount));}return tv;}@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);//        Log.d(TAG, "l: " + l + ", t: " + t + ", oldl: " + oldl + ", oldt: " + oldt);//        try {
//            Field field = ScrollView.class.getDeclaredField("mScroller");
//            field.setAccessible(true);
//            OverScroller mScroller = (OverScroller) field.get(this);
//
//
//            if(mScroller.isFinished()){
//                Log.d(TAG, "isFinished...");
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }refreshItemView(t);if (t > oldt) {
//            Log.d(TAG, "向下滚动");scrollDirection = SCROLL_DIRECTION_DOWN;} else {
//            Log.d(TAG, "向上滚动");scrollDirection = SCROLL_DIRECTION_UP;}}private void refreshItemView(int y) {int position = y / itemHeight + offset;int remainder = y % itemHeight;int divided = y / itemHeight;if (remainder == 0) {position = divided + offset;} else {if (remainder > itemHeight / 2) {position = divided + offset + 1;}//            if(remainder > itemHeight / 2){
//                if(scrollDirection == SCROLL_DIRECTION_DOWN){
//                    position = divided + offset;
//                    Log.d(TAG, ">down...position: " + position);
//                }else if(scrollDirection == SCROLL_DIRECTION_UP){
//                    position = divided + offset + 1;
//                    Log.d(TAG, ">up...position: " + position);
//                }
//            }else{position = y / itemHeight + offset;
//                if(scrollDirection == SCROLL_DIRECTION_DOWN){
//                    position = divided + offset;
//                    Log.d(TAG, "<down...position: " + position);
//                }else if(scrollDirection == SCROLL_DIRECTION_UP){
//                    position = divided + offset + 1;
//                    Log.d(TAG, "<up...position: " + position);
//                }
//            }
//        }//        if(scrollDirection == SCROLL_DIRECTION_DOWN){
//            position = divided + offset;
//        }else if(scrollDirection == SCROLL_DIRECTION_UP){
//            position = divided + offset + 1;}int childSize = views.getChildCount();for (int i = 0; i < childSize; i++) {TextView itemView = (TextView) views.getChildAt(i);if (null == itemView) {return;}if (position == i) {itemView.setTextColor(Color.parseColor("#0288ce"));} else {itemView.setTextColor(Color.parseColor("#bbbbbb"));}}}/*** 获取选中区域的边界*/int[] selectedAreaBorder;private int[] obtainSelectedAreaBorder() {if (null == selectedAreaBorder) {selectedAreaBorder = new int[2];selectedAreaBorder[0] = itemHeight * offset;selectedAreaBorder[1] = itemHeight * (offset + 1);}return selectedAreaBorder;}private int scrollDirection = -1;private static final int SCROLL_DIRECTION_UP = 0;private static final int SCROLL_DIRECTION_DOWN = 1;Paint paint;int viewWidth;@Overridepublic void setBackgroundDrawable(Drawable background) {if (viewWidth == 0) {viewWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth();Log.d(TAG, "viewWidth: " + viewWidth);}if (null == paint) {paint = new Paint();paint.setColor(Color.parseColor("#83cde6"));paint.setStrokeWidth(dip2px(1f));}background = new Drawable() {@Overridepublic void draw(Canvas canvas) {canvas.drawLine(viewWidth * 1 / 6, obtainSelectedAreaBorder()[0], viewWidth * 5 / 6, obtainSelectedAreaBorder()[0], paint);canvas.drawLine(viewWidth * 1 / 6, obtainSelectedAreaBorder()[1], viewWidth * 5 / 6, obtainSelectedAreaBorder()[1], paint);}@Overridepublic void setAlpha(int alpha) {}@Overridepublic void setColorFilter(ColorFilter cf) {}@Overridepublic int getOpacity() {return 0;}};super.setBackgroundDrawable(background);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);Log.d(TAG, "w: " + w + ", h: " + h + ", oldw: " + oldw + ", oldh: " + oldh);viewWidth = w;setBackgroundDrawable(null);}/*** 选中回调*/private void onSeletedCallBack() {if (null != onWheelViewListener) {onWheelViewListener.onSelected(selectedIndex, items.get(selectedIndex));}}public void setSeletion(int position) {final int p = position;selectedIndex = p + offset;this.post(new Runnable() {@Overridepublic void run() {WheelView.this.smoothScrollTo(0, p * itemHeight);}});}public String getSeletedItem() {return items.get(selectedIndex);}public int getSeletedIndex() {return selectedIndex - offset;}@Overridepublic void fling(int velocityY) {super.fling(velocityY / 3);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (ev.getAction() == MotionEvent.ACTION_UP) {startScrollerTask();}return super.onTouchEvent(ev);}private OnWheelViewListener onWheelViewListener;public OnWheelViewListener getOnWheelViewListener() {return onWheelViewListener;}public void setOnWheelViewListener(OnWheelViewListener onWheelViewListener) {this.onWheelViewListener = onWheelViewListener;}private int dip2px(float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}private int getViewMeasuredHeight(View view) {int width = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);view.measure(width, expandSpec);return view.getMeasuredHeight();}}

完整源码下载

Android开机向导setupwizard,设置系统语言,WiFi向导相关推荐

  1. 如何查看计算机配置语言,电脑如何设置系统语言的方法

    有些用户想要把电脑语言设置为英文或者其他,具体要怎么设置呢?下面由学习啦小编为大家整理了电脑如何设置系统语言的相关方法,希望对大家有帮助! 电脑如何设置系统语言的方法步骤如下 首先,点击"开 ...

  2. android改变系统语言,Android 9.0设置系统语言

    1.系统权限 android:sharedUserId="android.uid.system" 2.签名 通过手动签名的方式,用系统的签名文件为程序签名解决签名的问题,将程序加入 ...

  3. Android 9.0设置系统语言

    1.系统权限 android:sharedUserId="android.uid.system" 2.签名 通过手动签名的方式,用系统的签名文件为程序签名解决签名的问题,将程序加入 ...

  4. Linux怎么查看设置系统语言包

    查看当前系统语言 登陆linux系统打开操作终端之后,输入 echo $LANG可以查看当前使用的系统语言.如 查看安装的语言包 查看是否有中文语言包可以在终端输入 locale命令,如有zh cn  ...

  5. ubuntu怎么设置系统语言英文_Ubuntu系统设置中文语言的方法教程,Ubuntu系统怎么设置中文语言?...

    最近有Ubuntu系统用户反映,由于系统界面的语言都是英文,而用户又不懂英文,这让用户非常苦恼.其实,如果不懂英文的话,我们可以将Ubuntu系统的语言设置为中文.那么,Ubuntu系统怎么设置中文语 ...

  6. android 设置系统壁纸,Android HttpURLConnection下载网络图片设置系统壁纸

    需求: 壁纸是url链接,get就能请求到,所以就用get请求到图片,把图片转化为bitmap,然后设置壁纸. 代码: 这里我封装了工具类 package xxxxx.utils; import an ...

  7. Android 9.0 代码切换系统语言

    最近有个功能要求切换系统语言,通过查询资料找到用反射的方法进行系统设置,但是感觉实现方式太麻烦了,后来看源码发现 LocalePicker 这个类里面有 updateLocale 方法能够轻松完成系统 ...

  8. 计算机自动设置开机,电脑可以设置系统自动开机吗

    电脑设置自动开机功能需要自bios中设置,具体方法参照下面的说明.下面由学习啦小编为你整理了电脑可以设置系统自动开机吗的解决方法,希望对你有帮助! 电脑设置自动开机方法如下 在启动计算机时,按&quo ...

  9. APP修改时区和设置系统语言

    设置时区 添加权限 > <uses-permission android:name="android.permission.SET_TIME_ZONE" /> A ...

最新文章

  1. 在CSDN中如何转载别人的博客
  2. Jenkins与Docker的持续集成实践
  3. uoj#268. 【清华集训2016】数据交互(动态dp+堆)
  4. ALV列(Column)换到行(Row) 之 列上限不固定篇
  5. Calendar Game POJ - 1082(关于日历的博弈问题)
  6. php js 比较,PHP与JS的比较
  7. 重构碎片化知识_荐书|《重构:数字化转型的逻辑》
  8. 学用awk, 在linux下批量改名
  9. .NET生成静态页面并分页
  10. BZOJ 2839: 集合计数 解题报告
  11. adb -s emulator-5554 install JDKCast-PAP.apk
  12. java开发职业规划
  13. Jquery UI 教程
  14. 查看 Python 内置函数的方法
  15. java常量池在哪里_Java常量池详细说明
  16. 关于mis系统开发的一些配置含义
  17. moTzxx-CMS —— [一个基于PHP代码的后台管理系统(ThinkPHP5.1.40)]
  18. 微型投影仪第五篇——Metro UI
  19. jquery鼠标移入文字提示_Jquery hover鼠标经过时弹出div动态提示语
  20. c++ bitset 基本用法

热门文章

  1. 榆熙教育:电商运营必备关键指标公式
  2. Summernote 上传图片至 SMMS 图床 Api
  3. python时间序列分析包_python关于时间序列的分析
  4. 纸壳CMS替换默认实现
  5. 双十一来了,给自己的应用做个icon换脸小功能
  6. Windows xp开机时不显示用户名导致无法登录的错误处理方法
  7. Android home和back事件处理
  8. 红米k30pro工程包工厂包
  9. Objective-C和iPHONE系列教程
  10. linux文件夹内JPG批量转PNG