Android恢复出厂设置源码分析,基于Android 6.0

来源:互联网 发布:js tip 提示框 样式 编辑:程序博客网 时间:2024/04/30 06:35

近两天解决一些关于恢复出厂设置的问题,对此略有了解,注释了部分代码,给大家分享

设置>>>备份与重置>>>恢复出厂设置>>>… …

对应得类的路径:
\packages\apps\Settings\src\com\android\settings\MasterClear.java
代码如下所示:

package com.android.settings;import android.accounts.Account;import android.accounts.AccountManager;import android.accounts.AuthenticatorDescription;import android.app.Activity;import android.app.Fragment;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.content.pm.UserInfo;import android.content.res.Resources;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.os.Environment;import android.os.Process;import android.os.SystemProperties;import android.os.UserHandle;import android.os.UserManager;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.CheckBox;import android.widget.LinearLayout;import android.widget.TextView;import com.android.internal.logging.MetricsLogger;import java.util.List;import android.content.IntentFilter;import android.content.BroadcastReceiver;import android.widget.Toast;/** *确认并执行设备的出厂设置。多重确认是必需的: 首先,点击恢复出厂设置按钮,如果用户已经设置键盘锁,则跳转到解锁程序 接着是该类的内容,出现提示一些提示语,警告即将删除出的类容。 并根据不同情况提供选着框(与其它版本不同的是Android 6.0 添加了安全机制 ,以前任何时候都有“是否格式化SD卡的复选框”, 在这个版本中根据不同情况来显示或隐藏) */ //InstrumentedFragment.java类在同一包内 继承PreferenceFragment类public class MasterClear extends InstrumentedFragment {    //打印log用    private static final String TAG = "MasterClear";    private static final int KEYGUARD_REQUEST = 55;    static final String ERASE_EXTERNAL_EXTRA = "erase_sd";    private View mContentView;    private Button mInitiateButton;    private View mExternalStorageContainer;    private CheckBox mExternalStorage;    //自己添加的参数 用来监听电量    private int mBatteryLevel = 0xffff;    /    /**     * Keyguard validation is run using the standard {@link ConfirmLockPattern}     * component as a subactivity     * @param request the request code to be returned once confirmation finishes     * @return true if confirmation launched     */    //键盘锁    private boolean runKeyguardConfirmation(int request) {        Resources res = getActivity().getResources();        return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(                request, res.getText(R.string.master_clear_title));    }    //返回解锁状态    @Override    public void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if (requestCode != KEYGUARD_REQUEST) {            return;        }        // 如果解锁成功则进入下一个活动,否者恢复原始状态        if (resultCode == Activity.RESULT_OK) {            showFinalConfirmation();        } else {            establishInitialState();        }    }   //将复选框的值带给下个活动(是否格式化SD卡),启动下一个活动    private void showFinalConfirmation() {        Bundle args = new Bundle();        args.putBoolean(ERASE_EXTERNAL_EXTRA, mExternalStorage.isChecked());        ((SettingsActivity) getActivity()).startPreferencePanel(MasterClearConfirm.class.getName(),                args, R.string.master_clear_confirm_title, null, null, 0);    }    /**     * 如果用户点击开始恢复出厂设置     *如果用户已经设置键盘锁,则跳转到解锁程序     *没有可用的键盘锁,我们只需进入最后确认提示。     */    private final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {        public void onClick(View v) {        //自己添加的,监听电量 start            /* if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {                showFinalConfirmation();            } */            if(SystemProperties.getInt("ro.my.phone.reset",0)== 1){                if(mBatteryLevel != 0xffff) {                    if (mBatteryLevel >= 15) {                        if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {                            showFinalConfirmation();                        }                    }else{                        Resources res = getActivity().getResources();                        Toast.makeText( getActivity().getApplicationContext(), res.getText(R.string.restore_battery_tip), Toast.LENGTH_SHORT).show();                    }                }                           }else{                //源码                    if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {                        showFinalConfirmation();                    }            }        }        //自己添加的,监听电量 end    };    /**     * In its initial state, the activity presents a button for the user to     * click in order to initiate a confirmation sequence.  This method is     * called from various other points in the code to reset the activity to     * this base state.     *     * <p>Reinflating views from resources is expensive and prevents us from     * caching widget pointers, so we use a single-inflate pattern:  we lazy-     * inflate each view, caching all of the widget pointers we'll need at the     * time, then simply reuse the inflated views directly whenever we need     * to change contents.     */    private void establishInitialState() {        mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_master_clear);        mInitiateButton.setOnClickListener(mInitiateListener);        mExternalStorageContainer = mContentView.findViewById(R.id.erase_external_container);        mExternalStorage = (CheckBox) mContentView.findViewById(R.id.erase_external);        /*         * 如果是外部存储仿真,这不需要单独的格式化,会自动格式化其中一部分目录,而不是全部目录         * 如果外部存储为不可拆卸的,并且已经加密,这不要被格式化(新版本机制)         */         //是否是外部存储仿真        boolean isExtStorageEmulated = Environment.isExternalStorageEmulated();        //Environment.isExternalStorageRemovable()可拆卸则返回true,        if (isExtStorageEmulated                || (!Environment.isExternalStorageRemovable() && isExtStorageEncrypted())) {            //隐藏布局,不显示复选框            mExternalStorageContainer.setVisibility(View.GONE);            final View externalOption = mContentView.findViewById(R.id.erase_external_option_text);            externalOption.setVisibility(View.GONE);            //显示部分警告            final View externalAlsoErased = mContentView.findViewById(R.id.also_erases_external);            externalAlsoErased.setVisibility(View.VISIBLE);            // 如果不是外部存储仿真,则是加密分区 ,这不要被格式化            mExternalStorage.setChecked(!isExtStorageEmulated);        } else {            mExternalStorageContainer.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    mExternalStorage.toggle();                }            });        }      //一些初始化设置        final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);        loadAccountList(um);        StringBuffer contentDescription = new StringBuffer();        View masterClearContainer = mContentView.findViewById(R.id.master_clear_container);        getContentDescription(masterClearContainer, contentDescription);        masterClearContainer.setContentDescription(contentDescription);    }    private void getContentDescription(View v, StringBuffer description) {       if (v instanceof ViewGroup) {           ViewGroup vGroup = (ViewGroup) v;           for (int i = 0; i < vGroup.getChildCount(); i++) {               View nextChild = vGroup.getChildAt(i);               getContentDescription(nextChild, description);           }       } else if (v instanceof TextView) {           TextView vText = (TextView) v;           description.append(vText.getText());           description.append(","); // Allow Talkback to pause between sections.       }    }    //是否加密    private boolean isExtStorageEncrypted() {        String state = SystemProperties.get("vold.decrypt");        return !"".equals(state);    }    //    private void loadAccountList(final UserManager um) {        View accountsLabel = mContentView.findViewById(R.id.accounts_label);        LinearLayout contents = (LinearLayout)mContentView.findViewById(R.id.accounts);        contents.removeAllViews();        Context context = getActivity();        final List<UserInfo> profiles = um.getProfiles(UserHandle.myUserId());        final int profilesSize = profiles.size();        AccountManager mgr = AccountManager.get(context);        LayoutInflater inflater = (LayoutInflater)context.getSystemService(                Context.LAYOUT_INFLATER_SERVICE);        int accountsCount = 0;        for (int profileIndex = 0; profileIndex < profilesSize; profileIndex++) {            final UserInfo userInfo = profiles.get(profileIndex);            final int profileId = userInfo.id;            final UserHandle userHandle = new UserHandle(profileId);            Account[] accounts = mgr.getAccountsAsUser(profileId);            final int N = accounts.length;            if (N == 0) {                continue;            }            accountsCount += N;            AuthenticatorDescription[] descs = AccountManager.get(context)                    .getAuthenticatorTypesAsUser(profileId);            final int M = descs.length;            View titleView = Utils.inflateCategoryHeader(inflater, contents);            final TextView titleText = (TextView) titleView.findViewById(android.R.id.title);            titleText.setText(userInfo.isManagedProfile() ? R.string.category_work                    : R.string.category_personal);            contents.addView(titleView);            for (int i = 0; i < N; i++) {                Account account = accounts[i];                AuthenticatorDescription desc = null;                for (int j = 0; j < M; j++) {                    if (account.type.equals(descs[j].type)) {                        desc = descs[j];                        break;                    }                }                if (desc == null) {                    Log.w(TAG, "No descriptor for account name=" + account.name                            + " type=" + account.type);                    continue;                }                Drawable icon = null;                try {                    if (desc.iconId != 0) {                        Context authContext = context.createPackageContextAsUser(desc.packageName,                                0, userHandle);                        icon = context.getPackageManager().getUserBadgedIcon(                                authContext.getDrawable(desc.iconId), userHandle);                    }                } catch (PackageManager.NameNotFoundException e) {                    Log.w(TAG, "Bad package name for account type " + desc.type);                } catch (Resources.NotFoundException e) {                    Log.w(TAG, "Invalid icon id for account type " + desc.type, e);                }                if (icon == null) {                    icon = context.getPackageManager().getDefaultActivityIcon();                }                TextView child = (TextView)inflater.inflate(R.layout.master_clear_account,                        contents, false);                child.setText(account.name);                child.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);                contents.addView(child);            }        }        if (accountsCount > 0) {            accountsLabel.setVisibility(View.VISIBLE);            contents.setVisibility(View.VISIBLE);        }        // Checking for all other users and their profiles if any.        View otherUsers = mContentView.findViewById(R.id.other_users_present);        final boolean hasOtherUsers = (um.getUserCount() - profilesSize) > 0;        otherUsers.setVisibility(hasOtherUsers ? View.VISIBLE : View.GONE);    }    //加载布局    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,            Bundle savedInstanceState) {        if (!Process.myUserHandle().isOwner()                || UserManager.get(getActivity()).hasUserRestriction(                UserManager.DISALLOW_FACTORY_RESET)) {            return inflater.inflate(R.layout.master_clear_disallowed_screen, null);        }        mContentView = inflater.inflate(R.layout.master_clear, null);        establishInitialState();        return mContentView;    }    @Override    protected int getMetricsCategory() {        return MetricsLogger.MASTER_CLEAR;    }    //自己添加的,监听电量  在低电量下不允许恢复出厂设置  start    private IntentFilter mIntentFilter = null;    private BroadcastReceiver mIntentReceiver = null;    public void onCreate(Bundle icicle){        super.onCreate(icicle);        Log.i(TAG,"onCreate");        if(SystemProperties.getInt("ro.wind.phone.reset",0)== 1){            mIntentFilter = new IntentFilter();            mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);            mIntentReceiver = new BroadcastReceiver() {                public void onReceive(Context context, Intent intent) {                    String action = intent.getAction();                    if(action.equals(Intent.ACTION_BATTERY_CHANGED)){                        mBatteryLevel = intent.getIntExtra("level",0);                        Log.i(TAG, "mBatteryLevel = " + mBatteryLevel);                    }                }            };        }    }    public void onStart() {        super.onStart();        Log.i(TAG,"onStart");        if(SystemProperties.getInt("ro.wind.phone.reset",0)== 1){            getActivity().registerReceiver(mIntentReceiver, mIntentFilter);        }    }    public void onStop() {        super.onStop();        Log.i(TAG,"onStop");        if(SystemProperties.getInt("ro.wind.phone.reset",0)== 1){            getActivity().unregisterReceiver(mIntentReceiver);        }        mBatteryLevel = 0xffff;    }    //自己添加的,监听电量  在低电量下不允许恢复出厂设置  end}

