Are these two ways equal and correct?
Method 1:
Odex the APK to a .apk and a .odex
Sign the .apk file produced in step 1
Method 2:
Sign the APK
Odex the APK to a .apk and a .odex
First you need to understand working of .apk and .odex file.
.Odex file:
Odex file is the extracted and optimized DEX file (classes.dex) from APK or JAR files.
An ODEX file has dependencies on every file in the BOOTCLASSPATH that is loaded when it is generated.
The odex file is only valid when used with these exact BOOTCLASSPATH files.
Android Application come in packages with the extension .apk. These application packages, or APKs contain certain .odex files whose supposed function is to save space.
These ‘odex’ files are actually collections of parts of an application that are optimized before booting.
It also makes hacking those applications difficult because a part of the coding has already been extracted to another location before execution.
How it work:-
Android OS uses a Java-based virtual machine for running applications, called the Dalvik Virtual Machine. A deodexed, or .dex file contains the cache used by this virtual machine (referred to as Dalvik-cache) for a program, and it is stored inside the APK. An .odex file, on the other hand, is an optimized version of this same .dex file that is stored next to the APK as opposed to inside it.
Android applies this technique by default to all the system applications.
Now, when an Android-based system is booting, the davlik cache for the Davlik VM is built using these .odex files, allowing the OS to learn in advance what applications will be loaded, and thus speeds up the booting process.
By deodexing these APKs, a developer actually puts the .odex files back inside their respective APK packages. Since all code is now contained within the APK itself, it becomes possible to modify any application package without conflicting with the operating system’s execution environment.
You can find some information Here and
Here is one StackOverFlow question may helpful to you.
Related
When we install an apk on Android,system will get the classes.dex out of the apk file,optimize it with dexopt tool and generate another .dex file stored in /data/dalvik-cache.
Now if we use dexopt-wrappter tool to optimize the apk first to generate the odex file,and then delete the classes.dex from apk file,and then push the apk file(without classes.dex) and the odex file into /data/app.
Will the second way be faster than the first way when launching this app?
If all apks in this system have been optimized with the second way,will it be faster when launching the system?
I know the .dex files in /data/dalvik-cache/ are the same as files generating by the second way.I just wonder that will it be faster when launching with the second way.Because original Android system apps have been all optimized with the second way.
I am trying to modify an APK which came with my official firmware.
Actually only some resources should be modified (sounds should be replaced with silent files).
I moved APK and ODEX to backup folder, unzipped APK on a PC, modified files, zipped APK with 7Zip again and placed it into /system/app folder with corresponding permissions. After a reboot Camera application disappeared from everywhere.
Ok, I copied ODEX file back to /system/app, rebooted, and application appeared, but trying to run it makes it crash.
APK file has no DEX inside.
I thought that ODEX file contains code only and shouldn't be re-created.
What I was doing wrong and how to do it right?
You can't modify apk's without signing them again. The Android system will notice that the apk has been tampered with and refuse to load it. You could sign it with your own key, but then your signature wont match the official signature for that package name and that will prevent you from getting any updates for that application as long as your modified apk is installed. Also if that application is relying on being signed with the same certificates as other applications from the same manufacturer it wont work correctly.
You can read about signing android applications in the official documentation
Why do you want to do this?
I'm creating a software that will guide the user through a few steps, to publish an android application (APK file).
The way I am doing this, is that the APK file is already compiled, and all I need to do is replace an XML file in the package, and that will change the behaviour of the application. My big problem now, is that unpacking the apk file, and doing any tiny text edit, and then packing it again, breaks the signature and prevents the application from running on any device, giving a message that the signature is incorrect.
How can I solve this? I want to safely open the APK, write something in a text file, and close it again. Note that this operation will be done on the user's computer (after he purchases our application) so we're look for a command-line tool with no special requirements like JDK.
Any help?
Ok I reached the best "tested" solution - I'm posting it here to save other developers hours of googling. The only downside is that I will require the customer to install JDK on his machine, unfortunately. The reason is because I did not find any apk-signing tool that works purely on windows, without relying on JDK.
I have my android application created using Air, so this makes things easy for me - all of the air files are treated as resource assets. So have your APK archive file ready.
Once you have your modifications ready, put them inside a temporary folder named "assets". You will use the 7-zip command line tool (free: http://sourceforge.net/projects/sevenzip/) to update the contents of your apk. To have it working with your apk you will have to rename your apk's extension to zip - don't worry, you'll change it back later.
Now from a .bat file (or directly in the command prompt) from the location containing both your apk file (zip extensioned) and your assets folder, you'll call: 7za u APK-file.zip assets
Now your apk file is updated. Rename it back to .apk extension
Now you'll use the signAPK tool from here https://code.google.com/p/signapk/ and note that this is the only step requiring JDK installed. It also assumes that you have your key files ready (replace the dummy ones included in the package). Extract the file contents and call: java -jar signapk.jar key.x509.pem key.pk8 [android_app].apk [signed_android_app].apk
At the very end, you may find your signed apk file size drammatically increased. So you need to use the android's zipAlign tool: (darn, can't post the link since new users can only post a maximum of two hyperlinks)
you will be calling the command: zipAlign -c 4 [signed_android_app].apk
And voila! That's the route I'm taking.
If someone finds a way to do the signing process without relying on JDK (assuming the key files are ready) please share.
How can I solve this?
You don't. If you modify an APK file, by any means, it must be re-signed.
Android apk files must be signed. That signature proves that the contents of the apk have NOT BEEN MODIFIED from what was initially published. (Which is exactly what you are doing.) The signature at the same time, also proves who the author is.
So in a normal signed apk file:
You know who the author is. (Even if it's not something you as a human can understand.)
You know the contents were put there by the author, and not modified since.
This is a key security measure built into Android, is there for very good reason, and cannot be overcome. It prevents things like viruses from being embedded inside innocent apk files.
This is a very interesting thing. I have an APK file, com.company.app.apk. When installed to an emulator by using Eclipse, by using the following code to get the apk's file name:
String fileName = activity.getPackageManager().getApplicationInfo(
activity.getPackageName(), PackageManager.GET_META_DATA).publicSourceDir;
I get a pathname like this com.company.app-1.apk. The file size is the same as the apk file I built.
Now when I publish this app to Market, and install it to a real device (Android 2.3), the same code returned a pathname like this: com.company.app-2.zip. Note that the file extension has changed to .zip and, most importantly, the file size is significantly smaller than the original size.
Now if I transfer these two files to my PC and use WinZip to open them, I found one really interesting thing:
The one installed on emulator by Eclipse has exactly the same stuff as I expected. Namely: the code ('com' folder), the resource ('res' folder), the signature ('META-INF' folder), the assets ('assets' folder), and the manifest file (AndroidManifest.xml). However, the one installed on a real device by Market has only two parts: the resource, and the manifest file.
Question: I think when installed from Market, the .apk file is split into two (or more) files. One file is pointed to by ApplicationInfo.publicSourceDir, which contains only the resource. How can I get the pathname to the other file(s)?
ADDED: I have two versions of the same app, one is paid using Google's Vendor Licensing Service, the other is free. The above mentioned phenomenon happens only to the paid version. Why?
Correction: When I said the 'com' folder exists in the installed apk file in the first case, I should be more clear. The code per se, the *.java files, are not in the 'com' folder. As a matter of fact, the 'com' folder contains only a few garbage files that were inadvertently left there during the build process. If not for those garbage files, I don't think the 'com' folder would be there in the first place.
I think you are not right. The market works in the following way: you choose an application and push a button to install it. After that market sends the intent to gtalk service to install the application. This service downloads apk file that you've uploaded to the market and when finishes it installs this apk. Just during the installation can some changes happen. It seems to me that from the application during the installation classes.dex file is extracted and from this file optimized dex (.odex) is produced and put in the separate directory. That's why you see the difference in the files.
Ok, here is what I've found out, in case this helps someone out there:
When Market installs the free version of my app, the apk file is installed to /data/app/com.company.app.apk, the file content is exactly the same as I built it, same file size, same everything.
For the paid version that uses Market Vendor Licensing, the apk file itself is installed to /data/app-private/com.company.app.apk. This is the same file as I released. However, the resources are extracted and installed to another file /data/app/com.company.app.zip, note the file extension. This zip file contains only resources, so it's significantly smaller. But the .apk file in /data/app-private has everything, so the file size is the same as I built it.
ApplicationInfo.publicSourceDir always points to the file in /data/app, so it's /data/app/com.company.app.zip in the paid version's case, and /data/app/com.company.app.apk for the free version. For the paid version, I obtained the pathname from publicSourceDir, then replace.app with app-private, and replace .zip with .apk to get the original file.
If I install the apk directly to an emulator, then there is only one file and is always installed under /data/app.
How the .apk installation process works on device? Is the .apk file just copied to some place and kind of installer application extracts the application information, register somehow the application to environment, extract also the icon and put it on the application launch screen? Or the .apk content is extracted and files are copied to various folders and the .apk file itself is deleted?
I am asking to understand if there is any possibility on device to browse the .apk file structure and its content and access in read-only mode directly the assets, res folders, AndroidManifest.xml, the dex file and also used libraries (.jar or .so)?
The reason I am asking is that I am looking for possibility to read into memory .dex, .jar or .so files like arbitrary binary files (e.g. by using the File class) for the purpose of computing a message digest from its content (i.e. using md5 or other hash method)...
BR
STeN
The APK is copied onto the device, usually into the /system/app directory. The APK is not extracted or unzipped until it is used, so if you want to probe the files you'll need to do the decompression and extraction yourself.