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.
Related
I have a .NET MAUI Project with a lot of assets (images) in the Resources\Images directory that shall be deployed to the Google Play Store. This means that the size of the generated aab package is way beyond the Google Play Store limit of 150MB.
(Message: Your App Bundle contains the following configurations where the initial install would exceed the maximum size of 150 MB...)
My current solution resizes the images to <= 150MB. I now saw that there is the possibility to generate separate files for the assets, which is called Play Feature Delivery.
From this sample project I get the following gradle file to create an install-time-package:
apply plugin: 'com.android.asset-pack'
assetPack {
packName = "install_time_asset_pack" // Directory name for the asset pack
dynamicDelivery {
deliveryType = "install-time" // delivery mode
}
}
My question is: Can this somehow be done with .NET MAUI? Is it possible to add some elements to the csproj-file to do this, just like for example for the keystore:
<PropertyGroup Condition="$(TargetFramework.Contains('-android')) and '$(Configuration)' == 'Release'">
<AndroidKeyStore>True</AndroidKeyStore>
<AndroidSigningKeyStore>..\myapp.keystore</AndroidSigningKeyStore>
<AndroidSigningKeyAlias>key</AndroidSigningKeyAlias>
<AndroidSigningKeyPass>SuperSecretPassword!</AndroidSigningKeyPass>
<AndroidSigningStorePass></AndroidSigningStorePass>
</PropertyGroup>
The characteristic of the app and the users makes it impossible to load the images at runtime, e.g. via https.
tl;dr I did not find any Maui answer at this time.
The best starting point looks like XamarinComponent/Android/GoogleAndroidVending.
HOWEVER that wraps a java library, and appears to use gradle, so TBD what knowledge is required to be able to build this, then adapt it for Maui.
The corresponding Xamarin.Forms doc is APK Expansion Files.
The Xamarin.Forms nuget source code and doc is at github XamarinComponents/Android/GoogleAndroidVending.
There is a Nuget link there, but that won't work in .Net Maui.
Until there is a Maui Nuget, it will be necessary to download the source code, and modify it. (If anyone does this, would be good to upload back to github. TBD where.)
App Startup is a bit different in .Net Maui, I did not investigate what might need to change.
In addition, there might be references to Xamarin namespaces that should change to Maui equivalents.
IMPORTANT: This c# code is a wrapper for a java library from Google. The project includes gradle references. TBD what the requirements are to build this.
If your APK is getting over 150Mb then I suspect Google and Apple (if you're making an iOS app) will be expecting you to host the image data in the cloud and pull it to the device on an 'as needed' basis so you're not clogging your users' device storage up unnecessarily. That type of static imagery should be stored in cache and not backed up (so you'll need to check if it exists and re-download if necessary).
I want to migrate my android app (~40 MB of the base apk) that uses an .obb file (~70 MB) to the Android App Bundle format. I know for sure that the resources inside the .obb file will be updated less frequently than the base part. Therefore, there is no need for the users to download a full app (40 + 70 = 110 MB) on each app update but only the changed part (~40 MB).
What can I use after the migration to provide the same experience (update only changed part) to the end users?
Ideally, these unchanged resources should be accessible through the AssetManager like they are located within the assets directory.
For now, I found the Play Asset Delivery feature that allows moving some resources to a separate module to deliver it to devices at different times (install time / right after the download / when needed).
I've implemented an install time module logic and tested it via the internal + alpha tests. Throughout the testing, I found out each app update forces Google Play to download the full app (~110 MB) instead of the changed part (~40 MB). I do not know whether this situation will change when I release an app to the "available for everyone" track and I could not find the information about it either. Therefore, the answer "an install time module will not be redownloaded if unchanged; here is the documentation describing this: <link>" is fully acceptable and is one of the most welcoming ones.
tldr; Yes, in production, the download size will be smaller.
When you publish an app to production (whether APK or App Bundle), Play will generate patches of your app between this version and the previous versions of your app, so that your users only download the difference between the two versions. The consequence is that if you don't modify the content of a dynamic module, users will still receive updates for the unchanged modules but the download size will be very small.
Note that in practice, it is possible that the first couple of users downloading the update may still get the full size.
I have an Android project with 3000 photo's that needs to be available offline. When I include all the photo's in the build, the build fails. When I remove some of them, the build succeeds.
I have put the photo's in two dynamic modules that download at install time.
Here is the gradle scan for reference: https://scans.gradle.com/s/nn6eo527qvge6
Is this purely a size issue and if so, how do I get around that?
Is this purely a size issue
Probably.
how do I get around that?
Start by moving your photos out of res/drawable-xxhdpi-v4/ and into assets/ and adjust your code that consumes the photos to match.
Then, see what the resulting APK size is and compare it with the size limits for your intended app distribution channel (e.g., 100MB limit for the Play Store). If you exceed that limit, you will need to work through alternative approaches (e.g., APK expansion files).
To expand on CommonsWare's answer, I think the way you should do this is not by using Dynamic Modules but by using asset delivery. It's kinda "marketed" as a "for games" thing, but it's not limited at all by that.
The idea behind asset-delivery is that you have a pack of assets (images in your case) that you need for your app to function.
This "pack" of assets can be requested at install time, or later "on demand". All this is confusing because Dynamic Delivery sounds very similar. However, as stated at the top of the asset-delivery page, they use Different APIs.
In all honestly, I haven't used Asset Delivery, so take it with a grain of salt, and keep the considerations at hand, for example (and I quote):
If the download is larger than 150 MB and the user is not on Wi-Fi, the download does not start until the user explicitly gives their consent to proceed with the download using a mobile data connection. Similarly, if the download is large and the user loses Wi-Fi, the download is paused and explicit consent is required to proceed using a mobile data connection.
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?
I am working on an app where we are using lots of libraries to provide funtionalities like reading PDF,docx,ppt etc also we have a youtube player and many more other libraries.
Due to the design of our app, we are using lots of resources to design UI(resources is about 22 mb). We are using these images in layouts (which are lot if you ask).
I checked to see whether we can go down on using Background images, but more we strip them, our client asks for more features to integrate in the app which again increases the size to more then 50 MB (Google play limitation as mentioned here Google play expansion file setup link) .
I am looking for a solution where I can somehow remove the libraries while compiling the app to keep size under limit of 50 MB and put it in expansion file (I know this seems to be a problem, cuz I don't know how I will compile the app without those libraries) and load it on run time .
I am very confused here, Can some one help me here ??