Android OS Forum banner

[How To] Step by Step Guide To Add Menu and Search Soft Keys

41K views 34 replies 21 participants last post by  rdubyah 
#1 · (Edited by Moderator)
How To Add Menu and Search Soft Keys

NOTE: This guide is outdated and likely will not work on anything past Jelly Bean 4.1. I don't have a Galaxy Nexus anymore so I am not active in its development and unfortunately do not have plans update this guide.

Here is a guide that will walk you through the modifications needed to add permanent menu and search softkeys to Jelly Bean (and ICS).

As always, make these modifications at your own risk. I take no responsibility for any issues you cause or damage you do to your phone.

Before I start, this guide assumes you can already decompile and compile apks. There are many guides and tools on here, xda, and the rest of the internet to get you setup for this. I personally use APKManager with the newest SDK and ApkTool components.

I recommend having a good text editor and file comparison program to make things easier. I use NotePad++ for xml/code editing, and Beyond Compare for folder/file/text/etc comparison. Beyond Compare isn't free, but I've heard WinMerge is a good free comparison (never used it though).

I also recommend downloading one of the soft key mods I've already made so you can compare the changes to files as you work throught the guide.

All edits for this mod occur in SystemUI.apk. The following files are changed:
\res\drawable-xhdpi\ic_sysbar_menu.png
\res\drawable-xhdpi\ic_sysbar_menu_land.png
\res\drawable-xhdpi\ic_sysbar_search.png (new)
\res\drawable-xhdpi\ic_sysbar_search_land.png (new)
\res\layout\navigation_bar.xml
\res\values\ids.xml
\res\values\public.xml
\res\values\strings.xml
\smali\com\android\systemui\statusbar\phone\NavigationBarView.smali


1. Decompile SystemUI.apk

2. Add the new Soft Key icon files
I have attached "stock" softkey images for menu and search, however you can use whatever you'd like, just make sure the filenames are the same. Put these in \res\drawable-xhdpi (overwriting the existing menu pngs)
View attachment menu_search_pngs.zip

3. Add the resource ID for the search key.
The search key doesn't yet exist so you need to add it to the apk's resources. This is done by adding an ID in \res\values\public.xml. Open public.xml and scroll to the end of the list of lines that start with <public type="id" . Add the following line after the last id item:

Code:
<br />
<public type="id" name="search" id="______" /><br />
Replace the blank area with the next incremental hex value. This means take the value above it and just increase the last digit by one (0-9 a-f). If the last digit is f, make it 0 and increase the digit to the left by one. MAKE SURE THIS VALUE IS NOT USED ANYWHERE ELSE IN THE FILE. IT MUST BE UNIQUE. If it is used, keep incrementing it until it isn't. Remember this value since you will need it later.

Below is an example of what the last couples lines of id's look like on mine:
Code:
<br />
<public type="id" name="notification_inspect_item" id="0x7f0c009c" /><br />
<public type="id" name="recent_remove_item" id="0x7f0c009d" /><br />
<public type="id" name="recent_inspect_item" id="0x7f0c009e" /><br />
<public type="id" name="search" id="0x7f0c009f" /><br />
4. Add the following line to \res\values\ids.xml

Code:
<br />
<item type="id" name="search">false</item><br />
5. Add the following line to \res\values\strings.xml

Code:
<br />
<string name="accessibility_search">Search</string><br />
6. Time to edit some code.
Open \smali\com\android\systemui\statusbar\phone\NavigationBarView.smali

7. Add the following method.
I suggest adding it after the "getRecentsButton()" method

Code:
<br />
.method public getSearchButton()Landroid/view/View;<br />
	.locals 2<br />
<br />
	.prologue<br />
	.line 73<br />
	iget-object v0, p0, Lcom/android/systemui/statusbar/phone/NavigationBarView;->mCurrentView:Landroid/view/View;<br />
<br />
	const v1, 0x7f0c009f<br />
<br />
	invoke-virtual {v0, v1}, Landroid/view/View;->findViewById(I)Landroid/view/View;<br />
<br />
	move-result-object v0<br />
<br />
	return-object v0<br />
.end method<br />
After you add it, you must update the line "const v1, 0x7f0c009f" to use the hex value you added in step 3. So, replace 0x7f0c009f with what you filled in the blank in step 3.

This is the code that actually adds the Search Button

8. Find this method/line: .method public setDisabledFlags(IZ)V

The line right below it should be something like ".locals 7" or some other number. Increase the number by 2 because we're creating two new variables.

A little further down you should see a line that starts with "invoke-virtual" and has "getHomeButton()" near the end., and a line right below that starts with move-result-object. Pay attention to the "v#" value at the end of this line. In my case it is "v6".

Add the following code after this line, but set the "v#" values at the end of the move-result lines to +1 and +2 the number above. Since mine was v6, below they are v7 and v8

Code:
<br />
	invoke-virtual {p0}, Lcom/android/systemui/statusbar/phone/NavigationBarView;->getSearchButton()Landroid/view/View;<br />
<br />
	move-result-object v7<br />
<br />
	invoke-virtual {p0}, Lcom/android/systemui/statusbar/phone/NavigationBarView;->getMenuButton()Landroid/view/View;<br />
<br />
	move-result-object v8<br />
A few lines later you will see:
Code:
<br />
invoke-virtual {v6, v3}, Landroid/view/View;->setVisibility(I)V<br />
where the first v# is the same as the original number you saw above (again, v6 in this case). Add this same line twice more, changing the v#'s to the #'s you added above. My final block of code that includes both the above and these two lines looks like this:

Code:
<br />
	invoke-virtual {p0}, Lcom/android/systemui/statusbar/phone/NavigationBarView;->getHomeButton()Landroid/view/View;<br />
<br />
	move-result-object v6<br />
<br />
	invoke-virtual {p0}, Lcom/android/systemui/statusbar/phone/NavigationBarView;->getSearchButton()Landroid/view/View;<br />
<br />
	move-result-object v7<br />
<br />
	invoke-virtual {p0}, Lcom/android/systemui/statusbar/phone/NavigationBarView;->getMenuButton()Landroid/view/View;<br />
<br />
	move-result-object v8<br />
<br />
	if-eqz v1, :cond_6<br />
<br />
	move v3, v5<br />
<br />
	:goto_6<br />
	invoke-virtual {v6, v3}, Landroid/view/View;->setVisibility(I)V<br />
<br />
	invoke-virtual {v7, v3}, Landroid/view/View;->setVisibility(I)V<br />
<br />
	invoke-virtual {v8, v3}, Landroid/view/View;->setVisibility(I)V<br />
This section you just added makes sure the buttons are hidden on the lock screen or other places when they need to be.

9. Find these methods/lines: .method public setMenuVisibility(Z)V and .method public setMenuVisibility(ZZ)V

You want to delete most of the content of these methods, leaving just the .locals, .paramaters, and return lines. Here's what it should looks like:

Code:
<br />
.method public setMenuVisibility(Z)V<br />
	.locals 1<br />
	.parameter "show"<br />
<br />
	return-void<br />
.end method<br />
<br />
.method public setMenuVisibility(ZZ)V<br />
	.locals 2<br />
	.parameter "show"<br />
	.parameter "force"<br />
<br />
	return-void<br />
.end method<br />
Doing this keeps the menu key always visible.

9. Add the Soft Keys to the Nav Bar.
Open res/layout/navigation_bar.xml.

You will see four main LinearLayout sections. The first specifies the key layout in portrait from left to right, and the second specifies the same thing but in lights out mode (camera, gallery, etc). The third specifies the key layout in landscape from top to bottom, and the fourth again the same lights out layout.

The lines that start with "<View..." are the spacers between the keys, and the lines that start with "<com.android.systemui...." are the actual keys (with the id and keycode properties specifying which key they are).

The full modified XML for Back - Recent - Home - Search - Menu has been attached. Copy (overwrite) this file into your project. You can compare it to your current one if you'd like, but I don't think many mods are making changes to this file.
View attachment navigation_bar.xml

