What exactly happens when I install an android application? - android

My guess is that the contents of .apk package are extracted somewhere, and the application is registered at some directory so that the application launcher or whatever can find it. But is that all? If that is the case, is the original manifest.xml read every time the app is launched or it gets pre-processed into some other form?

Disclaimer: This answer is now 10 years old 🎉. While overall probably still accurate, details have definitely changed (ART instead of Dalvik, dynamic vs. static permissions, etc). Take it with a grain of salt!
Some basics
The .apk-file
An .apk-file is not magical at all. It's just a bundle of files which represent the content of an Android application. If you open it in a archive-tool (like 7Zip), you can browser and extract it's contents.
Android is Linux
The basic Android-System is a Linux system. Android uses a custom Linux kernel with some extra functionality on power-saving and some speed-improvements. The internal storage of an Android device is formatted with the YAFFS2-filesystem, which fully features the Linux-like access-concepts.
The used file-system might differ by manufacture or Android-Version. Newer devices often use ext3, while Samsung uses it's own file-system: RFS
This is one important aspect of the Sandbox-system, which is used by Android.
Compiling applications
What happens to the .java-files?
First, they are compiled by the normal Java compiler. After they are compiled (to .class-files), the dx-tool from the Android SDK then converts/transpiles those "normal" java-classes into Dalvik-Bytecode.
This "special" java-code is then interpreted by the DVM (Dalvik Virtual Machine), which is based on the opensource JRE-implementation Apache Harmony.
Update: In newer versions of Android, the convert/transpile step can be skipped when jack is used. This way, the .java files are directly compiled into the .dx format.
Also, since version 4.4 (KitKat) Android has the new ART runtime, which officially replaced Dalvik in Android 5 (Lollipop).
What happens to the resources i put into the /asset-directory?
Android offers the /assets-directory to add some binary raw-files (e.g. a SQLite Database). Files which are put into this directory are not compiled or optimized.
If you put your files into this directory, this is the kind of behavior you would expect from Android.
What happens to the resources i put into the /res/raw-directory?
Like the /assets-directory, you can also put binary (or other) raw-files in here (e.g. HTML-files for the Help-page). These files are compiled/optimized (if possible).
What happens to the Manifest and the other XML-files?
The Android-Manifest and also the other XML-files (Layouts, Strings, etc.) are stored and "compiled" into a binary XML-format. This is a speed-optimization.
The Sandbox
From Android OS point of view, a single Application owns:
it's own process,
it's own OS-User (like on Linux),
it's own DVM,
it's own place in the heap and
it's own place on the filesystem.
So yes, every Android app has it's own user which has the proper rights to access it's place in the internal storage (which is protected by standard Linux filesystem rights-management) and it's own DVM-process (which can't be accessed from outside of the application).
To give the application the possibility to leave the Sandbox (e.g. to connect to the Internet), the permissions declared in the Android Manifest are used.
Steps during the installation
So from the above explanations, it should be clear what happens when an Android-Application is installed:
The new user for the Application is created.
With this new users rights, the Applications directory in the internal storage is created.
The contents of the .apk-file are being extracted there.
The Android-Manifest is parsed and the declared intent-filters are registered (e.g. the android.intent.category.LAUNCHER-filter for the applications standard entry point).
Now the application is ready for it's first launch.

When you install an app, Android System copies its APK to "/data/app" folder and it named it by the package name followed by the installations number (how many times you install or update the app).
I tried to install an app manually by copying its APK and paste it in the /data/app folder and rebooted my device then it appears as an installed app and works perfectly.
Also I noticed in the link2SD app that any installed app has the folowing:
Apk located in /data/app/package-number.apk
Dex located in /data/dalvik-cache/data#app#package-number.apk#classes.dex
Lib located in /data/data/package/lib
Data located in /data/data/package
Cache located in /data/data/package/cache

Android defines an intent as "an abstract description of an operation to be performed." Not only do intents let you use activities made by others, but they are also used to launch applications. I'm sure you've seen these lines in every app you've written:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
This intent filter allows the launcher to find the starting activity of each app. Lookup "intent resolution" for more details on this process... I'd say it's more elegant than simply registering the application at some random directory.
As stated in, http://developer.android.com/guide/topics/intents/intents-filters.html, "Android system populates the application launcher, the top-level screen that shows the applications that are available for the user to launch, by finding all the activities with intent filters that specify the "android.intent.action.MAIN" action and "android.intent.category.LAUNCHER" category. It then displays the icons and labels of those activities in the launcher"

Related

How to install two versions of the same Android app on one (rooted) device?

Is it possible to install two instances of the same app on a rooted Android device?
I know, that the Android system distinguishes apps based on their package name.
It is possible to decompile apps with tools like apktool, change the Manifest file and recompile / sign them. However, for more sophisticated applications (e.g., if they have multiple apk files packed in a apkx file) or complex dependencies this not always works.
I do not want to work with third party applications like Dual Space, Titanium Backup and so on.
How would you approach this?
A few options:
Use lucky patcher's "clone" function in the tools menu (shouldn't be hard to find)
Copy the app apk out of system memory and edit it manually (good luck, text file "readers" read it fine, editors do not)
Use an apk editor to change the package name (I have a copy of one if necessary)

Android App Injection

Is it possible to inject an app into another after installation process?
Consider the following example:
Device D is rooted and Android version is >= 5, means it's using ART.
App A gets installed via "adb install App_A.apk". At first startup dex2oat gets called and creates the .oat file for app A. My goal is now to inject App B into App A so that App B gets started instead of App A. For another reason, the .oat file of App B gets "crosscompiled" for the device D. What parts of App A now need to get exchanged by App B to get it to work?
I guess the following steps are necessary, still the app crashes when I am trying to start it:
use the same package name "com.example.app"
use the same application name
Exchange AndroidManifest.xml
Exchange/Add res and lib folders and resources.arsc
Exchange the .oat file
Use the same key for signing the final apk (in /data/app/App_A/base.apk) after exchanging the parts above
For my understanding, "classes.dex" should not be needed, because the oat file is already present. So in theory, it should also work with a broken classes.dex?
What am I missing here? I also tried to monitor what Android does when starting an app (which files are touched and so on) but could not get behind the scenes really :(
I would apreciate every kind of help. Thanks a lot!
Regards

Where application icons are stored in an Android device?

Just out of curiosity, I wanted to know where on the file system of an Android device the application icons are stored.
Like I have shortcuts to various applications on the homescreen of my device, where those icons files (or images) are stored. Is it only inside the application package (.apk) or Android stores it some where else?
If it is in application package only does Android loads all the imagess from each of the apk and loads it when it is started for the first time?
When an app file is installed, the .apk file is analyzed and various items of information are extracted by the launcher. (This process does not involve loading and running the app itself.) Among these items is the app icon, which the launcher typically caches in its own private area. Exactly how this is done depends on the launcher currently active on your device. You might be able to browse through the source for your launcher to find out more details about how it caches these items extracted from the app .apk files, but I'm not sure what practical use there would be to that exercise.
The launcher's use of its own cache greatly speeds up start-up, as otherwise every installed app would have to be scanned at every reboot to extract the requisite information for the launcher to show itself. However, the cache is the source of occasional problems, such as the icon not updating right away when an updated app (with a new icon and possibly a new app name) is installed. (See, for example, this thread and this one.)
Think about what happens when you create your own app. Typically, you create icons for your app for all drawable resource buckets (or at least the ones you want to support). Then these files get packaged with AAPT into the apk with the rest of your project. Then after installing your app, the OS will pick the icon that matches your phone configuration and create a shortcut on your installed apps page.

Split Android app in two parts

I'm trying to understand if it is possible to split an Android App into two parts (installed from one APK). I looking into this to install one part on the Device memory and the other part on the SD-CARD. The two parts belong together and should not be installed separately.
Note: I need to separate not only resources, but also activities, so APK Expansion Files not a solution, because not provide such functionality.
I think it will be possible. Can you try following approach?
Create two apps
In the Manifest file of first APK, you should have an Activity that is of MAIN and LAUNCHER category. This way your app will be visible in the Launcher list
You should not have any Activity of MAIN and LAUNCHER category in 2nd APK, but you know which Activity you have to open as Launcher Activity of second app as it's your own app. This way your second app will never show up in Launcher list of apps
Put 2nd APK in assets folder of first APK
Whenever your main app wants to use contents from 2nd app, install 2nd app from assets folder (as mentioned here) with setting the install location on SDCard like this: android:installLocation="preferExternal" and then launch your desired activity of second app
I've not tried this yet but theoretically seems legit.
Let me know if this works. Thanks!
APK Expansion Files
Google Play currently requires that your APK file be no more than 100MB. For most applications, this is plenty of space for all the application's code and assets. However, some apps need more space for high-fidelity graphics, media files, or other large assets. Previously, if your app exceeded 100MB, you had to host and download the additional resources yourself when the user opens the app. Hosting and serving the extra files can be costly, and the user experience is often less than ideal. To make this process easier for you and more pleasant for users, Google Play allows you to attach two large expansion files that supplement your APK.
Google Play hosts the expansion files for your application and serves them to the device at no cost to you. The expansion files are saved to the device's shared storage location (the SD card or USB-mountable partition; also known as the "external" storage) where your app can access them. On most devices, Google Play downloads the expansion file(s) at the same time it downloads the APK, so your application has everything it needs when the user opens it for the first time. In some cases, however, your application must download the files from Google Play when your application starts.
Downloading the Expansion Files
In most cases, Google Play downloads and saves your expansion files to the device at the same time it installs or updates the APK. This way, the expansion files are available when your application launches for the first time. However, in some cases your app must download the expansion files itself by requesting them from a URL provided to you in a response from Google Play's Application Licensing service.
The basic logic you need to download your expansion files is the following:
When your application starts, look for the expansion files on the shared storage location (in the Android/obb// directory).
If the expansion files are there, you're all set and your application can continue.
If the expansion files are not there:
Perform a request using Google Play's Application Licensing to get your app's expansion file names, sizes, and URLs.
Use the URLs provided by Google Play to download the expansion files and save the expansion files. You must save the files to the shared storage location (Android/obb//) and use the exact file name provided by Google Play's response.
Source
Your app could just check wether the sd card is currently available ("plugged-in") or not. If it is available your app works like normal and if the sd card is not available the app would automatically quit / show a pop-up / launch different activities / whatever.
Yeah, it's possible. But with a caveat, it would be possible to install both apps separately, since both of them should be uploaded to the store. You just need to use a lot of intents.
You'll need to handle all communications between both apps using intents. That means, everything the first app needs must be asked using an intent to the second app, and failing to find the other app within the device should trigger an intent to the play store. This way, you'll have two apps working like one. Keep in mind, the user is still going to determine where to install your app, but as christian-strempfer pointed, the SD card can be set as the preferred target.
If the purpose of this is saving space, you should make your resources (images, sounds, etc) dynamic. Since all of those are just files inside the apk, you could easily replace them with files from the SD-Card. You just need to upload them somewhere and download them after the app is installed. That way, you could provide the exact versions of each asset and remove them when you need. You could learn which screens are most used and remove the assets for the ones you use less. Etc.
You can, but not for your reason. Multiple APKs are just to ensure your app works for multiple devices - not to divide up its total size between internal memory and SD card.
Multiple APK Support
Although we encourage you to develop and publish a single APK that
supports as many device configurations as possible, doing so is
sometimes not possible. To help you publish your application for as
many devices as possible, Google Play allows you to publish multiple
APKs under the same application listing. Google Play then supplies
each APK to the appropriate devices based on configuration support
you've declared in the manifest file of each APK.
By publishing your application with multiple APKs, you can:
Support different OpenGL texture compression formats with each APK.
Support different screen configurations with each APK.
Support different platform versions with each APK.
Currently, these are the only device characteristics that Google Play
supports for publishing multiple APKs as the same application.
Maybe is this what you want?
APK Expansion Files
If you're just looking for a way to keep application resources on the external drive, Harry's answer will be useful.
Otherwise it's not possible to split one app installation into two parts. You can use the android:installLocation manifest attribute to define where you want to install it and you can even force it to only install internally on the device, but there is no option to split it.
Alternatives
Two Apps
You create two separate two apps and check on start of any of them, if the other one is installed. If not, you ask the user to install the other one and forward the user to the app store.
One app checks the external storage
I don't know your use case, but from your comments it sounds like you're looking for the wrong solution.
The application I'm thinking about has one part that I want always to be available (install on device memory) and one part that the user may make unavailable (temporary) by removing the SD-CARD. Also when the user decides to move the app to or from the SD-CARD, the part that I want installed in device memory should always stay there.
You can just check if the external storage is available and block certain activties if it's not. If you want to make sure, it's the same SD card you can create a UUID on first run and save it both internally and externally. If they match it's the correct SD card.
Conclusion
Your solution probably is too complicated and you should look for alternatives.
You can create two different launching activities from one APK by defining two MAIN LAUNCHER entries in Manifest.xml
<activity android:name=".ChooserActivity"
android:label="Auth Firebase">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".GoogleSignInActivity"
android:label="Auth Google"
android:installLocation="preferExternal">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
this will create two entry points for an app, two different launcher icons one named "Auth Firebase" and other named "Auth Google" both will open different activities.

Android SDK - Open any file I want?

According to the Android Development Documentation, you can't just open any file you want ("Open a private file associated with this Context's application package for writing.").
What, however, when I want my application to read files created by other applications? Let's say I have a file in /data/app_1/hello.txt, but my application has nothing to do with it because my app is called app_2, how would I still be able to open this file (and write back to it)?
You can't in general, Applications on Android are isolated and sparated. A application can only write and read its own files.
There are exceptions: As the documentation states: "It's possible to arrange for two applications to share the same Linux user ID, in which case they are able to access each other's files. To conserve system resources, applications with the same user ID can also arrange to run in the same Linux process and share the same VM (the applications must also be signed with the same certificate)."
Another possiblity is that the files are created as "world readable" so that every application can read it.
So to summarize and come back to your question: If you can not modify "my_app_1" then it is impossible. Of you can modify both applications choose one of the solutions above.
Two options:
If you are designing both applications and want to share the file, keep it somewhere else (for example - external storage) or make it world readable.
If you are trying to read another app's file - well, you shouldn't, that's a key element in the android security architecture.

Categories

Resources