作为订制化的系统,我们有时候需要修改导航栏,在这里我们以修改导航栏图标为例,在导航栏添加语音助手的图标。
2017/6/19
首先在SystemUI中添加语音助手的资源文件,路径如下:
frameworks/base/packages/SystemUI/res/
修改导航栏的布局文件,路径:
frameworks/base/packages/SystemUI/res/layout/navigation_bar.xml
在返回键前面添加语音助手和录像按钮的布局(注意要修改两个地方一个横屏的一个竖屏的,如果只修改了上面那段在切换横屏时候会崩溃):
<com.android.systemui.statusbar.phone.NavigationBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="@drawable/system_bar_background"
>
<FrameLayout android:id="@+id/rot0"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
android:clipChildren="false"
android:clipToPadding="false"
android:id="@+id/nav_buttons"
android:animateLayoutChanges="true"
>
<View
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="0"
android:visibility="invisible"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_back"
systemui:keyCode="4"
android:layout_weight="0"
android:scaleType="center"
android:contentDescription="@string/accessibility_back"
/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_home"
systemui:keyCode="3"
systemui:keyRepeat="false"
android:layout_weight="0"
android:contentDescription="@string/accessibility_home"
/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
android:layout_width="1dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_recent"
android:contentDescription="@string/accessibility_recent"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/videoCapture"
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_video_off"
android:layout_weight="0"
android:contentDescription="@string/accessibility_recent"
android:padding="5dp"
android:scaleType="center"
/>
<View
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="0"
android:visibility="invisible" />
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/voiceAssist"
android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:src="@drawable/rc_statuebar_voiceassist_selector"
android:layout_weight="0"
android:contentDescription="@string/accessibility_recent"
android:padding="5dp"
android:scaleType="center"
/>
<View
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="0"
android:visibility="invisible" />
<FrameLayout
android:layout_width="@dimen/navigation_extra_key_width"
android:layout_height="match_parent"
android:layout_weight="0" >
<com.android.systemui.statusbar.policy.KeyButtonView
android:id="@+id/menu"
android:layout_width="@dimen/navigation_extra_key_width"
android:layout_height="match_parent"
android:contentDescription="@string/accessibility_menu"
android:src="@drawable/ic_sysbar_menu"
android:visibility="invisible"
systemui:keyCode="82" />
<com.android.systemui.statusbar.policy.KeyButtonView
android:id="@+id/ime_switcher"
android:layout_width="@dimen/navigation_extra_key_width"
android:layout_height="match_parent"
android:contentDescription="@string/accessibility_ime_switch_button"
android:scaleType="centerInside"
android:src="@drawable/ic_ime_switcher_default"
android:visibility="invisible" />
FrameLayout>
LinearLayout>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
android:id="@+id/lights_out"
android:visibility="gone"
>
<ImageView
android:layout_width="80dp"
android:layout_height="match_parent"
android:layout_marginStart="40dp"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<ImageView
android:layout_width="80dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
android:layout_weight="0"
/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<ImageView
android:layout_width="80dp"
android:layout_marginEnd="40dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
/>
LinearLayout>
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
android:layout_height="match_parent"
android:layout_width="match_parent"
systemui:minSize="@dimen/navigation_bar_deadzone_size"
systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
systemui:holdTime="@integer/navigation_bar_deadzone_hold"
systemui:decayTime="@integer/navigation_bar_deadzone_decay"
systemui:orientation="horizontal"
android:layout_gravity="top"
/>
FrameLayout>
<FrameLayout android:id="@+id/rot90"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="gone"
android:paddingTop="0dp"
>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:clipChildren="false"
android:clipToPadding="false"
android:id="@+id/nav_buttons"
android:animateLayoutChanges="true"
>
<FrameLayout
android:layout_weight="0"
android:layout_width="match_parent"
android:layout_height="40dp" >
<com.android.systemui.statusbar.policy.KeyButtonView
android:id="@+id/ime_switcher"
android:layout_width="match_parent"
android:layout_height="40dp"
android:contentDescription="@string/accessibility_ime_switch_button"
android:scaleType="centerInside"
android:src="@drawable/ic_ime_switcher_default"
android:visibility="invisible" />
<com.android.systemui.statusbar.policy.KeyButtonView
android:id="@+id/menu"
android:layout_width="match_parent"
android:layout_height="40dp"
android:contentDescription="@string/accessibility_menu"
android:src="@drawable/ic_sysbar_menu_land"
android:visibility="invisible"
systemui:keyCode="82" />
FrameLayout>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/videoCapture"
android:src="@drawable/ic_sysbar_video_off"
android:layout_height="80dp"
android:layout_width="match_parent"
android:padding="5dp"
android:scaleType="center"
android:layout_weight="0"
android:contentDescription="@string/accessibility_back"
/>
<View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/voiceAssist"
android:src="@drawable/rc_statuebar_voiceassist_selector"
android:layout_height="80dp"
android:layout_width="match_parent"
android:padding="5dp"
android:scaleType="center"
android:layout_weight="0"
android:contentDescription="@string/accessibility_back"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
android:layout_height="1dp"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_recent_land"
android:contentDescription="@string/accessibility_recent"
/>
<View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
android:layout_height="80dp"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_home_land"
systemui:keyCode="3"
systemui:keyRepeat="false"
android:layout_weight="0"
android:contentDescription="@string/accessibility_home"
/>
<View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
android:layout_height="80dp"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_back_land"
android:scaleType="center"
systemui:keyCode="4"
android:layout_weight="0"
android:contentDescription="@string/accessibility_back"
/>
<View
android:layout_height="40dp"
android:layout_width="match_parent"
android:layout_weight="0"
android:visibility="invisible"
/>
LinearLayout>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:id="@+id/lights_out"
android:visibility="gone"
>
<ImageView
android:layout_height="80dp"
android:layout_marginTop="40dp"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
/>
<View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<ImageView
android:layout_height="80dp"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
android:layout_weight="0"
/>
<View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:visibility="invisible"
/>
<ImageView
android:layout_height="80dp"
android:layout_marginBottom="40dp"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
/>
LinearLayout>
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
android:layout_height="match_parent"
android:layout_width="match_parent"
systemui:minSize="@dimen/navigation_bar_deadzone_size"
systemui:maxSize="@dimen/navigation_bar_deadzone_size_max"
systemui:holdTime="@integer/navigation_bar_deadzone_hold"
systemui:decayTime="@integer/navigation_bar_deadzone_decay"
systemui:orientation="vertical"
android:layout_gravity="top"
/>
FrameLayout>
com.android.systemui.statusbar.phone.NavigationBarView>
顺便把rc_statuebar_voiceassist_selector也贴出来,这个selector用在当用户长按按钮的时候,按钮disable掉:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:state_pressed="false"
android:drawable="@drawable/ic_sysbar_voice_off" />
<item android:state_enabled="true"
android:state_pressed="true"
android:drawable="@drawable/ic_sysbar_voice_on" />
<item android:state_enabled="true"
android:state_pressed="false"
android:drawable="@drawable/ic_sysbar_voice_on"/>
selector>
mNavigationBarView.getVoiceAssistButton().setOnLongClickListener(mLongPressVoiceListener);//larsonzhong@163.com
mNavigationBarView.getVoiceAssistButton().setOnClickListener(mYuyinClickListener);//larsonzhong@163.com
mNavigationBarView.getVideoCaptureButton().setOnClickListener(mDvrClickListener);//larsonzhong@163.com
对应的getVoiceAssistButton()要在
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
中实现:
//[email protected]
public View getVoiceAssistButton(){
return mCurrentView.findViewById(R.id.voiceAssist);
}
//[email protected]
public View getVideoCaptureButton(){
return mCurrentView.findViewById(R.id.videoCapture);
}
///////////////////*语音按钮长按*////////////
private View.OnLongClickListener mLongPressVoiceListener =//[email protected]
new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (!isYuyinSwitchOn()){
PhoneStatusBar.this.setYuyinSwitch(true);
showToast("打开语音助手");
}else{
PhoneStatusBar.this.setYuyinSwitch(false);
showToast("关闭语音助手");
}
updateYuyinStatue();
return true;
}
};
private void updateYuyinStatue() {
ImageView localImageView;
if (mNavigationBarView.getVoiceAssistButton() != null){
localImageView = (ImageView)mNavigationBarView.getVoiceAssistButton();
localImageView.setEnabled(isYuyinSwitchOn());
}
}
private void showToast(String resString){//[email protected]
android.widget.Toast.makeText(mContext, resString, android.widget.Toast.LENGTH_SHORT).show();
}
private void setYuyinSwitch(boolean paramBoolean){//[email protected]
android.content.ContentResolver localContentResolver = this.mContext.getContentResolver();
Settings.System.putInt(localContentResolver, "yuyin_switch", paramBoolean?1:0);
}
private boolean isYuyinSwitchOn(){//[email protected]
return Settings.System.getInt(this.mContext.getContentResolver(), "yuyin_switch", 1) == 1;
}
////***********************[email protected]*************//////////////////////
/************ 语音按钮点击 *********/
private View.OnClickListener mYuyinClickListener = new View.OnClickListener()// [email protected]
{
public void onClick(View paramAnonymousView) {
// 语音助手关闭,则点击无效
if (!isSupportYuyinSwitch())
return;
if (!isYuyinSwitchOn()) {
setYuyinSwitch(true);
updateYuyinStatue();
}
sendYuyinDownBroadcast();
}
};
private final String BROADCAST_START_VOICE_ASSIST = "com.larson.systemui.KEYDOWN_VOICE_ASSIST";
private void sendYuyinDownBroadcast() {
mContext.sendBroadcast(new Intent(BROADCAST_START_VOICE_ASSIST));
}
//// ***********************DVR按钮*************//////////////////////
private final String BROADCAST_START_DVR = "com.larson.systemui.KEYDOWN_DVR";
private View.OnClickListener mDvrClickListener = new View.OnClickListener() {
public void onClick(View paramAnonymousView) {
mContext.sendBroadcast(new Intent(BROADCAST_START_DVR));
}
};
如果你的应用有使用横屏模式,务必把layout下的land下的布局也同步修改了。
SystemUI.apk生成以后,直接重新刷系统是看不到改变的,我们需要把重新生成的SystemUI.apk推送到手机中,具体步骤如下:
我们先确定SystemUI所在的目录,为了验证我上一句话是对的,我先把系统里的SystemUI.apk拉出来,然后看下布局文件是否改变,如果没有改变说明重新刷系统无效。
为了让系统可读写,我们首先执行
#获取系统权限,便于执行remount
adb root
#让系统可读写
adb remount
#把SystemUI.apk拖出来
adb pull adb pull /system/priv-app/SystemUI/SystemUI.apk F:\
#进入到修改后的SystemUI.apk所在目录
adb push SystemUI.apk /system/priv-app/SystemUI/SystemUI.apk
#重起系统查看效果
adb reboot
2017/4/19
导入eclipse只是在eclipse方便写代码而已,不要在意报错,因为最终还是要在源码树上调试。下面这几步只是为了方便开发,因为记事本写导包啊啥的挺麻烦的。
首先从安卓源码树中拿到SystemUI的原代码,位置在 \源码目录\frameworks\base\packages\SystemUI,我们把这个文件夹拷贝出来。
把framework的jar包导入,上面的错误大部分是因为缺少依赖导致。framework.jar在编译好的系统输出目录下,out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes.jar
拿到这个文件,我们改名为framework.jar,加入到SystemUI工程目录的buildPath中。这个时候我们发现少了很多错误。
按照上面的方式添加以下依赖:
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
out/target/common/obj/JAVA_LIBRARIES/service_intermediates/classes.jar
out/target/common/obj/JAVA_LIBRARIES/core-tests_intermediates/javalib.jar
发现还有错误;
将/frameworks/base/packages/Keyguard 里面src下的文件都拷贝到工程中
eclipse要选Java 1.7版本。
发现还有报错
//import com.android.systemui.EventLogTags;
代码里用到EventLog的会报错,把这个屏蔽掉
还有资源文件报错
不管了,反正我们到时候是要把代码复制到系统源码里面的,不影响写代码就行。