美文网首页
Settings.apk 6.0开发记录

Settings.apk 6.0开发记录

作者: 风骚无俩 | 来源:发表于2017-04-01 17:47 被阅读0次

    其apk在设备上的位置:/system/priv-app/Settings。

    开发前准备

    • 除了需要导入Settings的源码,还需导入SettingsLib模块作为依赖
    • 在app目录下新建systemlib目录作为系统库,需添加 如下jar包作为Provider,具体参考模块依赖
      • android_stubs_current_intermediates.jar
      • bouncycastle_intermediates.jar
      • conscrypt_intermediates.jar
      • core-libart_intermediates.jar
      • ext_intermediates.jar
      • framework_intermediates.jar
      • frameworks-core-util-lib_intermediates.jar
      • ims-common_intermediates.jar
      • jsr305_intermediates.jar
      • setup-wizard-lib_intermediates.jar
      • setup-wizard-navbar_intermediates.jar
      • telephony-common_intermediates.jar
    • 整理资源文件,补齐缺失的资源 直到编译通过

    一级选项添加流程 以有线网络为例

    1.Settings中一级选项的显示是在dashboard_categories.xml中添加的,路径为main\res\xml\,Favorites中有收藏此文件。打开dashboard_categories.xml,选项是按组分类的,如无线和网络、设备、系统,我们自定义的无线网络放在无线和网络组中。先创建EthernetFragment,通过title(Wireless&network)找到无线和网络的dashboard-category。
    在上述组里添加如下代码

    <dashboard-tile
     //此id要添加到SettingsActivity的SETTINGS_FOR_RESTRICTED数组中,如果id不存在此数组,加载时会移除
    android:id="@+id/ethernet_settings"
    android:title="有线网络" 
    //此Fragment为之前创建的路径,名称要添加到SettingsActivity的ENTRY_FRAGMENTS数组中
    android:fragment="com.android.settings.shine.EthernetFragment"
    android:icon="@drawable/ic_settings_data_usage"/>
    

    2.在Settings.java中添加如下代码

     public static class EthernetSettingsActivity extends SettingsActivity {  }
    

    3.在manifest中注册EthernetSettingsActivity

     <activity
        android:name=".Settings$EthernetSettingsActivity"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:label="有线网络设置"
        android:taskAffinity="">
            <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <action android:name="android.settings.ETHERNET_SETTINGS"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.VOICE_LAUNCH"/>
            <category android:name="com.android.settings.SHORTCUT"/>
            </intent-filter>
        //当点击添加的有线网络选项时会跳转到此页面
            <meta-data
                android:name="com.android.settings.FRAGMENT_CLASS"
                //真正显示的内容,路径与dashboard_categories.xml中注册的一样
                android:value="com.android.settings.shine.EthernetFragment"/>
            <meta-data
        android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
        //id与dashboard_categories.xml中注册的一样
        android:resource="@id/ethernet_settings"/>
        </activity>
    

    4.添加有线网络选项的id到SettingsActivity的SETTINGS_FOR_RESTRICTED数组中

    private int[] SETTINGS_FOR_RESTRICTED = {
        R.id.wireless_section,//无线
        R.id.wifi_settings,//wifi
        R.id.bluetooth_settings,//蓝牙
        R.id.data_usage_settings,
        R.id.ethernet_settings,//有线网络
        R.id.server_settings,....}
    

    5.将EthernetFragment类名添加到SettingsActivity的ENTRY_FRAGMENTS数组

    private static final String[] ENTRY_FRAGMENTS = {
        WirelessSettings.class.getName(),
        EthernetFragment.class.getName(),//有线网络
        ServerSettingFragment.class.getName(),//服务器设置
        OnOffSettingFragment.class.getName(),//开关机设置
        ...}
    

    添加退出选项

    退出不需要进入子页面,则不需要注册Activity和添加Fragment。同样打开dashboardcategories.xml,我们把退出选项添加在系统组里,知道title为System的dashboard-category,添加如下代码

     <dashboard-tile
        //此id可作为身份判断
        android:id="@+id/exit_settings"
        android:title="退出"
        android:icon="@drawable/ic_settings_about"
        />
    

    直接在DashboardTileView的OnClick方法中添加退出点击处理

    public void onClick(View v) {
        if (mTile.fragment != null) {
            Utils.startWithFragment(getContext(), mTile.fragment, mTile.fragmentArguments, null, 0,
                    mTile.titleRes, mTile.getTitle(getResources()));
        } else if (mTile.intent != null) {
            int numUserHandles = mTile.userHandle.size();
            if (numUserHandles > 1) {
                ProfileSelectDialog.show(((Activity) getContext()).getFragmentManager(), mTile);
            } else if (numUserHandles == 1) {
                getContext().startActivityAsUser(mTile.intent, mTile.userHandle.get(0));
            } else {
                getContext().startActivity(mTile.intent);
            }
        }else if (mTile.id == R.id.exit_settings) {
            //点击退出按钮退出应用
            ((SettingsActivity)getContext()).finish();
        }
    }
    

    移除选项,比如位置选项

    在SettingsActivity中的updateTilesList()方法里添加如下代码

    private void updateTilesList(List<DashboardCategory> target) {
        ....省略一批代码
     // Ids are integers, so downcasting is ok
        int id = (int) category.id;
        int n = category.getTilesCount() - 1;
        while (n >= 0) {
        ....省略一批代码
            else if (id == R.id.location_settings) {
             removeTile=true;
           }
        ....省略一批代码
        n--;
        }
    

    6.0系统默认永不休眠,要显示这个选项,打开app\src\main\res\values\custom_config.xml文件,修改代码如下

     <bool name="config_show_screen_off_never_timeout" translatable="false">true</bool>
    

    系统默认的高亮色比较淡,不容易区分条目是否被选中,打开\src\main\res\values\themes.xml文件,在如下样式中添加自定义背景色

    <style name="Theme.Settings" parent="Theme.SettingsBase">
    ...省略其他样式设置
    //修改高亮色
    <item name="android:colorControlHighlight">@color/memory_user_light</item>
    </style>
    

    屏幕旋转的处理,显示选项和后台都能控制设备的旋转,前提是Launcher允许桌面旋转(具体操作查看Launcher.apk的修改记录),否则只会应用旋转,桌面不会同步旋转;代码如下,需在子线程中执行:

    IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
    //保存到全局
    Settings.System.putInt(getContentResolver(),Settings.System.USER_ROTATION, value);
    //保存到数据库,与后台同步
    ShineDataBaseHelper.getInstance(this).save(Common.DESKTOP_ORIENTATION, data);
    try {
        wm.freezeRotation(value);
        WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
        wallpaperManager.setBitmap(wallpaperManager.getBitmap());
        Log.d(TAG, "设置旋转完成");
    } catch (RemoteException | IOException e) {
        Log.d(TAG, "设置旋转异常");
        e.printStackTrace();
    }
    

    提示音和通知选项,在src\main\java\com\android\settings\notification\NotificationSettings.java文件中移除了闹钟和铃音设置,只留下媒体音量,其功能实现在src\main\java\com\android\settings\notification\VolumeSeekBarPreference.java文件中。
    主要改动有修改了SeekBarPreference的源码,否则SeekBar控件找不到报空,打开src\main\res\layout\preference_volume_slider.xml,修改id

    <SeekBar 
        //@*android:id/seekbar 源代码
        android:id="@+id/seekbar"
        android:layout_marginStart="24dp"
        android:layout_gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    

    拷贝SeekBarPreference源码到项目,使VolumeSeekBarPreference继承之,本项目路径为E:\workspace_a64\Settings\app\src\main\java\com\android\settings\shine\SeekBarPreference.java。修改SeekBarPreference的onBindView方法:

    @Override
    protected void onBindView(View view) {
        super.onBindView(view);
        SeekBar seekBar = (SeekBar) view.findViewById(R.id.seekbar);
    //  SeekBar seekBar = (SeekBar) view.findViewById( com.android.internal.R.id.seekbar);
        ...
    }
    

    打开VolumeSeekBarPreference.java文件,添加遥控器调节音量的响应,具体修改参考源文件

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (event.getAction() != KeyEvent.ACTION_UP) {
            if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT
                    || keyCode == KeyEvent.KEYCODE_EQUALS) {
                mSeekBar.setProgress(mSeekBar.getProgress() + 1);
                mVolumizer.onProgressChanged(mSeekBar,mSeekBar.getProgress(),true);
                return true;
            }
            if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
                mSeekBar.setProgress(mSeekBar.getProgress() - 1);
                mVolumizer.onProgressChanged(mSeekBar,mSeekBar.getProgress(),true);
                return true;
            }
        }
        return false;
    }
    

    显示输入法,在系统完成Boot,调用以下方法,在SettingProvider中没有找到默认设置

    Settings.Secure.putInt(getContentResolver(), "show_ime_with_hard_keyboard", 1);
    

    修改PhoneWindowManager.java源码,设定对F12按键响应,使遥控器对设置应用的直接调用。找到interceptKeyBeforeDispatching方法添加如下代码:

    @Override
    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
    ...
    ...
     if (keyCode == KeyEvent.KEYCODE_HOME) {
    ...响应首页键
    ...其他按键
    }else if(keyCode == KeyEvent.KEYCODE_F12){
        if(down){
            //应用的首页需在清单文件添加类别android.intent.category.SETTINGS
            Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, "android.intent.category.SETTINGS");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            try {
                mContext.startActivityAsUser(intent, UserHandle.CURRENT);
            } catch (ActivityNotFoundException ex) {
               ...
            }
        }
            return -1;   
        }
    ....

    相关文章

      网友评论

          本文标题:Settings.apk 6.0开发记录

          本文链接:https://www.haomeiwen.com/subject/rptwottx.html