Tuesday, January 17, 2012

Porting TouchWiz Apps for CM7



So hey, I'm Tortel. Recently, I've taken some time to port some of my favorite stock apps to CM7. In that time, I came up with a pretty decent process to remove all the TouchWiz dependencies from stock apps, and I would like to share what I have done. Check the thread on XDA for some downloads.

Here's the basic steps I took for removing the TouchWiz dependencies from the Memo, Calendar, and Task Manager apps

1. De-compile the app
I used apktool for this, use whatever you want

2. Remove the library dependence from the AndroidManifest.xml
The line looks like this:
<uses-library android:name="touchwiz" />
With that removed, it will install correctly. Might not work yet, but it will install.
Something else to look out for is alsong the lines of ‘com.device.samsung’

3. De-compile both the twframework.jar and twframework-res.apk files.

I used apktool again for this. We need the code for the stupidly re-written widgets, resources, and other shit.

4. Copy the twframework code into the app source.
With apktool, the directories to copy are in ‘twframework.jar.out/smali/’
Copy that entire directory tree into the app your de-TWing. Some directories will overlap, that’s normal.
The app your working on now contains both its own code, and all the needed TouchWiz code. There’s a small chance it might work if you recompile it now, but it probably also needs resources.

5. Update the resources

a. Add the needed files/parts
I found its easiest to search for any ‘@touchwiz:’ parts in any xml file under res/.
Next, you will need to merge everything under /res/ from the twframework-res.apk.
Copy over anything that doesn’t already exist. Files under /res/values/ (Except public.xml) will need to be merged, meaning insert all the values from the framework into the app, before the closing tag (Keep the XML valid). If your missing any resources, re-compiling the APK will fail and let you know vaguely what you need.

b. Remove the touchwiz references
Replace every occurrence of ‘@touchwiz:’ with just an ‘@’
In the Memo.apk, there were lots of references to ‘@touchwiz:color__’. find and sed are helpful
Don’t forget to remove the colon!

There are some calls to IDs in the 0x20 range, this is an issue because as far as I know, the 0x20 range can only be provided by the system somehow. For the Calendar app, I had to remove setIcon calls in a few activities to prevent ResourceNotFound exceptions.
If you remove them, then some things like images might not work. I also found that just removing them can cause random NullPointer errors.

Note: While working on the Task Manager, it became more complex. I had to update the old 0x20 references to the references within the new package.
After the resources are added, decompile it again, so the added resources show up in the /res/values/public.xml
Search for the old 0x20 value, and update it to the new value. If you include the /smali/touchwiz/ directory, then you can just search for the hex value and you will get the name of it from the TW R.smali files, and you can find the updated hex value in the /res/value/public.xml file

6. Re-compile

I used apktool again.

7. Sign the apk

Its a system app, so it will need one of two possible keys: The CM testkey, or the CM platform key, depending on its permissions.
These keys are found in ~/android/system/build/target/product/security/ as testkey.pk8 and testkey.x509.pem (Or platform)

To sign using these files, you need SignAPK (http://code.google.com/p/signapk/)
Usage: signapk testkey.x509.pem testkey.pk8 original.apk signed.apk

The Calendar and provider needed the testkey signature, but the Task Manager needed the platform signature. It depends on the permissions of the app. Check the log for any permission errors, and google them. Most apps will probably only need the testkey signature.

8. Install
adb push /system/app/ ftw!

9. Run it, and have logcat open
Check for any exceptions, fix whats needed, and re-test.
Most likely, you’ll run into ResourceNotFound exceptions, and maybe NullPointer exceptions. This is the most fun part.
For ResourceNotFound, I grepped the source for the hex value. Then checked for the new value, and replaced all occurrences. (See 5b)
NullPointer exceptions seem to be from findResource calls. Check the smali for the class where the error occurs, and replace any 0x20x hex values with the updated value.
Keep testing until it actually works. Make sure you check all parts of the app, and the context menus. Samsung’s code isn’t the cleanest, so there are fun surprises hiding everywhere.



Once its running
Don’t forget to zipalign the final working apk, after its signed. Then it should be all set.

4 comments:

  1. I: Building resources...
    Exception in thread "main" brut.androlib.AndrolibException: brut.common.BrutExce
    ption: could not exec command: [aapt, p, -F, C:\Users\ASPIRE\AppData\Local\Temp\
    APKTOOL8681481102277650201.tmp, -I, C:\Users\ASPIRE\apktool\framework\1.apk, -I,
    C:\Users\ASPIRE\apktool\framework\2.apk, -S, D:\Kiran\E\ANDROID SOFTIES\Apk_Man
    ager_5.0.2\other\..\projects\Mms.apk\res, -M, D:\Kiran\E\ANDROID SOFTIES\Apk_Man
    ager_5.0.2\other\..\projects\Mms.apk\AndroidManifest.xml]
    at brut.androlib.res.AndrolibResources.aaptPackage(AndrolibResources.jav
    a:193)
    at brut.androlib.Androlib.buildResourcesFull(Androlib.java:301)
    at brut.androlib.Androlib.buildResources(Androlib.java:248)
    at brut.androlib.Androlib.build(Androlib.java:171)
    at brut.androlib.Androlib.build(Androlib.java:154)
    at brut.apktool.Main.cmdBuild(Main.java:174)
    at brut.apktool.Main.main(Main.java:59)
    Caused by: brut.common.BrutException: could not exec command: [aapt, p, -F, C:\U
    sers\ASPIRE\AppData\Local\Temp\APKTOOL8681481102277650201.tmp, -I, C:\Users\ASPI
    RE\apktool\framework\1.apk, -I, C:\Users\ASPIRE\apktool\framework\2.apk, -S, D:\
    Kiran\E\ANDROID SOFTIES\Apk_Manager_5.0.2\other\..\projects\Mms.apk\res, -M, D:\
    Kiran\E\ANDROID SOFTIES\Apk_Manager_5.0.2\other\..\projects\Mms.apk\AndroidManif
    est.xml]
    at brut.util.OS.exec(OS.java:83)
    at brut.androlib.res.AndrolibResources.aaptPackage(AndrolibResources.jav
    a:191)
    ... 6 more i get this error while recompiling after merging res folder

    ReplyDelete
  2. Well done man!!
    i have been waiting for this since so long!! Thanks alot!!

    ReplyDelete
  3. hey man!
    i am unable to decompile twframework.jar
    neither does apkmanager recognize it, nor does any other tool decompile it.
    any way out?

    ReplyDelete
    Replies
    1. @Dbatra

      Use smali/baksmali to decompile your jar file
      Here is a package on XDA

      http://forum.xda-developers.com/attachment.php?attachmentid=934193&d=1331041816

      here is my cut n paste post from XDA:

      Hi,

      I have totally repackaged your tools and added some of my own that will be of great help to people. The Smali packages I made my self, the dex2jar toolset was made by the guy that originally did the translating. Credits to him.

      I have also packaged everything with the latest smali/baksmali which will do Ice Cream Sandwich as well and it totally backawards compatible

      You now don't need instructions at all you just type decompile before the name of any jar file and it will do it all for you...same as for recompile (although I haven't tested that yet though. I assume that you will need to do all the regular stuff like apktool as I set it up the same

      Code:
      decompile services.jar
      thats it...its that simple

      Code:

      recompile out -o classes.dex
      then -> WinRAR services.jar and drag classes.dex back in and close


      NOTE: Use the help function. It is decompile.bat. It wil print the options in prompt for you.

      You guys who are ICS or less will need to change API level from default 14 (as you should all do anyway Rule #1 check the api level of the toolset and Question #1 is can it be changed to match mine? in this case yes!

      Delete