Way Android P Setting the development of 01

The first step is to find the entrance Setting

   By AndroidManifest.xml file, we can know Settings.java entrance Setting entire program.

  Open Settings.java may find that it inherited from SettingsActivity.java

public class Settings extends SettingsActivity {

    /*
    * Settings subclasses for launching independently.
    */
    public static class AssistGestureSettingsActivity extends SettingsActivity { /* empty */}
    public static class BluetoothSettingsActivity extends SettingsActivity { /* empty */ }
    public static class SimSettingsActivity extends SettingsActivity { /* empty */ }
    public static class TetherSettingsActivity extends SettingsActivity { /* empty */ }
    public static class VpnSettingsActivity extends SettingsActivity { /* empty */ }
......
......

 

  Note annotation (ps: to set a separate subclass start) we can know the reason for the definition of these classes inherited from SettingsActivity in Settings in the Setting is used to set an internal option to start a separate, for example, long press the status bar WIFI small icon to jump to the WiFi settings.

  Here we open SettingsActivity.java

 

public class SettingsActivity extends SettingsDrawerActivity
        implements PreferenceManager.OnPreferenceTreeClickListener,
        PreferenceFragment.OnPreferenceStartFragmentCallback,
        ButtonBarHandler, FragmentManager.OnBackStackChangedListener {

    private static final String LOG_TAG = "SettingsActivity";

 

  It inherited SettingsDrawerActivity (ps: Path /frameworks/base/package/SettingsLib/src/com/android/settingslib/drawer/SettingsActivity.java)

  First seen onResume () method

 @Override
    protected void onResume() {
        super.onResume();
        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
        filter.addDataScheme("package");
        registerReceiver(mPackageReceiver, filter);

        new CategoriesUpdateTask().execute();
    }

  The main added package install, remove, modify, update, monitor, registered radio, start the thread last update.

  Went CategoriesUpdateTask snippet

    private class CategoriesUpdateTask extends AsyncTask<Void, Void, Void> {

        private final CategoryManager mCategoryManager;

        public CategoriesUpdateTask() {
            mCategoryManager = CategoryManager.get(SettingsDrawerActivity.this);
        }

        @Override
        protected Void doInBackground(Void... params) {
            mCategoryManager.reloadAllCategories(SettingsDrawerActivity.this, getSettingPkg());
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            mCategoryManager.updateCategoryFromBlacklist(sTileBlacklist);
            onCategoriesChanged();
        }
    }

  Automatically invoked when CategoriesUpdateTask inherited AsyncTask, unaware of AsyncTask students can learn, doInBackground thread will execute execute (), onPostExecute in the execute () after the call to execute, execute () method to be called in the main thread.  

    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        final ViewGroup parent = findViewById(R.id.content_frame);
        if (parent != null) {
            parent.removeAllViews();
        }
        LayoutInflater.from(this).inflate(layoutResID, parent);
    }

    @Override
    public void setContentView(View view) {
        ((ViewGroup) findViewById(R.id.content_frame)).addView(view);
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
    }

  Here rewrite setContentView () method, so that subclasses can be added to the interface content_frame when calling setContextView.

  SettingsDrawerActivity main set of the child and monitor refresh, do not do too much description here, let us continue to return SettingsActivity

  See onCreate () code snippet

    @Override
    protected void onCreate(Bundle savedState) {
        super.onCreate(savedState);
        Log.d(LOG_TAG, "Starting onCreate");
        long startTime = System.currentTimeMillis();

        final FeatureFactory factory = FeatureFactory.getFactory(this);

        mDashboardFeatureProvider = factory.getDashboardFeatureProvider(this);

        // Should happen before any call to getIntent()
        getMetaData();

        final Intent intent = getIntent();
        if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
            getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
        }

