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)
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
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.
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.
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.