该类的布局:
\packages\apps\Settings\res\layout\master_clear.xml

<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2010 The Android Open Source Project     Licensed under the Apache License, Version 2.0 (the "License");     you may not use this file except in compliance with the License.     You may obtain a copy of the License at          http://www.apache.org/licenses/LICENSE-2.0     Unless required by applicable law or agreed to in writing, software     distributed under the License is distributed on an "AS IS" BASIS,     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.     See the License for the specific language governing permissions and     limitations under the License.--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    >    <ScrollView            android:layout_width="match_parent"            android:layout_height="0dip"            android:layout_marginStart="12dp"            android:layout_marginEnd="12dp"            android:layout_marginTop="12dp"            android:layout_weight="1">        <LinearLayout android:id="@+id/master_clear_container"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:orientation="vertical">            <TextView                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:includeFontPadding="false"                android:textSize="18sp"                android:text="@string/master_clear_desc" />            <TextView android:id="@+id/also_erases_external"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:includeFontPadding="false"                android:visibility="gone"                android:textSize="18sp"                android:text="@string/master_clear_desc_also_erases_external" />            <TextView android:id="@+id/accounts_label"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:visibility="gone"                android:textSize="18sp"                android:text="@string/master_clear_accounts" />            <LinearLayout android:id="@+id/accounts"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:orientation="vertical"                    android:visibility="gone">                <!-- Do not add any children here as they will be removed in the MasterClear.java                    code. A list of accounts will be inserted programmatically. -->            </LinearLayout>            <TextView android:id="@+id/other_users_present"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:visibility="gone"                android:textSize="18sp"                android:text="@string/master_clear_other_users_present" />            <TextView android:id="@+id/erase_external_option_text"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:textSize="18sp"                android:text="@string/master_clear_desc_erase_external_storage" />            <LinearLayout android:id="@+id/erase_external_container"                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:orientation="horizontal"                    android:focusable="true"                    android:clickable="true">                <CheckBox android:id="@+id/erase_external"                        android:layout_width="wrap_content"                        android:layout_height="wrap_content"                        android:layout_gravity="center_vertical"                        android:paddingEnd="8dp"                        android:focusable="false"                        android:clickable="false"                        android:duplicateParentState="true" />                <LinearLayout android:layout_width="match_parent"                        android:layout_height="wrap_content"                        android:layout_gravity="center_vertical"                        android:orientation="vertical">                    <TextView                        android:layout_width="wrap_content"                        android:layout_height="wrap_content"                        android:paddingTop="12dp"                        android:textSize="18sp"                        android:text="@string/erase_external_storage" />                    <TextView                        android:layout_width="wrap_content"                        android:layout_height="wrap_content"                        android:paddingTop="4sp"                        android:textSize="14sp"                        android:text="@string/erase_external_storage_description" />                </LinearLayout>            </LinearLayout>        </LinearLayout>    </ScrollView>    <Button            android:id="@+id/initiate_master_clear"            android:layout_gravity="center_horizontal"            android:layout_marginTop="20dip"            android:layout_marginBottom="12dip"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="@string/master_clear_button_text"            android:gravity="center" /></LinearLayout>

跳转到下一个类,也就是恢复出厂设置核心类:
\packages\apps\Settings\src\com\android\settings\MasterClearConfirm.java
这里只贴出主要部分代码

 /*恢复出厂设置方法  发送一个广播,(!!! 以前旧版本会在此活动界面添加是否格式化外部存储的复选框 根据复选框的值来发送不同的广播))*/    private void doMasterClear() {        Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);        intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");        intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, mEraseSdCard);        getActivity().sendBroadcast(intent);        // Intent handling is asynchronous -- assume it will happen soon.    }

该类的布局文件:

<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2010 The Android Open Source Project     Licensed under the Apache License, Version 2.0 (the "License");     you may not use this file except in compliance with the License.     You may obtain a copy of the License at          http://www.apache.org/licenses/LICENSE-2.0     Unless required by applicable law or agreed to in writing, software     distributed under the License is distributed on an "AS IS" BASIS,     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.     See the License for the specific language governing permissions and     limitations under the License.--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    >    <TextView        android:id="@+id/master_clear_confirm"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginStart="12dp"        android:layout_marginEnd="12dp"        android:layout_marginTop="12dp"        android:textSize="20sp"        android:text="@string/master_clear_final_desc" />    <Button android:id="@+id/execute_master_clear"        android:layout_gravity="center_horizontal"        android:layout_marginTop="40dip"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/master_clear_final_button_text"        android:gravity="center" /></LinearLayout>

作者水平有限,有不对之处,敬请谅解,指正!谢谢!

1 0
原创粉丝点击