        // Getting Intent properties can only be done after the super.onCreate(...)
        final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);

        final ComponentName cn = intent.getComponent();
        final String className = cn.getClassName();

        mIsShowingDashboard = className.equals(Settings.class.getName());

        // This is a "Sub Settings" when:
        // - this is a real SubSettings
        // - or :settings:show_fragment_as_subsetting is passed to the Intent
        final boolean isSubSettings = this instanceof SubSettings ||
                intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);

        // If this is a sub settings, then apply the SubSettings Theme for the ActionBar content
        // insets
        if (isSubSettings) {
            setTheme(R.style.Theme_SubSettings);
        }

        setContentView(mIsShowingDashboard ?
                R.layout.settings_main_dashboard : R.layout.settings_main_prefs);

        mContent = findViewById(R.id.main_content);

        getFragmentManager().addOnBackStackChangedListener(this);

        if (savedState != null) {
            // We are restarting from a previous saved state; used that to initialize, instead
            // of starting fresh.
            setTitleFromIntent(intent);

            ArrayList<DashboardCategory> categories =
                    savedState.getParcelableArrayList(SAVE_KEY_CATEGORIES);
            if (categories != null) {
                mCategories.clear();
                mCategories.addAll(categories);
                setTitleFromBackStack();
            }
        } else {
            launchSettingFragment(initialFragmentName, isSubSettings, intent);
        }

        final boolean deviceProvisioned = Utils.isDeviceProvisioned(this);
        if (mIsShowingDashboard) {
            findViewById(R.id.search_bar).setVisibility(
                    deviceProvisioned ? View.VISIBLE : View.INVISIBLE);
            findViewById(R.id.action_bar).setVisibility(View.GONE);
            final Toolbar toolbar = findViewById(R.id.search_action_bar);
            FeatureFactory.getFactory(this).getSearchFeatureProvider()
                    .initSearchToolbar(this, toolbar);
            setActionBar(toolbar);

            // Please forgive me for what I am about to do.
            //
            // Need to make the navigation icon non-clickable so that the entire card is clickable
            // and goes to the search UI. Also set the background to null so there's no ripple.
            View navView = toolbar.getNavigationView();
            navView.setClickable(false);
            navView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
            navView.setBackground(null);
        }

        ActionBar actionBar = getActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(deviceProvisioned);
            actionBar.setHomeButtonEnabled(deviceProvisioned);
            actionBar.setDisplayShowTitleEnabled(!mIsShowingDashboard);
        }
        mSwitchBar = findViewById(R.id.switch_bar);
        if (mSwitchBar != null) {
            mSwitchBar.setMetricsTag(getMetricsTag());
        }

        // see if we should show Back/Next buttons
        if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {

            View buttonBar = findViewById(R.id.button_bar);
            if (buttonBar != null) {
                buttonBar.setVisibility(View.VISIBLE);

                Button backButton = (Button) findViewById(R.id.back_button);
                backButton.setOnClickListener(new OnClickListener() {
                    public void onClick(View v) {
                        setResult(RESULT_CANCELED, null);
                        finish();
                    }
                });
                Button skipButton = (Button) findViewById(R.id.skip_button);
                skipButton.setOnClickListener(new OnClickListener() {
                    public void onClick(View v) {
                        setResult(RESULT_OK, null);
                        finish();
                    }
                });
                mNextButton = (Button) findViewById(R.id.next_button);
                mNextButton.setOnClickListener(new OnClickListener() {
                    public void onClick(View v) {
                        setResult(RESULT_OK, null);
                        finish();
                    }
                });

                // set our various button parameters
                if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) {
                    String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT);
                    if (TextUtils.isEmpty(buttonText)) {
                        mNextButton.setVisibility(View.GONE);
                    } else {
                        mNextButton.setText(buttonText);
                    }
                }
                if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) {
                    String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT);
                    if (TextUtils.isEmpty(buttonText)) {
                        backButton.setVisibility(View.GONE);
                    } else {
                        backButton.setText(buttonText);
                    }
                }
                if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
                    skipButton.setVisibility(View.VISIBLE);
                }
            }
        }

  the getMetaData () method, ps: for获取activity 的meta-data字段

    private void getMetaData() {
        try {
            ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
                    PackageManager.GET_META_DATA);
            if (ai == null || ai.metaData == null) return;
            mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
        } catch (NameNotFoundException nnfe) {
            // No recovery
            Log.d(LOG_TAG, "Cannot get Metadata for: " + getComponentName().toString());
        }
    }

  mFragmentClass obtained value corresponding meta-data, i.e. full path name of the package of Fragment; META_DATA_KEY_FRAGMENT_CLASS = "com.android.settings.FRAGMENT_CLASS".

  Then see getIntent (), SettingsActivity rewrite this method.

    @Override
    public Intent getIntent() {
        Intent superIntent = super.getIntent();
        String startingFragment = getStartingFragmentClass(superIntent);
        // This is called from super.onCreate, isMultiPane() is not yet reliable
        // Do not use onIsHidingHeaders either, which relies itself on this method
        if (startingFragment != null) {
            Intent modIntent = new Intent(superIntent);
            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
            Bundle args = superIntent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
            if (args != null) {
                args = new Bundle(args);
            } else {
                args = new Bundle();
            }
            args.putParcelable("intent", superIntent);
            modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
            return modIntent;
        }
        return superIntent;
    }

  The code is not complicated, in essence, is going to jump interface assigned to EXTRA_SHOW_FRAGMENT.

   OnCreate continue setContentView went down ()

        setContentView(mIsShowingDashboard ?
                R.layout.settings_main_dashboard : R.layout.settings_main_prefs);

  mIsShowingDashboard is to judge whether the display interface to the class name and the value Settings consistent results, display different layout.

  When you set Title, if savedState is not empty, it will get from the intent of the title, otherwise launchSettingFragment direct () method

    @VisibleForTesting
    void launchSettingFragment(String initialFragmentName, boolean isSubSettings, Intent intent) {
        if (!mIsShowingDashboard && initialFragmentName != null) {
            setTitleFromIntent(intent);

            Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
            switchToFragment(initialFragmentName, initialArguments, true, false,
                    mInitialTitleResId, mInitialTitle, false);
        } else {
            // Show search icon as up affordance if we are displaying the main Dashboard
            mInitialTitleResId = R.string.dashboard_title;

            switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false,
                    mInitialTitleResId, mInitialTitle, false);
        }
    }

  Similarly, there is a determination to be the main interface or subclass Setting screen, and select a different title.

  There is a switchToFragment () method, filling contents into the main content, the method used is the transaction.

    /**
     * Switch to a specific Fragment with taking care of validation, Title and BackStack
     */
    private Fragment switchToFragment(String fragmentName, Bundle args, boolean validate,
            boolean addToBackStack, int titleResId, CharSequence title, boolean withTransition) {
        Log.d(LOG_TAG, "Switching to fragment " + fragmentName);
        if (validate && !isValidFragment(fragmentName)) {
            throw new IllegalArgumentException("Invalid fragment for this activity: "
                    + fragmentName);
        }
        Fragment f = Fragment.instantiate(this, fragmentName, args);
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        transaction.replace(R.id.main_content, f);
        if (withTransition) {
            TransitionManager.beginDelayedTransition(mContent);
        }
        if (addToBackStack) {
            transaction.addToBackStack(SettingsActivity.BACK_STACK_PREFS);
        }
        if (titleResId > 0) {
            transaction.setBreadCrumbTitle(titleResId);
        } else if (title != null) {
            transaction.setBreadCrumbTitle(title);
        }
        transaction.commitAllowingStateLoss();
        getFragmentManager().executePendingTransactions();
        Log.d(LOG_TAG, "Executed frag manager pendingTransactions");
        return f;
    }

  OnCreate continue to go down, judge Setting main interface or sub-class interface, to decide whether to set the search bar (considering whether the device supports), then the various buttons appear at the top of the interface loading process ends.

  

 

 

 

 

 

  

Guess you like

Origin www.cnblogs.com/nextbug/p/12143718.html