android框架_5.0的Settings模块之WIFI模块的分析3_009

今天的主角:com.android.settings.wifi.WifiSettings基类;

一、WifiSettings.java

/**
 * Two types of UI are provided here.
 * 有两种UI界面,在这里,第一种是手机需要链接wifi激活的界面,第二种是激活的正常显示界面
 * The first is for "usual Settings", appearing as any other Setup fragment.
 *
 * The second is for Setup Wizard, with a simplified interface that hides the action bar
 * and menus.
 */
public class WifiSettings extends RestrictedSettingsFragment
        implements DialogInterface.OnClickListener, Indexable  {

    private static final String TAG = "WifiSettings";

1、按照惯例,分析类中有哪些继承和实现

2、首先继承一个RestrictedSettingsFragment类,同时实现了 DialogInterface.OnClickListener接口和Indexable接口;

3、针对RestrictedSettingsFragment的作用

 

4、WifiSettings的结构类型,我们先暂时分析最顶层上的fragment吧;

 

二、PreferenceFragment类的分析

public abstract class PreferenceFragment extends Fragment implements
        PreferenceManager.OnPreferenceTreeClickListener {

    private static final String PREFERENCES_TAG = "android:preferences";

    private PreferenceManager mPreferenceManager;
    private ListView mList;
    private boolean mHavePrefs;
    private boolean mInitDone;

    private int mLayoutResId = com.android.internal.R.layout.preference_list_fragment;

1、从上可以看出集成Fragment,实现了接口PreferenceManager.OnPreferenceTreeClickListener;

    /**
     * Interface definition for a callback to be invoked when a
     * {@link Preference} in the hierarchy rooted at this {@link PreferenceScreen} is
     * clicked.
     *
     * @hide
     */
    public interface OnPreferenceTreeClickListener {
        /**
         * Called when a preference in the tree rooted at this
         * {@link PreferenceScreen} has been clicked.
         * 
         * @param preferenceScreen The {@link PreferenceScreen} that the
         *        preference is located in.
         * @param preference The preference that was clicked.
         * @return Whether the click was handled.
         */
        boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference);
    }

2、接口实现中,有一个onPreferenceTreeClick方法;

 

三、重点分析基类SettingsPreferenceFragment

/**
 * Base class for Settings fragments, with some helper functions and dialog management.
 */
public class SettingsPreferenceFragment extends PreferenceFragment implements DialogCreatable {

    private static final String TAG = "SettingsPreferenceFragment";

    private static final int MENU_HELP = Menu.FIRST + 100;//菜单帮助id
    private static final int DELAY_HIGHLIGHT_DURATION_MILLIS = 600;//延迟高亮

    private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted";//保存高亮

    private SettingsDialogFragment mDialogFragment;//对话框形式的Fragment

    private String mHelpUrl;//帮助url

    // Cache the content resolver for async callbacks
    private ContentResolver mContentResolver;

    private String mPreferenceKey;
    private boolean mPreferenceHighlighted = false;//是否高亮
    private Drawable mHighlightDrawable;//高亮的drawable

    private ListAdapter mCurrentRootAdapter;//当前根视图的adapter
    private boolean mIsDataSetObserverRegistered = false;
    //数据集合观察者
    private DataSetObserver mDataSetObserver = new DataSetObserver() {
        @Override
        public void onChanged() {
            highlightPreferenceIfNeeded();
        }

        @Override
        public void onInvalidated() {
            highlightPreferenceIfNeeded();
        }
    };

1、开始定义了一些基本的数据信息;

private ViewGroup mPinnedHeaderFrameLayout;

@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);

    if (icicle != null) {//获取是否高亮的key值
        mPreferenceHighlighted = icicle.getBoolean(SAVE_HIGHLIGHTED_KEY);
    }

    // Prepare help url and enable menu if necessary
    int helpResource = getHelpResource();
    if (helpResource != 0) {//获取帮助菜单的url和资源id
        mHelpUrl = getResources().getString(helpResource);
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    //初始化视图view和mPinnedHeaderFrameLayout
    final View root = super.onCreateView(inflater, container, savedInstanceState);
    mPinnedHeaderFrameLayout = (ViewGroup) root.findViewById(R.id.pinned_header);
    return root;
}
//设置视图,也就是加载视图pinnedHeader
public void setPinnedHeaderView(View pinnedHeader) {
    mPinnedHeaderFrameLayout.addView(pinnedHeader);
    mPinnedHeaderFrameLayout.setVisibility(View.VISIBLE);
}
//清除视图
public void clearPinnedHeaderView() {
    mPinnedHeaderFrameLayout.removeAllViews();
    mPinnedHeaderFrameLayout.setVisibility(View.GONE);
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
		//保存是否高亮的变量
    outState.putBoolean(SAVE_HIGHLIGHTED_KEY, mPreferenceHighlighted);
}

2、获取一些初始化的数据;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (!TextUtils.isEmpty(mHelpUrl)) {//显示帮助菜单
        setHasOptionsMenu(true);
    }
}

