RK3288Android5.1系統在設定中新增隱藏和顯示導航欄功能
1.需求
應客戶需求,在android系統設定中新增一個設定選項,該選項中新增一個開關功能,用於顯示和隱藏系統底部導航欄。
2.分析
首先當然是有系統原始碼了,RK3288,5.1系統原始碼一份。
然後就是修改系統設定app,即Settings.apk的原始碼。
再然後修改系統SystemUI.apk的原始碼。
最後,通過Settings.apk的開關按鈕來觸發,傳送廣播通知給SystemUI.apk來實現導航欄的顯示和隱藏邏輯。
3.實現
環境:
原始碼放在了公司的伺服器上,本猿用的是ubuntu系統。
第一步:連線到伺服器上操作
a. 開啟終端:Ctrl+shift+T
b. 連線伺服器:ssh [email protected]_address
第二步:進入RK3288原始碼目錄
a. Settings.apk原始碼路徑: RK3288-5.1/packages/apps/Settings
b. SystemUI.apk原始碼路徑: RK3288-5.1/frameworks/base/packages/SystemUI
第三步:修改Settings.apk原始碼
a.修改RK3288-5.1/packages/apps/Settings/res/xml/dashboard_categories.xml
新增程式碼:
<!-- Navigation set add by xtm --> <dashboard-tile android:id="@+id/setNavigation_settings" android:title="導航欄設定" android:fragment="com.android.settings.SetNavigationSettings" android:icon="@drawable/ic_settings_about" />
這幾行程式碼用在點開設定第一個出現在介面中的條目,這裡借用的“關於裝置”的圖示,可見每個條目對應一個fragment。
在包com.android.settings下新建一個類:
package com.android.settings; import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceFragment; import android.util.Log; import android.widget.Toast; import android.content.Context; import android.content.Intent; /** * * @author TianMing.Xiong * */ public class SetNavigationSettings extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener{ private Context mContext; public static final String HIDE_NAVIGATION_BAR = "android.intent.action.HIDE_NAVIGATION_BAR"; public static final String SHOW_NAVIGATION_BAR = "android.intent.action.SHOW_NAVIGATION_BAR"; @Override public void onCreate(Bundle icicle) { // TODO Auto-generated method stub super.onCreate(icicle); addPreferencesFromResource(R.xml.navigation_settings); mContext = getActivity(); // 獲取級別描述(組) Preference set_navigation = getPreferenceManager().findPreference("set_navigation"); CharSequence summary = set_navigation.getSummary(); CharSequence title = set_navigation.getTitle(); Log.e("TAG","summary:"+summary+",title:"+title); // 監聽開關按鈕 Preference navigation_is_show_and_hide = getPreferenceManager().findPreference("navigation_is_show_and_hide"); // 用於監聽哪個Preference的回撥,用key標識 navigation_is_show_and_hide.setOnPreferenceChangeListener(this); } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { // TODO Auto-generated method stub String key = preference.getKey(); Log.e("TAG","key:"+key+",value:"+newValue); if(newValue instanceof Boolean){ Boolean flag = Boolean.valueOf(((Boolean) newValue).booleanValue()); if(flag){ // Toast.makeText(getActivity(), "open", Toast.LENGTH_SHORT).show(); mContext.sendBroadcast(new Intent(HIDE_NAVIGATION_BAR)); }else { // Toast.makeText(getActivity(), "close", Toast.LENGTH_SHORT).show(); mContext.sendBroadcast(new Intent(SHOW_NAVIGATION_BAR)); } } return true; } }
此類需要addPreferencesFromResource(R.xml.navigation_settings),在res/xml資料夾下新建navigation_settings.xml
內容:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 設定的類別 -->
<PreferenceCategory
android:key="set_navigation"
android:summary="set navigation"
android:title="這時標題">
<CheckBoxPreference
android:key="navigation_is_show_and_hide"
android:summary="這時概要"
android:defaultValue="false"
android:title="這也是標題"/>
</PreferenceCategory>
</PreferenceScreen>
至此,Settings.apk原始碼修改完畢!
第四步:修改SystemUI.apk原始碼
找到包com.android.systemui.statusbar.phone下的PhoneStatusBar.java
新增程式碼:
import android.content.SharedPreferences;// add by xtm
public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,CircleMenuView.BtnClickCallBack {
/*----------------------------------------------------add by xtm------------------------------------------------------*/
public static final String HIDE_NAVIGATION_BAR = "android.intent.action.HIDE_NAVIGATION_BAR";
public static final String SHOW_NAVIGATION_BAR = "android.intent.action.SHOW_NAVIGATION_BAR";
private static final String NAVIGATION_CONF = "navigation_conf";
private static final String NAVIGATION_KEY = "navigation_key";
private SharedPreferences navigation_sp;
private boolean isShowNavigation = true;
/*----------------------------------------------------------------------------------------------------------*/
在該類的start()方法中的addNavigationBar();這行程式碼下新增:
addNavigationBar();
/*----------------------------------add by xtm--------------------------------------------------*/
navigation_sp = mContext.getSharedPreferences(NAVIGATION_CONF, Context.MODE_PRIVATE);
isShowNavigation = navigation_sp.getBoolean(NAVIGATION_KEY, true);
if (isShowNavigation) {
displayNavigation();
}else {
hideNavigation();
}
/*------------------------------------------------------------------------------------*/
在本類中程式碼private BroadcastReceiver winreceiver=new BroadcastReceiver() {....}上方新增:
/*----------------------------------------------------add by xtm------------------------------------------------------*/
private BroadcastReceiver navigationreceiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if(action.equals(SHOW_NAVIGATION_BAR)){
displayNavigation();
navigation_sp.edit().putBoolean(NAVIGATION_KEY,true).apply();
}else if(action.equals(HIDE_NAVIGATION_BAR)) {
hideNavigation();
navigation_sp.edit().putBoolean(NAVIGATION_KEY,false).apply();
}
}
};
public void displayNavigation(){
addNavigationBarInnerLocked();
}
public void hideNavigation(){
removeNavigationBar();
}
private void addNavigationBarInnerLocked(){
if(mNavigationBarView == null){
mNavigationBarView = (NavigationBarView) View.inflate(mContext, R.layout.navigation_bar, null);
mNavigationBarView.setDisabledFlags(mDisabled);
mNavigationBarView.setBar(this);
mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
checkUserAutohide(v, event); return false;
}
});
if (mNavigationBarView == null) return;
prepareNavigationBarView();
try {
mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
} catch (Exception e) {
}
}
}
private void removeNavigationBar() {
if (mNavigationBarView == null) return;
mWindowManager.removeView(mNavigationBarView);
mNavigationBarView = null;
}
/*----------------------------------------------------------------------------------------------------------*/
在函式protected PhoneStatusBarView makeStatusBarView()中新增程式碼:
/*----------------------------------------------------add by xtm------------------------------------------------------*/
IntentFilter navigationintentfilter=new IntentFilter();
navigationintentfilter.addAction(HIDE_NAVIGATION_BAR);
navigationintentfilter.addAction(SHOW_NAVIGATION_BAR);
context.registerReceiver(navigationreceiver, navigationintentfilter);
/*----------------------------------------------------------------------------------------------------------*/
至此,SystemUI.apk原始碼修改完畢!
第五步:編譯整個系統
連線好伺服器的的終端上輸入:
1. source build/envsetup.sh
2. lunch
選3 -----(編譯java環境)
3. make -----(全部編譯)
第六步:找到編譯好的apk檔案push到裝置上,重啟看效果:
Settings.apk檔案路徑:
RK3288-5.1/out/target/product/rk3288/system/priv-app/Settings/
SystemUI.apk檔案路徑:
RK3288-5.1/out/target/product/rk3288/system/priv-app/SystemUI/
拷貝出來push進裝置:
命令:
adb root
adb remount
adb push ~/SystemUI.apk /system/priv-app/SystemUI/ adb push ~/Settings.apk /system/priv-app/Settings/
adb reboot
4.總結
參考: