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.
Related
I want to store local android applications on local android repository (e.g. using fdroid) using different format (for example compressed in bzip2 -- MyApp.bz).
Can I change fdroid server to send bzip2 files to fdroid android "play store" app and then decompress it, tar it
(Or to keep it in uncompressed format) and rename as apk before handling it to the android package manager to be able do this? Will it still being able to install app with android package manager?
From what I understand not all apk files are compressed with zip, so package manager should understand tared file with renamed extension?
That´s not possible the only permitted format is the Android Application Package (.APK) that is compressed as .ZIP
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.
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.
Is there a way in Eclipse ADT to ignore a certain set of files under the Package Explorer when exporting an APK package?
I have a PhoneGap application that reuses a whole bunch of js/css/images with another application, but currently the APK export is including everything under my "assets" directory, inflating the APK size as a result. Ideally, I only want certain js/css/image files under my "assets" directory to be included in the package instead of everything.
I don't think that there is any support in the SDK/API to achieve this directly but you put your shared resources into a directory on to the memory card and refer to them there from your app? Though your next question is how would you 'install' the shared images etc without including them in the .apk file.. which I'm not sure of the answer.
How can I store a normal tree of files inside an Android .apk without all the weirdness of the Ressource or Asset concepts? It seems I have to do some akward thing to use Files from current path like any non-Android Java application do?
"use Files from current path" and "store... inside an Android .apk file" have nothing to do with each other.
Since, statistically speaking, you are likely familiar with Windows, let's draw some analogies.
"store... inside an Android .apk file" on Windows would be "store... inside a Windows .exe file". This is reasonably uncommon on Windows, at least the last I checked.
"use Files from current path" on Windows would refer to files that perhaps exist in the app's Program Files directory or the equivalent. On Android, this works fairly conventionally -- use getFilesDir() and Java file I/O.
What exists in Windows and does not exist in Android is the concept of packaging files to be installed at install time via an installer package, such as a .msi file.
Since you declined to tell us what the "normal tree of files" is and why you think it should be "inside an Android .apk", it is impossible to give you advice on how to avoid whatever "weirdness" you think exist in the "Ressource [sic] or Asset concepts". All I can tell you is that the equivalent on other OSes to bake files into the executable would likely be similarly "weird".
Okay, I haven't tested this, but a solution could be to add extra files to the APK before signing. You could automate this from the command line:
$ ant release
$ zip -r bin/MyApp-unsigned.apk <custom_folder>
$ jarsigner -verbose -keystore <keystore> -storepass <password> bin/MyApp-unsigned.apk <alias>
$ zipalign -v 4 bin/MyApp-unsigned.apk bin/MyApp-signed.apk
And then, in your activity, open the APK with ZipFile to access your custom folder:
ZipFile apk = new ZipFile(getApplicationInfo().sourceDir);
I'm not sure how the Android Market would react to this non-standard APK though.
With assets you can have a file tree in an APK, which can be accessed by using the AssetManager returned by getAssets().
The whole point of this mechanism is saving space. The files are not extracted to the file system when the app gets installed. When you read the content of an asset, it is uncompressed (unzipped) on the fly from the APK. It does make sense. Saving space is important on Android devices.
But nothing forbids you to extract the assets tree into the file system when your application is first launched, if you need that.
One approach that might work for you is to open the APK using ZipFile and ZipEntry, as this gives you access very similar to a conventional read-only directory structure.
Alternatively, you may be able to use getResourceAsStream to work with a traditional file structure - you might find this bug report useful if you go with this approach - it shows some perils of working with getResourceAsStream on android.
I should add that you shouldn't think of an APK as something gets extracted - files inside the APK are not on the filesystem, they're like resources inside a JAR file in a J2ME or J2SE environment (or the WAR/EAR for J2EE).
Hope this helps,
Phil Lello