@Override
public void onResume() {
    super.onResume();

    final Bundle args = getArguments();
    if (args != null) {//获取mPreferenceKey,从字段EXTRA_FRAGMENT_ARG_KEY中
        mPreferenceKey = args.getString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY);
        highlightPreferenceIfNeeded();
    }
}

@Override
protected void onBindPreferences() {
    registerObserverIfNeeded();//注册本地数据集合监听器
}

@Override
protected void onUnbindPreferences() {
    unregisterObserverIfNeeded();
}

@Override
public void onStop() {
    super.onStop();

    unregisterObserverIfNeeded();
}
//注册观察者
public void registerObserverIfNeeded() {
    if (!mIsDataSetObserverRegistered) {
        if (mCurrentRootAdapter != null) {
            mCurrentRootAdapter.unregisterDataSetObserver(mDataSetObserver);
        }
        mCurrentRootAdapter = getPreferenceScreen().getRootAdapter();
        mCurrentRootAdapter.registerDataSetObserver(mDataSetObserver);
        mIsDataSetObserverRegistered = true;
    }
}
//反注册观察者
public void unregisterObserverIfNeeded() {
    if (mIsDataSetObserverRegistered) {
        if (mCurrentRootAdapter != null) {
            mCurrentRootAdapter.unregisterDataSetObserver(mDataSetObserver);
            mCurrentRootAdapter = null;
        }
        mIsDataSetObserverRegistered = false;
    }
}
//是否有必要高亮Preference
public void highlightPreferenceIfNeeded() {
    if (isAdded() && !mPreferenceHighlighted &&!TextUtils.isEmpty(mPreferenceKey)) {
        highlightPreference(mPreferenceKey);
    }
}
//获取高亮的图片Drawable
private Drawable getHighlightDrawable() {
    if (mHighlightDrawable == null) {
        mHighlightDrawable = getActivity().getDrawable(R.drawable.preference_highlight);
    }
    return mHighlightDrawable;
}
/**
 * Return a valid ListView position or -1 if none is found
 * 返回一个有效的listview的position
 */
private int canUseListViewForHighLighting(String key) {
    if (!hasListView()) {
        return -1;
    }

    ListView listView = getListView();
    ListAdapter adapter = listView.getAdapter();

    if (adapter != null && adapter instanceof PreferenceGroupAdapter) {
        return findListPositionFromKey(adapter, key);
    }

    return -1;
}
//通过key值查找高亮的Preference
private void highlightPreference(String key) {
    final Drawable highlight = getHighlightDrawable();
		//listview查找position
    final int position = canUseListViewForHighLighting(key);
    if (position >= 0) {
        mPreferenceHighlighted = true;

        final ListView listView = getListView();
        final ListAdapter adapter = listView.getAdapter();
				//设置高亮drawable
        ((PreferenceGroupAdapter) adapter).setHighlightedDrawable(highlight);
        ((PreferenceGroupAdapter) adapter).setHighlighted(position);

        Log.w(TAG, "highlightPreference, key = " + key + ", this = " + this);
        listView.post(new Runnable() {
            @Override
            public void run() {
                Log.w(TAG, "highlightPreference, 1st runnable runs, this = " + this);
                listView.setSelection(position);//设置selection
                listView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Log.w(TAG, "highlightPreference, 2st runnable runs, this = " + this);
                        final int index = position - listView.getFirstVisiblePosition();
                        if (index >= 0 && index < listView.getChildCount()) {
                            final View v = listView.getChildAt(index);
                            final int centerX = v.getWidth() / 2;
                            final int centerY = v.getHeight() / 2;
                            highlight.setHotspot(centerX, centerY);
                            /// M: CR ALPS01838309,remove the action
                            //v.setPressed(true);
                            //v.setPressed(false);
                        }
                    }
                }, DELAY_HIGHLIGHT_DURATION_MILLIS);
            }
        });
    }
}
//在ListAdapter中通过key找到position
private int findListPositionFromKey(ListAdapter adapter, String key) {
    final int count = adapter.getCount();
    for (int n = 0; n < count; n++) {
        final Object item = adapter.getItem(n);
        if (item instanceof Preference) {
            Preference preference = (Preference) item;
            final String preferenceKey = preference.getKey();
            if (preferenceKey != null && preferenceKey.equals(key)) {
                return n;
            }
        }
    }
    return -1;
}

 

//通过key移除选项
protected void removePreference(String key) {
    Preference pref = findPreference(key);
    if (pref != null) {
        getPreferenceScreen().removePreference(pref);
    }
}

 

    public static class SettingsDialogFragment extends DialogFragment {
        private static final String KEY_DIALOG_ID = "key_dialog_id";
        private static final String KEY_PARENT_FRAGMENT_ID = "key_parent_fragment_id";

        private int mDialogId;

        private Fragment mParentFragment;

        private DialogInterface.OnCancelListener mOnCancelListener;
        private DialogInterface.OnDismissListener mOnDismissListener;

        public SettingsDialogFragment() {
            /* do nothing */
        }

        public SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
            mDialogId = dialogId;
            if (!(fragment instanceof Fragment)) {
                throw new IllegalArgumentException("fragment argument must be an instance of "
                        + Fragment.class.getName());
            }
            mParentFragment = (Fragment) fragment;
        }
//调用返回按键
public void finish() {
    getActivity().onBackPressed();
}
//启动fragment
public boolean startFragment(Fragment caller, String fragmentClass, int titleRes,
        int requestCode, Bundle extras) {
    final Activity activity = getActivity();
    if (activity instanceof SettingsActivity) {
        SettingsActivity sa = (SettingsActivity) activity;
        sa.startPreferencePanel(fragmentClass, extras, titleRes, null, caller, requestCode);
        return true;
    } else if (activity instanceof PreferenceActivity) {
        PreferenceActivity sa = (PreferenceActivity) activity;
        sa.startPreferencePanel(fragmentClass, extras, titleRes, null, caller, requestCode);
        return true;
    } else {
        Log.w(TAG,
                "Parent isn't SettingsActivity nor PreferenceActivity, thus there's no way to "
                + "launch the given Fragment (name: " + fragmentClass
                + ", requestCode: " + requestCode + ")");
        return false;
    }
}

 

 

四、重点分析基类:RestrictedSettingsFragment

 

 

/**
 * Base class for settings screens that should be pin protected when in restricted mode.
 * The constructor for this class will take the restriction key that this screen should be
 * locked by.  If {@link RestrictionsManager.hasRestrictionsProvider()} and
 * {@link UserManager.hasUserRestriction()}, then the user will have to enter the restrictions
 * pin before seeing the Settings screen.
 *
 * If this settings screen should be pin protected whenever
 * {@link RestrictionsManager.hasRestrictionsProvider()} returns true, pass in
 * {@link RESTRICT_IF_OVERRIDABLE} to the constructor instead of a restrictions key.
 */
public class RestrictedSettingsFragment extends SettingsPreferenceFragment {

    protected static final String RESTRICT_IF_OVERRIDABLE = "restrict_if_overridable";

    // No RestrictedSettingsFragment screens should use this number in startActivityForResult.
    private static final int REQUEST_PIN_CHALLENGE = 12309;

    private static final String KEY_CHALLENGE_SUCCEEDED = "chsc";
    private static final String KEY_CHALLENGE_REQUESTED = "chrq";

    // If the restriction PIN is entered correctly.
    private boolean mChallengeSucceeded;
    private boolean mChallengeRequested;

    private UserManager mUserManager;
    private RestrictionsManager mRestrictionsManager;

    private final String mRestrictionKey;

    // Receiver to clear pin status when the screen is turned off.
    private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!mChallengeRequested) {
                mChallengeSucceeded = false;
                mChallengeRequested = false;
            }
        }
    };

1、从类名可以很明显的看出,这是一个限制的Fragment类

    /**
     * @param restrictionKey The restriction key to check before pin protecting
     *            this settings page. Pass in {@link RESTRICT_IF_OVERRIDABLE} if it should
     *            be protected whenever a restrictions provider is set. Pass in
     *            null if it should never be protected.
     */
    public RestrictedSettingsFragment(String restrictionKey) {
        mRestrictionKey = restrictionKey;
    }

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        mRestrictionsManager = (RestrictionsManager) getSystemService(Context.RESTRICTIONS_SERVICE);
        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);

        if (icicle != null) {
            mChallengeSucceeded = icicle.getBoolean(KEY_CHALLENGE_SUCCEEDED, false);
            mChallengeRequested = icicle.getBoolean(KEY_CHALLENGE_REQUESTED, false);
        }

        IntentFilter offFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        offFilter.addAction(Intent.ACTION_USER_PRESENT);
        getActivity().registerReceiver(mScreenOffReceiver, offFilter);
    }

2、获取intent的extra数据,注册广播;

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        if (getActivity().isChangingConfigurations()) {
            outState.putBoolean(KEY_CHALLENGE_REQUESTED, mChallengeRequested);
            outState.putBoolean(KEY_CHALLENGE_SUCCEEDED, mChallengeSucceeded);
        }
    }

    @Override
    public void onResume() {
        super.onResume();

        if (shouldBeProviderProtected(mRestrictionKey)) {
            ensurePin();
        }
    }

    @Override
    public void onDestroy() {
        getActivity().unregisterReceiver(mScreenOffReceiver);
        super.onDestroy();
    }

3、保存值,反注销广播;

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_PIN_CHALLENGE) {
            if (resultCode == Activity.RESULT_OK) {
                mChallengeSucceeded = true;
                mChallengeRequested = false;
            } else {
                mChallengeSucceeded = false;
            }
            return;
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    private void ensurePin() {
        if (!mChallengeSucceeded && !mChallengeRequested
                && mRestrictionsManager.hasRestrictionsProvider()) {
            Intent intent = mRestrictionsManager.createLocalApprovalIntent();
            if (intent != null) {
                mChallengeRequested = true;
                mChallengeSucceeded = false;
                PersistableBundle request = new PersistableBundle();
                request.putString(RestrictionsManager.REQUEST_KEY_MESSAGE,
                        getResources().getString(R.string.restr_pin_enter_admin_pin));
                intent.putExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE, request);
                startActivityForResult(intent, REQUEST_PIN_CHALLENGE);
            }
        }
    }

4、保证pin

继续继续。。。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值