Here is the XML of the first section:
Code:
<br />
<LinearLayout android:orientation="horizontal" android:id="@id/nav_buttons" android:clipChildren="false" android:clipToPadding="false" android:layout_width="fill_parent" android:layout_height="fill_parent" android:animateLayoutChanges="true"><br />
	<View android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" /><br />
	<com.android.systemui.statusbar.policy.KeyButtonView android:id="@id/back" android:layout_width="70.0dip" android:layout_height="fill_parent" android:src="@drawable/ic_sysbar_back" android:layout_weight="0.0" android:contentDescription="@string/accessibility_back" systemui:keyCode="4" systemui:glowBackground="@drawable/ic_sysbar_highlight" /><br />
	<View android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" /><br />
	<com.android.systemui.statusbar.policy.KeyButtonView android:id="@id/recent_apps" android:layout_width="70.0dip" android:layout_height="fill_parent" android:src="@drawable/ic_sysbar_recent" android:layout_weight="0.0" android:contentDescription="@string/accessibility_recent" systemui:glowBackground="@drawable/ic_sysbar_highlight" /><br />
	<View android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" /><br />
	<com.android.systemui.statusbar.policy.KeyButtonView android:id="@id/home" android:layout_width="70.0dip" android:layout_height="fill_parent" android:src="@drawable/ic_sysbar_home" android:layout_weight="0.0" android:contentDescription="@string/accessibility_home" systemui:keyCode="3" systemui:keyRepeat="false" systemui:glowBackground="@drawable/ic_sysbar_highlight" /><br />
	<View android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" /><br />
	<com.android.systemui.statusbar.policy.KeyButtonView android:id="@id/search" android:layout_width="70.0dip" android:layout_height="fill_parent" android:src="@drawable/ic_sysbar_search" android:layout_weight="0.0" android:contentDescription="@string/accessibility_search" systemui:keyCode="84" systemui:glowBackground="@drawable/ic_sysbar_highlight" /><br />
	<View android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" /><br />
	<com.android.systemui.statusbar.policy.KeyButtonView android:id="@id/menu" android:layout_width="70.0dip" android:layout_height="fill_parent" android:src="@drawable/ic_sysbar_menu" android:layout_weight="0.0" android:contentDescription="@string/accessibility_menu" systemui:keyCode="82" systemui:glowBackground="@drawable/ic_sysbar_highlight" /><br />
	<View android:visibility="invisible" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1.0" /><br />
</LinearLayout><br />
a. To reorder the keys, all you need to do is switch the order of the xml lines. So, if you wanted to switch the above to Back - Menu - Home - Search - Recent, you would put the line with =@id/menu where the line with =@id/recent_apps is, and vice versa.

b. Do this same thing in the third section so your landscape layout is also changed.

c. If you want to remove a key, do not just delete the line! Instead, set the width and height properties to "0.0dip". I suggest moving it to the bottom of the list as well, just to get it out of the way.
Example:
Code:
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@id/search" android:layout_width="0.0dip" android:layout_height="0.0dip" android:src="@drawable/ic_sysbar_search" android:layout_weight="0.0" android:contentDescription="@string/accessibility_search" systemui:keyCode="84" systemui:glowBackground="@drawable/ic_sysbar_highlight" /><br />
d. If you delete a key make sure you also update the lights-out sections. However with these you can just delete the line instead of making it 0 width/height. Also update the spacers if you want to keep the keys centered. You always want one spacer on each end and one between each key. These can also be deleted versus setting to 0 h/w, but either works.

e. If you want long-press on that soft key (home and search), add the property systemui:keyRepeat="true" to that button. Set it to false if you want to disable long-press.

10. Compile the apk and install it on your phone

11. Enjoy

Also, if anyone has any suggestions or improvements for this guide, or if something is wrong, please let me know! It was written based on my own research (aka looking at other people's mods
) and experience making the mod for myself.
 

Attachments

See less See more
3
#3 ·
Nice write up man!

Those with experience shouldn't have any problems, but I think the newer guys/gals are going to struggle a bit.

I didn't realize how much work this mod was until now that I'm seeing it all written down...lol

Sent from my Galaxy Nexus using RootzWiki
 
  • Like
Reactions: willyjay
#4 ·
Sweet, thanks for taking the time to post all this info for everyone.

Subscribed...

Sent from my Galaxy Nexus using Xparent SkyBlue Tapatalk 2
 
#10 ·
Thanks for this awsome guide. I successfully added the menu button to my navbar.
One little question, the buttons are not centered. Look at my screenshot to see what i mean. How can i center it?

Do you also know how to make the navbar buttons brighter? So that i better see it when the sun is shining?
The brightness is now on ca. 60% and i want it 100% :)

http://dl.dropbox.com/u/45805601/Screenshot_2012-07-18-20-18-29.png

Thanks for all your work, much apreciated! You are the man!

Kindly regards, lichti
 
