1. 程式人生 > >RK3288Android5.1系統在設定中新增隱藏和顯示導航欄功能

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.總結

 

參考: