Porting Nougat Apps to Marshmallow
This might be a long one... So i couldn't find any guide regarding the basics at least of porting apps. The idea behind it is somewhat simple, You gather logs, Fix mismatches , test, rinse and repeat until the app works.
This will cover the idea / some common fixes for porting N Apps to MM , (downgrading API , fixing missing methods etc)
I assume you would know how to do the basic stuff as recompiling / decompiling etc
Difficulty : Not impossible
Requirements : -
- Ability to run logcats
- Knowing how to deal with adb push pull etc
- Knowing how to use TMA (Tickle my android) or any apktool
- Familiar with smali (Removing / adding methods etc)
- A device
- Time...lots and lots of time
Helpful apps (almost required in my opinion)
Atom : A very neat Text editor with a global search and replace feature, we will need that when replacing method names further down in the guide
Notepad ++ : Another nice text editor
Winmerg : Comparing 2 folders and the files inside them, helpful when looking at changes between apps
Fileseek : Allows you to search for a string of text in a folder (Atom does the same, but this is faster and easier to use)
Finally download the attachment below, it will help alot
It contains latest ADB version , and some quick batch files you can run for logging , pushing apks etc , Put it in _OUT folder in TMA
You can edit the .bat file you want with any text editor to change apkname / path.
I suggest that you always put the app name the same as the old one you have so its quicker to Log
---------------------------
So lets begin. in this example we will be using MyFiles from S8 Rom.
Please note this will not get you the running apk , you need to do that by yourself, this is just an app to get logs and give examples
First of all , get the APK you need to work on, download the attachment below , put the apk you want to port in TMA _IN folder , install frameworks (S8 apps install S8 Framework and so on) , Decompile app and do the following
1- Getting the app to install on Marshmallow (No parsing error) would be the first step to do
First, open the app APK with winrar , and delete SEC-INF Folder
Then decompile the APK, Go to _Working/Apkname , And edit these 2 files
Androidmanifest
Change
" platformBuildVersionCode="24" platformBuildVersionName="7.0"> "
To
" platformBuildVersionCode="23" platformBuildVersionName="6.0">"
Then Edit apktool.yml
Change "
minSdkVersion: '24'
targetSdkVersion: '24'
To
minSdkVersion: '23'
targetSdkVersion: '24'
----------------------------
What we did basically was changing the APK api level to work on MM. Save the 2 files then
recompile with new signature. and run the bat to push the file (in this case Sfiles bat) , reboot the phone (so you dont get any weird log erros) rebooting only needed the first time you push the apk, also wiping cache/data is a good practice for the app
Now, Run the APP and it will FC, thats when you know the downgrade worked.
If you dont see the app in your drawer check the system folder to make sure its in the right path / permissions , if its there and shows parsing error, re read the first part.
--------------------------
2- Pulling Logs and fixing common errors
SemFloatingFeature Error -----------
Run Logerrors.bat , then open the app few times to log runtime error
You will have an error.log file in your _Out Folder, open it with notapad++
What we are looking for is runtime error. This is how the log would look like for sfiles app if its the first time porting.
Code:
05-26 15:08:36.191 11364 11364 E AndroidRuntime: FATAL EXCEPTION: main
05-26 15:08:36.191 11364 11364 E AndroidRuntime: Process: com.sec.android.app.myfiles, PID: 11364
05-26 15:08:36.191 11364 11364 E AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/samsung/android/feature/SemFloatingFeature;
05-26 15:08:36.191 11364 11364 E AndroidRuntime: at com.sec.android.app.myfiles.info.AppFeatures.<clinit>(AppFeatures.java)
05-26 15:08:36.191 11364 11364 E AndroidRuntime: at com.sec.android.app.myfiles.provider.MyFilesProvider.onCreate(MyFilesProvider.java)
05-26 15:08:36.191 11364 11364 E AndroidRuntime: at android.content.ContentProvider.attachInfo(ContentProvider.java)
05-26 15:08:36.191 11364 11364 E AndroidRuntime: at android.content.ContentProvider.attachInfo(ContentProvider.java)
05-26 15:08:36.191 11364 11364 E AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java)
....................
What we really need is the first line for now
Code:
05-26 15:08:36.191 11364 11364 E AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/samsung/android/feature/SemFloatingFeature;
05-26 15:08:36.191 11364 11364 E AndroidRuntime: at com.sec.android.app.myfiles.info.AppFeatures.<clinit>(AppFeatures.java)
So issue is simple, it cant find SemFloatingFeature because we dont have Nougat. So we fix that by renaming it to the propper MM name, which is FloatingFeature
To fix it. Open ATOM text editor, select the APK Folder in _working
And press Ctrl + Shift + F , Type "Lcom/samsung/android/feature/SemFloatingFeature;" in FIND IN PROJECT
And type "Lcom/samsung/android/feature/FloatingFeature;" in REPLACE IN PROJECT
Press FindAll , then replace all , Recomplile again with new signiture, Push app , Run log , repeat the process
SemCscFeature---------------
second common error is SemCSCFeatute
Code:
05-26 15:16:08.231 13222 13222 E AndroidRuntime: Process: com.sec.android.app.myfiles, PID: 13222
05-26 15:16:08.231 13222 13222 E AndroidRuntime: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/samsung/android/feature/SemCscFeature;
05-26 15:16:08.231 13222 13222 E AndroidRuntime: at com.sec.android.app.myfiles.info.AppFeatures.<clinit>(AppFeatures.java)
To fix this error, you need to fix the path, not only the name, In MM The path is "Lcom/sec/android/app/CscFeature;"
To Find these paths by yourself, you can decompile framework.jar from Nougat and MM , then find the SemCSCFeature line in nougat. There will be an equivalent in MM called CSCFeature, Another method i use is you can use Winmerg , then compare both APKs from MM to N (in this case sfiles) and navigate to the broken smali by following the log, in this case its smali/com/sec/android/app/myfiles/info/Appfeatures.smali <Clint> Method, compare it and old my files and will give you the popper path.
So Using atom, find all old path, and replace with new path
Lcom/samsung/android/feature/SemCscFeature;
To
Lcom/sec/android/app/CscFeature;
------------------------
3- Renamed Methods.
So if the idea is clear, you should be able to understand this fast.
Run a log and you will see a new error
Code:
05-26 15:27:30.881 13893 13893 E AndroidRuntime: java.lang.NoSuchMethodError: No virtual method getBoolean(Ljava/lang/String;)Z in class Lcom/samsung/android/feature/FloatingFeature; or its super classes (declaration of 'com.samsung.android.feature.FloatingFeature' appears in /system/framework/framework.jar:classes2.dex)
05-26 15:27:30.881 13893 13893 E AndroidRuntime: at com.sec.android.app.myfiles.info.AppFeatures.<clinit>(AppFeatures.java)
So . to break down this log, It is seraching for getboolean method in your framework jar but it cant find it. its searching in framework.jar / com / samsung / android / feature / FloatingFeature.smali (in classes dex 2)
There are 2 ways to fix this
1- Add the missing method manually to framework.jar (This isnt recommended honestly , But some future errors cant be just renamed and must be added / removed from the apk itself
2- Finding the propper name
You can either use winmerg and compare old app, but if you dont have the old app , what i do is i decompile both frameworks, compare FloatingFeature.smali and SemFloatingFeature.smali to find what is the method supposed to be, you can search for surrounding code in both smalis , it takes time but in the end you will get the result , in this case
Easier way is to compare old and new APK , and search surrounding code, in the end you will get the propper name
Code:
[COLOR="Red"]getBoolean(Ljava/lang/String;)Z[/COLOR] In nougat is [COLOR="Red"]getEnableStatus(Ljava/lang/String;)Z[/COLOR] in MM
[COLOR="Red"]Landroid/os/SemSystemProperties;[/COLOR] In nougat is [COLOR="Red"]Landroid/os/SystemProperties;[/COLOR] in MM
UPDATE 7/5/2017
So i decided to update this guide with some more helpful notes / ways to fix certain errors that cant be routed or renamed , and its hard to add in framework directly, and add propper adb zip , i forgot the most important file which is logerros lol
in this example we will take a look at the following error
Code:
07-05 00:04:11.511 9591 9591 E AndroidRuntime: FATAL EXCEPTION: main
07-05 00:04:11.511 9591 9591 E AndroidRuntime: Process: com.sec.android.app.launcher, PID: 9591
07-05 00:04:11.511 9591 9591 E AndroidRuntime: java.lang.NoSuchMethodError: No static method isDesktopMode()Z in class Lcom/samsung/android/desktop/DesktopManager; or its super classes (declaration of 'com.samsung.android.desktop.DesktopManager' appears in /system/framework/framework.jar:classes2.dex)
07-05 00:04:11.511 9591 9591 E AndroidRuntime: at com.android.launcher3.LauncherProvider.onCreate(LauncherProvider.java)
07-05 00:04:11.511 9591 9591 E AndroidRuntime: at android.content.ContentProvider.attachInfo(ContentProvider.java)
07-05 00:04:11.511 9591 9591 E AndroidRuntime: at android.content.ContentProvider.attachInfo(ContentProvider.java)
So our problem is
Code:
E AndroidRuntime: java.lang.NoSuchMethodError: No static method isDesktopMode()Z
This is an example of porting S8 launcher, you will get this error eventually.
So its looking for
isDesktopMode()z inside
Lcom/samsung/android/desktop/DesktopManager; and it cant find it in the app or in framework.jar classess2
So how do we fix this ?
2 ways, and both will work just fine for the most part.
We can find that code and what smali it is in, then add that entire smali (with proper pathing) inside our framework
So this means the smali that got
isDesktopMode()z would be
SemDesktopModeManager.smali . you can get this smali from the same framework path in S8 framework. and ofcourse the child smalis with it.
So we add it to
framework.jar/smali_classes2/com/samsung/android/DesktopManager/ (obviously we need to create the folders) and add the 3 smalis inside that folder (attached below for reference)
Now the second way is the preferred way if you ever wish to share your app, adding the missing smali inside the apk itself.
in this case we do the excat same thing, and we add the missing smali inside
launcher.apk/smali/com/samsung/android/DesktopManager
And the app will get the missing smalis.
Same can be done for multiple other smalis that then you can basically drop into your apk (preferably in a new class dex to avoid any possible conflicts)
Thanks to
@corsicanu for teaching me that its possible to add smalis inside the apk itself without rerouting for the most part :laugh:
----------------------------------------
There are many more renamed methods , Some like string;z)z and string;Z)Z , notice the uppercase , it matters. The more issues you solve the more complex / easier it gets , it all depends , some methods would require you to delete invokes and method code from smali , and some would require you to add invokes and methods in framework jar. Not all apps can be ported, But this is the basics of it.
This will also allow you to fix FC errors in some apps if you know how to look, this isnt a Guide to quickly port an app, it just throws the idea because not everyone is moving to Nougat, and i have no use for this knowledge without sharing it.
Finally, Any dev willing to help add/fix some mistakes i made, please mention it. in the end this is for people who want to get into porting
Thanks to XDA community because all of this is from here, and thanks to
@thereassaad @DaOldMan and
@Kill-Switch and many more who helped me learn this.