#11 · (Edited by Moderator)
I'm guessing that in the nav bar xml you removed the search key (by setting height/width to 0) but left the extra spacer. I realize I didn't mention anything about that in the guide. To keep the buttons centered, you always want one spacer on each end and one between each key (assuming their widths remain set to "fill_parent"). So just remove the extra one by deleting the line or also setting its heigh/width to 0. Doesn't matter if its the one above or below the button.

As for the brightness, I've never modified that so I don't know off hand how to do it. Its probably a hex value somewhere in the xml.
 
#13 ·
This tutorial is awesome!!!

I followed the instruction and built it step by step, but some errors were reported.
When I rebuild SystemUI.apk , apktool shows the message:

Code:
[color=#000000]C:\Users\21\Desktop\apktool>apktool b SystemUI[/color]<br />
[color=#000000]I: Checking whether sources has changed...[/color]<br />
[color=#000000]I: Smaling...[/color]<br />
[color=#000000]I: Checking whether resources has changed...[/color]<br />
[color=#000000]I: Building resources...[/color]<br />
[color=#000000]C:\Users\21\Desktop\apktool\SystemUI\res\values\public.xml:601: error: Pub[/color][color=#000000]lic resource id/recent_remove_item has conflicting public identifiers (0x7f0e008[/color][color=#000000]f vs 0x7f0e0092).[/color]<br />
[color=#000000]C:\Users\21\Desktop\apktool\SystemUI\res\values\public.xml:598: Originally[/color][color=#000000]defined here.[/color]<br />
[color=#000000]C:\Users\21\Desktop\apktool\SystemUI\res\values\public.xml:602: error: Pub[/color][color=#000000]lic resource id/recent_inspect_item has conflicting public identifiers (0x7f0e00[/color][color=#000000]90 vs 0x7f0e0093).[/color]<br />
[color=#000000]C:\Users\21\Desktop\apktool\SystemUI\res\values\public.xml:599: Originally[/color][color=#000000]defined here.[/color]<br />
[color=#000000]C:\Users\21\Desktop\apktool\SystemUI\res\values\public.xml:600: error: Pub[/color][color=#000000]lic symbol id/notification_inspect_item declared here is not defined.[/color][color=#000000]C:\Users\21\Desktop\apktool\SystemUI\res\values\public.xml:603: error: Pub[/color][color=#000000]lic entry identifier 0x7f0e0094 entry index is larger than available symbols (in[/color][color=#000000]dex 148, total symbols 146).[/color]<br />
[color=#000000]C:\Users\21\Desktop\apktool\SystemUI\res\values\public.xml:603: error: Pub[/color][color=#000000]lic symbol id/search declared here is not defined.[/color]<br />
[color=#000000]Exception in thread "main" brut.androlib.AndrolibException: brut.common.BrutExce[/color][color=#000000]ption: could not exec command: [aapt, p, -F, C:\Users21\AppData\Local\Tem[/color][color=#000000]p\APKTOOL2460210573261669654.tmp, -I, C:\Users\21\apktool\framework\1.apk,[/color]<br />
[color=#000000]-S, C:\Users\21\Desktop\apktool\SystemUI\res, -M, C:\Users\21\Deskt[/color][color=#000000]op\apktool\SystemUI\AndroidManifest.xml][/color]<br />
[color=#000000]at brut.androlib.res.AndrolibResources.aaptPackage(AndrolibResources.jav[/color][color=#000000]a:193)[/color]<br />
[color=#000000]at brut.androlib.Androlib.buildResourcesFull(Androlib.java:301)[/color]<br />
[color=#000000]at brut.androlib.Androlib.buildResources(Androlib.java:248)[/color]<br />
[color=#000000]at brut.androlib.Androlib.build(Androlib.java:171)[/color]<br />
[color=#000000]at brut.androlib.Androlib.build(Androlib.java:154)[/color]<br />
[color=#000000]at brut.apktool.Main.cmdBuild(Main.java:182)[/color]<br />
[color=#000000]at brut.apktool.Main.main(Main.java:67)[/color]<br />
[color=#000000]Caused by: brut.common.BrutException: could not exec command: [aapt, p, -F, C:\U[/color]<br />
[color=#000000]sers\21\AppData\Local\Temp\APKTOOL2460210573261669654.tmp, -I, C:\Users\[/color][color=#000000]21\apktool\framework\1.apk, -S, C:\Users\21\Desktop\apktool\SystemUI\r[/color]<br />
[color=#000000]es, -M, C:\Users\21\Desktop\apktool\SystemUI\AndroidManifest.xml][/color]<br />
[color=#000000]at brut.util.OS.exec(OS.java:83)[/color]<br />
[color=#000000]at brut.androlib.res.AndrolibResources.aaptPackage(AndrolibResources.jav[/color]<br />
[color=#000000]a:191)[/color]<br />
[color=#000000]... 6 more[/color]
it seems like I make something wrong in my public.xml:

Code:
<br />
    <public type="id" name="slider" id="0x7f0e008c" /><br />
    <public type="id" name="label" id="0x7f0e008d" /><br />
    <public type="id" name="close" id="0x7f0e008e" /><br />
    <public type="id" name="recent_remove_item" id="0x7f0e008f" /><br />
    <public type="id" name="recent_inspect_item" id="0x7f0e0090" /><br />
<public type="id" name="notification_inspect_item" id="0x7f0e0091" /><br />
<public type="id" name="recent_remove_item" id="0x7f0e0092" /><br />
<public type="id" name="recent_inspect_item" id="0x7f0e0093" /><br />
<public type="id" name="search" id="0x7f0e0094" /> <br />
</resources>
any suggestions?
 
#21 · (Edited by Moderator)
9. Find these methods/lines: .method public setMenuVisibility(Z)V and .method public setMenuVisibility(ZZ)V

You want to delete most of the content of these methods, leaving just the .locals, .paramaters, and return lines. Here's what it should looks like:

Code:
<br />
.method public setMenuVisibility(Z)V<br />
	.locals 1<br />
	.parameter "show"<br />
<br />
	return-void<br />
.end method<br />
<br />
.method public setMenuVisibility(ZZ)V<br />
	.locals 2<br />
	.parameter "show"<br />
	.parameter "force"<br />
<br />
	return-void<br />
.end method<br />
[background=rgb(245, 245, 245)]Doing this keeps the menu key always visible.[/background]
If I just want the standard 3dot menu to always show would I only need this step?
 
#23 ·
Awesome guide! Thanks! Quick question about adding a long-press. I want to long press menu and have to go to recents. So in the menu button code, I add the "systemui:keyRepeat="true"" like you said, but then what? Do I add the code for the second button after it? Thanks a ton for your work on this! :D
 
#28 · (Edited by Moderator)
I followed the guide in an attempt to add a search nav button to a rasbeanjelly for the N4. I made all the changes and recompiled SystemUI.apk successfully (didn't see any errors at least). I copied res folder, classes.dex, resources.arsc into the original SystemUI.apk and flashed the rom again. It flashed fine but SystemUI forces closes after booting.

Is this most likely a post compiling issue with signatures ... or some other error I made along the way before compiling? When I saw no compiling errors I thought I was in the clear.

Thanks for the guide.

Edit: Could the navigationbar.xml file you linked be different/incompatible with what I need? I suppose I should compare them.
 
#29 · (Edited by Moderator)
You dont need to copy res classes and resource file when compiling a systemui. If it compiled without errors that should be fine.

And btw this is my navigation bar xml for rasbean jelly you should be fine to use it on n4. Default layout is back-menu-home-recent. Just add the search key line or remove the menu and insert search key in to it. Donload>http://db.tt/oYAb00kX

Sent from my Galaxy Nexus
 
#35 · (Edited by Moderator)
Using a gnex deodexed stock 4.2.2 firmware..

I got it working just fine albeit minus the search button, since I don't have a use for it. It takes some finagling but it works, the process isn't identical. I got it to work however! It started out really slow, first I'd reorder the navbar, then I added the menu key and long press for the home button to get recent apps to show up. Right now I'm trying to get it worked out so that the menu button isn't tiny and they're all centered.

Slowly but steadily I'll figure it out! Trial and error my friend! I just gotta figure out the spacing for the navbar! I will post my navigation_bar.xml later I'm off to bed!
 

Attachments

#34 ·
Hey Detonation A very nice job, have u seen the navigation keys action in Huawei Ascend D2,
it has a fourth button on left hand side on nav bar,it is for hiding the nav bar.
You can recall the nav bar by just swapping the finger to upside at the bottom.
The nav keys will be visible again.The purpose of showing this to u is I hope from u that,
U can make a mod like that for our xperia devices,I have Xperia V running on 1.140fw..........
Waiting for a miracle from U,Thanx in advance
 
This is an older thread, you may not receive a response, and could be reviving an old thread. Please consider creating a new thread.
Top