android系统应用之Settings

Setting作为安卓一个比较重要的系统级应用,为用户提供一些系统项的设置。原生android系统的源码路径:/packages/apps/Settings。但MTK厂商的源码包中对该应用进行了重构其源码路径:/vendor/mediatek/proprietary/packages/apps/MtkSettings。

一、Setting

1、入口Activity

android应用程序的入口比较简单,可以直接查看AndroidManifest.xml,里面有配置应用的包名、版本、权限、四大组件等。Setting配置文件代码如下:


           
    
      
    
    
        
        
        
            
                
                
            
            
        
        
        
            
                
                
                
            
            
        
        
            
                
                
            
        
        
        
    

上面的配置文件第一个被android.intent.action.MAIN修饰的是一个activity-alias标签,该标签意思是一个activity的别名。即它是一个已经存在的activity的别名(这个已经存在的activity被属性targetActivity修饰),因此我们可以认为Settings程序的主界面是SettingsHomepageActivity.java。值得注意的是该标签的name属性并不会指定某个java文件,它只是一个命名标志而已,与他绑定相关的java文件是targetActivity对应的内容,因此这里只是把主界面命名为Settings,但是与源代码中的com.android.settings.Settings.java毫无关系。详情参考《activity-alias详解及应用》。

android系统应用之Settings_第1张图片

为了验证上面的理论如上图我分别在SettingsHomepageActivity.java和Settings.java的onCreate加了日志,在启动Settings的时候看看打印的日志是什么?

2、SettingsHomepageActivity

//packages/apps/Settings/src/com/android/settings/homepage/SettingsHomepageActivity.java
public class SettingsHomepageActivity extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 设置主界面布局文件:settings_homepage_container.xml
        setContentView(R.layout.settings_homepage_container);
        // 获取布局文件中homepage_container:主题内容
        final View root = findViewById(R.id.settings_homepage_container);
        root.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |  View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        //获取布局文件中search_action_bar:顶部搜索控件
        final Toolbar toolbar = findViewById(R.id.search_action_bar);
        FeatureFactory.getFactory(this).getSearchFeatureProvider().initSearchToolbar(this, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);
        //设置contextual_cards_content对应的fragment,不是低内存手机显示卡片布局视图
        if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
            showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
        }
        //设置main_content对应fragment为TopLevelSettings,即所有二级菜单选项
        showFragment(new TopLevelSettings(), R.id.main_content);
        ((FrameLayout) findViewById(R.id.main_content))
                .getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
    }
}


    
        
        
            
            
            
            
        
    
    
    
        
    

如上Activity和对应的布局文件代码,很容易理解,整个布局主要分两大块:

  • 首先顶部的搜索栏通过包含search_bar.xml文件(实现了Settings的搜索设置功能),通过工厂方式来创建并初始化SearchFeatureProvider,可通过它来搜索Settings所有的子菜单
  • 最后内容主体部分使用了NestedScrollView滑动控件,它包含了两个部分:顶部的卡片内容和下面主体二级菜单选项。其中二级菜单选项视图被设置成了TopLevelSettings

2.1、SearchFeatureProvider搜索子菜单

2.2、TopLevelSettings二级菜单布局

//packages/apps/Settings/src/com/android/settings/homepage/TopLevelSettings.java
@SearchIndexable(forTarget = MOBILE)
public class TopLevelSettings extends DashboardFragment implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
    public TopLevelSettings() {
        final Bundle args = new Bundle();
        args.putBoolean(NEED_SEARCH_ICON_IN_ACTION_BAR, false); //是否禁用搜索图标
        setArguments(args);
    }
    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.top_level_settings;  //对于视图布局文件
    }
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        use(SupportPreferenceController.class).setActivity(getActivity());
    }
    @Override
    public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
        new SubSettingLauncher(getActivity())
                .setDestination(pref.getFragment())
                .setArguments(pref.getExtras())
                .setSourceMetricsCategory(caller instanceof Instrumentable ? ((Instrumentable) caller).getMetricsCategory() : Instrumentable.METRICS_CATEGORY_UNKNOWN)
                .setTitleRes(-1)
                .launch();
        return true;
    }
    @Override
    protected boolean shouldForceRoundedIcon() {
        return getContext().getResources()
                .getBoolean(R.bool.config_force_rounded_icon_TopLevelSettings);
    }
}

从上面的代码可以知道TopLevelSettings是一个fragment,大部分功能在DashboardFragment父类具体实现,这里只提供了几个接口,从名字上可以看出getPreferenceScreenResId对应于视图布局文件,top_level_settings.xml如下:

android系统应用之Settings_第2张图片

你可能感兴趣的:(Android)