I am using vitamio framework to play audio on android.
The framework consists of a library file libarm.so The file is very big (5M), which makes my apk very big.
I delete file and compile my app, and still running fine.
I am wondering is it safe to just delete the file?
It contains some CPU-specific highly-optimized code that is used to improve the performance of some operations, like decoding of certain types of multimedia streams (ffmpeg uses it and I'm not sure if something else does too).
The library is actually a 7zipped pack of several libraries, built for different ARM architectures (ARMv6, ARMv7, etc.), thus its size.
These libraries are extracted to your device the first time you run your app. If you remove them and run your app successfully, it is most likely because they have already been extracted. Clear you app data, and try it again.
If the app doesn't crash when you delete it (and have cleared your app data), it means that you're just not using code that utilizes libarm.so APIs, so, unless you plan to add more multimedia support to your app, it is safe to leave the library out of it.
Related
i just exported my game to use Play Asset delivery following this guide:
https://docs.unity3d.com/2021.1/Documentation/Manual/play-asset-delivery.html
in short
build app bundle enabled
split application binary also checked.
The exported aab size is 311mb and when uploading to google play it says:
base ----install_time ---30.1mb
UnityDataAssetPack ----install time ---264mb
But then when i download the app in any device, the file size is 846mb, more than double the expected size. Also it tries to download all at once, i thought that the dataassetpack was downloaded after the base one.
i'm using Unity 2021.1.16f1
Do you know any cause for this to happen, and how to fix it?
thank you very much!
You are comparing a "download size" to a "size on disk":
The size you see in the Play Console corresponds to the download size, which is compressed.
On the device, you see the size on disk where the data is stored uncompressed so it can be directly rendered without having to keep two copies of the same data (one compressed and one uncompressed), so that explains the discrepancy.
It seems that you have configured the modules to be install-time so they will be installed as part of the initial install. If you want them to be installed while the user is starting the game, you should configure them to be fast-follow. If you want to manually download them using the Play Core API, you should configure them to be on-demand. This is all explained in the page you linked in the Managing asset packs at runtime section.
That page also links to the Google documentation on the topic, which has a dedicated section for Unity -- which would be too long to copy here, so have a read and come back if you have more specific questions.
If you're only using Unity marking the AAB output type in the build settings, and not using Google's API to do your stuff via script, then it's correct. Unity has a bug when assembling bundles and will simply (at least) double the size of your app. Things will be doubled in your AAB, you'll see the stuff you had in streaming assets in split apks and also inside the base.apk. Unity's way is not reliable, it's quite wrong and Google's plain way for Unity also is not perfect, it will not work for every single project. I was able to get the hang of it, but in the end I wrote our own tool to create the asset packs, created our runtime implementation to use the API and also our build procedures to be called by our custom build class.
My suggestion is, squeeze the docs here https://developer.android.com/guide/playcore/asset-delivery/integrate-unity?language=api and build your custom solution.
Is it possible to split my Android apk of 512MB into different parts or modules.
Compile small part of it into a release Apk (small Apk size) for Play Store.
Then fetch the remaining parts or modules from online or your own server during first time install on a device.
Thats:
Small Apk to Google Play Store
Fetch remaining big files after first install.
I am using Android Studio.
Of course you can, that can be easily achieved if you got to split heavy resources(like images, videos, databases). Here you must write some logic which will download that resources and will work with them after a successful download.
I cant imagine a situation when you must to split a code in a separate module, compiled code is light and dont increase apk size so much as another resources. Code can become heavy when there is a lot of code from libraries, in that case I suggest you to learn about Proguard Shrink.
Also you can learn why in android is not possible to load java modules in runtime. On of the reasons is performance given by JIT
Here a is workaround with ndk How do I import shared object libraries at runtime in Android?
The short summary is: How do I build an APK and separate libraries (by which I mean sets of classes (and ideally, resources too) in some form, such as JAR, AAR or DEX files), but not include those libraries in the APK; instead, the app loads them at run time?
Detail
So my main question is how to build such an app (e.g. Gradle configuration). How do I specify which classes go into which JAR or DEX files? Do I create an Android Studio module for each DEX file I want to end up with?
A closely related question is how the Java code should then load the external libraries and access their classes at run time. For the latter, I'm hopeful that the approach shown at accessing to classes of app from dex file by classloader would work.
I've tried the instructions at https://developer.android.com/studio/projects/android-library.html, but that builds an APK that does include the dependency library.
I've also tried Multidex (https://developer.android.com/studio/build/multidex.html), but that doesn't seem to leave the developer any control over which classes go in which DEX file, and furthermore, packages them all into a single APK. AFAICT there is no way to control the loading of these DEX files at run time.
Background
There's a possibility of the "X-Y problem" here, so I'd better explain the background.
I'm building an app for a client. It's not going to be distributed through an app store, so it won't have access to the normal mechanism for updates. Instead, the client wants the app to be able to update itself by downloading new components of itself to replace the old components, without a need to manually sideload a new APK. The primary motive here is that the updates have to be easy for non-technical users. If the app can control the update process, it can make it smooth and guide the user.
Moreover, the app will be used in areas where internet access is scarce and expensive, so the client wants to be able to issue app updates in smaller chunks (e.g. 2MB) rather than forcing the user to re-download the whole app to receive a small update.
One aspect of the requirements I should mention, in case it matters, is that the libraries to be loaded at run time are supposed to live on a microSD card. This can also help with distribution of updates without internet access.
The current status of the app is that it's about 50% written: That is, a couple of earlier versions have been released, but the app now needs to be modified (restructured) to meet the above requirements, as well as others.
This tutorial is a good start for external loading of DEX files.
Only three small files of source (MainActivity.java, LibraryInterface.java, LibraryProvider.java) and it copies secondary_dex.jar from the assets folder, into internal application storage [outdex/dex] (the internet is also stated as possible in the tutorial).
You have to build it with ant, because it uses custom build steps.
I tried it, it works fine. Worth a look.
custom class loading in Dalvik and ART
UPDATE
this code has been ported to Android Studio gradle (no need for ant).
https://github.com/timrae/custom-class-loader
Tested ok. Copies com.example.toastlib.jar from the SDcard into internal application storage [outdex/dex],(not assets folder).
( you must read the README.md file in the project to build it).
Q: How do I add an Activity, I cannot add it to the manifest ? A: Use
Fragments, they don't need entries in the manifest.
Q: A Jar with resources that is meant to be added to an existing
project needs to be able to merge its resources with the project's
own resources (R.). A: Hacks are available, Data file...Packaging Android resource files within a distributable Jar file
Q: The external file has wrong permissions. A: Import it.
Q: I need to add uses-permission. A: Use API23 you can programmatically add uses-permissions (but they still need to be declared in the Manifest, so the new permissions model is probably not much use to us).
This section is for more general users (#LarsH has more specific requirements about updates), The example above is 17kb apk and 1 kb jar. You could put the bulk of you code in the one-off jar, and updates would involve just loading an new Apk (and then importing the bulk code jar, to minimise the data transfer).
When the Apk gets too big, start again with a small Apk and everything migrated to another jar (import 2 jar's). You need to balance coding effort, user experience, maintainability, supportability, bandwidth, android rules, play store rules (if these words even exist ;O)).
NOTE Dalvik is discontinued
The successor of Dalvik is Android Runtime (ART), which uses the same bytecode and .dex files (but not .odex files), with the succession aiming at performance improvements transparent to the end users. The new runtime environment was included for the first time in Android 4.4 "KitKat" as a technology preview, and replaced Dalvik entirely in later versions; Android 5.0 "Lollipop" is the first version in which ART is the only included runtime.
You could try to build multiple apk's with the same sharedUserId and the same process.
This is the plugin mechanism used by Threema
Edit: More about Theema
Threema has one main app and two plugins:
main app: https://play.google.com/store/apps/details?id=ch.threema.app
QR-Code Plugin: https://play.google.com/store/apps/details?id=ch.threema.qrscannerplugin
Voicemessage Plugin: https://play.google.com/store/apps/details?id=ch.threema.voicemessageplugin
Doing so the main app does not need the permissions for accessing the camera or microphone
Has anyone tried using market apk expansion downloader library (available as an add-on) for downloading large files on android <= 2.2? The source code is a bit difficult to understand and I was not able to figure out how it can be used for downloading any large files in general. Are there any alternatives for downloading large files on lower android devices(apart from writing my own DownloadService which I wouldn't prefer doing if there is something already available).
I have not tried to use it but the docs do state the the expansion downloader library is compatibile with API Level 4, taken from the docs:
Note: By default, the Downloader Library requires API level 4, but the
APK Expansion Zip Library requires API level 5.
I completely agree that the source code is difficult to follow, however it was designed in such a way to be fault tolerant to network issues.
I think you can take the sample and roll with that, however I found it was very difficult to test.
We ended up going with our own in the end (using an Arbitrary server) to host the downloads.
I do not believe there are any alternatives, however the downloader library does have a few gems. For instance the Expansion Zip Library can be used independently of the Downloader Library and is a great way to read content directly from the zip.
The only challenge would be writing your own downloader service and performing a CRC check.
Seems like API 4 or >
The expansion API is used for "permanent" file extensions to your application, they don't want you to move them or delete them or even unpack them etc. but use them in place, it's unclear what would happen if you did but I suspect a lot of odd side effects.
You also don't have direct control of when this file is downloaded, it has to be associated in the market and then it happens automatically unless for some reason it "fails" in which case when your app starts you are expect to initiate the process manually and then you need to use the Download Libary, else it's automagic as my 3 year old says.
From your post you may be looking for a way to get large files (more than one) and do what you want with them, if so this is not a good method to do that since every time you add a new file via the market it would tell your users you have an updated version and overwrite the older file (though you can use the patch extension to avoid that if you are updating the original but that only moves it back one step)
All of that is here what expansions files are for and how to use them
If you just want a method to get large files using your own server take a look at the support package and specifically the loader and loader manager. They also say they are making source code to the extension library downloader and zip file manager available but I haven't bothered to check that yet.
I'm porting a rather large game engine written in C++ from Windows/Mac to Android. There is a lot of pre-existing code to read assets for games. In addition, there is quite a bit of code doing file system calls (stat'ing the files to make sure they exist, looking up all of the files and directories inside of a directory, etc.)
Right now, I'm focusing on just getting something up and running as quickly as possible, so I'd prefer not to have to rewrite a lot of this. What would be a good way of getting our game assets onto the device and accessing them with minimal changes to our existing standard C++ file system API usage?
I've got some basic support implemented already using the Asset Manager API, but that doesn't support the file system calls and I'm concerned that the 1 MB asset size limit is going to bite me at some point.
I've also looked at OBB, but the tools for creating an OBB file don't look like they are part of the current SDK/NDK. Otherwise, that looks like it would be perfect.
Is it a horrible idea to package up all of the files and just extract them on the SD Card the first time the app is run? Or is there some better way of dealing with this?
Update: I'm also not very concerned on being able to run on a broad range of devices, I am specifically looking at newish tablets, probably the 10.1" Samsung Galaxy tab.
We ran into a similar problem in developing our (data-file-heavy) app, and we ended up deciding to keep the APK tiny and simply download our data files on first run; they're going to have to be downloaded either way, but a small APK works much better on older devices without a lot of internal storage. Plus, you can potentially rig up a way for people to copy over the files directly from their computer if they have a limited data plan or a slow internet connection on their phone.
The "Downloader" sample app in apps-for-android (confusingly buried under "Samples") is almost a fully-implemented solution for this - you can pretty much just plug in the particulars of your data files and let it do the rest.
I wrote an app that relies on putting a good amount of native code into the Android filesystem. I did this by packaging the files into the APK as 'resources'. Instead of pushing them to the SD card, you can put then into the application's private namespace, I.E. /data/data/com.yourdomain.yourapp/nativeFolder.
For details on how to accomplish this, you can see my answer to this question.
It's fairly simple to package to just unpack them on the first run and never worry about them again. Also, since they're under the application's namespace, they should be deleted if/when someone were to decide to delete your app.
EDIT:
This method can be used to put anything into the app's private area; /data/data/com.yourdomain.yourapp/
However, as far as I know, your application has to be the one to create all the folders and sub-folders in this area. Luckily this is fairly easy to do. For example to have your app make a folder:
Process mkdir = Runtime.getRuntime().exec("mkdir " +localPath);
That works as it would in most linux shells. I walked through the assets folder I packaged into my APK, made the corresponding directories and copied all the native files to those directories.
What you might be more concerned with is the limited Android shell. There are many commands that you might want that aren't present. stat for example isn't available, so all of this may be moot if your native code can't make it's system calls.