Monday, August 31, 2015

Modding Android SystemUI.apk

Look at that bloated ugliness of a navigation bar.. And it's not even centered!

I've just upgraded my Teclast X98 Air 3G tablet to Android Lollipop and it is faaaantastic. It's incredible how each new Android release makes older hardware run the software with ever more fluidity. However, with the new upgrade means I've lost the stock navigation bars. These Chinese tablets love to mod the navigation bar to include the screenshot, vol+, vol-, and the menu icon (most likely to support Android TV sticks. They look ugly and are a nuisance when I keep accidentally tapping on it. Now to remove this requires modding the stock Android system app SystemUI.apk. I've done this before but I couldn't quite remember it hence I'm leaving a note to myself on how this is done so I won't have to keep googling next time around.

Note: For Windows users, all of these information should be the same, the shell scripts will not work though, you will have to adapt it for batch scripting.

What you'll need:

  • Rooted Android device with developer options enabled
  • Apktool.jar - at time of writing latest is apktool_2.0.1.jar
  • Computer with adb tools and Java installed


So, first, you'll need a copy of the SystemUI.apk. Do this via:

adb pull /system/priv-app/SystemUI/SystemUI.apk
You'll also need a copy of framework-res.apk. Again:

adb pull /system/framework/framework-res.apk

These two files basically contain the android system's layout and image resources - the "/res" directory in any UI Android activity. Keep a copy of these somewhere so you can always reset to these if your mods mess up.


Next, we'll need to extract these files.

# install framework
java -jar apktool_2.0.1.jar if ./framework-res.apk

# install systemUI
java -jar apktool_2.0.1.jar if ./SystemUI.apk

# decode the SystemUI package
java -jar apktool_2.0.1.jar d ./SystemUI.apk


This gives us an extracted /SystemUI folder with all the resources as if you were building an Android app project. If you're an Android developer, this should be familiar to you, go ahead and get modding. All you have to do is find the layout for the navigation bar and change the xml files. In my case, the appropriate file is in /SystemUI/res/layout-sw600dp-v13/navigation_bar.xml. This path indicates that the resource is used on a device with a minimum screen width of 600 dp and has at least an SDK version of 13. Now open the file and you'll see a text in xml format. This, here, is interesting to me because it seems that the layout definition for the landscape and portrait modes are actually sitting in the same xml file, but the orientation would just simply pick whether to use the first FrameLayout with id "@id/rot0" or the second FrameLayout with id "@id/rot90". Anyway, looking closely at the ids of some of the KeyButtonViews, you can see "@id/screenshot", "@id/volumedown", "@id/back", "@id/home", "@id/recent_apps", "@id/volume_up", "@id_menu", etc. Now we just have to modify these such that their dimensions are so small that you can't see them. Or you could make their visibility property invisible. However, that would not solve the problem because they'd still be clickable even if they're invisible.

My modifications to these xml items are to set the layout_width to "0.0dip" so that each of these entries would have this property:

android:layout_width="0.0dip"

Save the file. Before we go on to the next step, it is noted that the current apktool decodes this SystemUI.apk incorrectly and will align the Lollipop's pulldown menu to the left when you try to apply this patch, even without mucking any of the xml files. I'm unsure if this is an issue with Apktool or the SystemUI.apk file that is used in this tablet. In any case, the additional steps you'll need to modify are:

  • in file /SystemUI/res/layout/status_bar_expanded_header.xml, look for android:layout_gravity="center|left|top" and change it to android:layout_gravity="center|top" (should only be one instance ofStatusBarHeaderView that uses this property)
  • in file /SystemUI/res/layout/status_bar_expanded.xml, do the same thing. replace all "center|left|top" to "center|top" (4 instances in my build)

Now we need to package this back into the Android package format using the same Apktool. This is simply done by running:

java -jar apktool_2.0.1.jar b SystemUI

In your previously generated /SystemUI/ folder should now be a sub-folder called "dist" (short for distribution I suppose?). In that sub-folder you will find a SystemUI.apk, this is the newly modded file you will try to put back into your device. To do so, run the following commands.

# Temporarily throw the file back into the sdcard root
adb push ./SystemUI/dist/SystemUI.apk /sdcard/SystemUI.apk

# Get superuser access and mount the system directory as rewritable
adb shell "su -c mount -o remount,rw /system"

# Overwrite the new SystemUI.apk file with the current SystemUI.apk
adb shell "su -c cp /sdcard/SystemUI.apk /system/priv-app/SystemUI/SystemUI.apk"

In a moment your android device may complain that SystemUI.apk has stopped working, and it will flash momentarily, locking your device and on wake/return, you'll see the modded navigation bars. You may have to reboot device for pre-KitKat versions of Android in this step. If your device doesn't complain, lock the screen and wake it up again, it should just load the new modded apk. If it still doesn't do it, try restarting, however, I have not come across this issue yet. I do notice that sometimes small changes do not get updated, so what I would do is use the last set of commands to restore the SystemUI.apk to the original version (before you modded, the one I told you to keep a backup somewhere) and then reapply the new patch. It would be wise to create a script that you will run each time you make a modification to facilitate loading the modded files in. Here are my shell scripts:

# decode.sh
rm -r ~/apktool/framework
rm -r SystemUI

# install framework
java -jar apktool_2.0.1.jar if ./framework-res.apk

# install systemUI
java -jar apktool_2.0.1.jar if ./SystemUI.apk

# decode the SystemUI package
java -jar apktool_2.0.1.jar d ./SystemUI.apk

# encodeAndLoad.sh
java -jar apktool_2.0.1.jar b SystemUI

# Temporarily throw the file back into the sdcard root
adb push ./SystemUI/dist/SystemUI.apk /sdcard/SystemUI.apk

# Get superuser access and mount the system directory as rewritable
adb shell "su -c mount -o remount,rw /system"

# Overwrite the new SystemUI.apk file with the current SystemUI.apk
adb shell "su -c cp /sdcard/SystemUI.apk /system/priv-app/SystemUI/SystemUI.apk"

# restore.sh
adb push ~/SystemUI.apk /sdcard/SystemUI.apk
adb shell "su -c mount -o remount,rw /system"
adb shell "su -c cp /sdcard/SystemUI.apk /system/priv-app/SystemUI/SystemUI.apk"

What does the end result look like?

Much cleaner, but the mdpi drawables for the back/home/recent buttons are kind of fuzzy. I should do something about that, too.

6 comments :

  1. hi!
    great work here, much more cleaner!

    I'm trying to mod SystemUI.apk of my cube iWork 10 but I'm pretty confused about all the stuff it's inside the apk.. I'm not a mood but I don't know where to look for the stuff I need and some very common naming rules :(
    For example: I really want to remove the battery level percentage in number that is placed to the left of the battery itself in the status bar.. The unpacked apk has a lot of battery related files inside, so I don't know what to edit..
    Do you have some link where I can find some common name rules explained, maybe, if you please?

    Thanks a lot for paying attention, happy modding! ;)

    ReplyDelete
  2. Hi if you look at my next post that shows how to use UIAutomationViewer tool, you can simply click on the battery percentage using the tool and it will show you what the resource name is. Then you can do a grep search on that resource name and find the file to edit.

    ReplyDelete
    Replies
    1. Hi Tso, thanks for replying me!

      OK, I'll give a look at that, hope it could help me!
      Have a nice day, see you!

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete