-
Notifications
You must be signed in to change notification settings - Fork 533
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AssetPack Support #8631
AssetPack Support #8631
Conversation
804967b
to
cc43575
Compare
7a2d771
to
207ed62
Compare
We should add support for doing this.
or have some way to "unset" the value. The reasoning is that you might have ALLOT of assets you want to include in an default "installtime" pack. But only select a few which will end up in the main pack. |
This looks great. We use the hack mentioned to make a InstallTime asset pack. This could replace that hack for us. |
37b5171
to
f900a76
Compare
b0f5393
to
8e0d89b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall my comments are pretty minimal, LGTM. 👍
src/Xamarin.Android.Build.Tasks/Tasks/CreateDynamicFeatureManifest.cs
Outdated
Show resolved
Hide resolved
1d5c2e1
to
7d5ec40
Compare
b4bc565
to
64aaa35
Compare
b293abb
to
7118e7c
Compare
src/Xamarin.Android.Build.Tasks/Tasks/CreateDynamicFeatureManifest.cs
Outdated
Show resolved
Hide resolved
case "AssetPack": | ||
GenerateAssetPackManifest (doc); | ||
break; | ||
default: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be a case "featurepack"
here as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At some point I hope there will be a feture pack, we have a number of hoops to go through to get that working. But its just not supported yet.
@dellis1972: are there any constraints on asset pack names / the value of |
Probably the same rules as an apk I guess. |
testing locally, and tried: <AndroidAsset Update="Assets\movie-install.mp4" AssetPack="install-movies" DeliveryType="InstallTime" /> It errors out:
|
Draft commit message: Context: https://github.com/xamarin/xamarin-android/issues/4810
Google Android began supporting splitting up the app package into
multiple "packs" with the introduction of the `aab` package format.
Each "pack" can be downloaded to the device either at install time or
on-demand. This allows application developers to save space and
install time by only installing the required parts of the app
initially, then installing other packs as required.
There are two types of packs: Feature packs and Asset packs.
*Feature* pack contains *non-native* Java code and other resources.
Java code in feature packs can be launched via
`Context.StartActivity()`. Currently, .NET Android cannot support
Feature packs, as Feature packs cannot contain native code.
*Asset* packs contain *only* `@(AndroidAsset)`s. They *cannot* contain
any code or other resources. This type of pack can be installed at
install-time, fast-follow, or ondemand. It is most useful for apps
which contain a lot of Assets, such as Games or Multi Media applications.
Consider a default Android app with an asset:
% dotnet new android
% mkdir Assets
% touch Assets/movie1.mp4
% dotnet build -c Release
% unzip -l bin/Release/net9.0-android/*-Signed.aab | grep -Ei 'asset|movie'
0 01-01-2010 00:00 base/assets/movie1.mp4
…
12 01-01-2010 00:00 base/assets.pb
Note that assets are listed within the `.aab`, within the
`base/assets` directory.
Add support for the following metadata items:
* `%(AndroidAsset.AssetPack)`: the *name* of the asset pack that
should contain the asset.
* `%(AndroidAsset.DeliveryType)`: How the named asset pack should
be installed.
When `%(AndroidAsset.AssetPack)` is specified, the asset is placed into
a different directory within the `.aab` file. For example, add
additional assets:
% touch Assets/movie-install.mp4
% touch Assets/movie-follow.mp4
% touch Assets/movie-demand.mp4
Then update the `.csproj` to specify `%(AssetPack)` and
`%(DeliveryType)`:
<ItemGroup>
<AndroidAsset Update="Assets\movie-install.mp4" AssetPack="install_movies" DeliveryType="InstallTime" />
<AndroidAsset Update="Assets\movie-follow.mp4" AssetPack="follow_movies" DeliveryType="FastFollow" />
<AndroidAsset Update="Assets\movie-demand.mp4" AssetPack="demand_movies" DeliveryType="OnDemand" />
</ItemGroup>
Now we see:
% dotnet build -c Release
% unzip -l bin/Release/net9.0-android/*-Signed.aab | grep -Ei 'asset|movie'
0 01-01-2010 00:00 base/assets/movie1.mp4
12 01-01-2010 00:00 base/assets.pb
0 01-01-2010 00:00 demand_movies/assets/movie-demand.mp4
644 01-01-2010 00:00 demand_movies/manifest/AndroidManifest.xml
12 01-01-2010 00:00 demand_movies/assets.pb
0 01-01-2010 00:00 follow_movies/assets/movie-follow.mp4
646 01-01-2010 00:00 follow_movies/manifest/AndroidManifest.xml
12 01-01-2010 00:00 follow_movies/assets.pb
0 01-01-2010 00:00 install_movies/assets/movie-install.mp4
648 01-01-2010 00:00 install_movies/manifest/AndroidManifest.xml
12 01-01-2010 00:00 install_movies/assets.pb
The `AndroidManifest.xml` files tell the Google Play Store how they
asset packs should be deployed. |
* main: [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631)
* main: [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478) Localized file check-in by OneLocBuild Task (#8813) [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631) [runtime] Remove the last vestiges of desktop builds (#8810) [ci] Don't auto-retry APK test suites. (#8811) [Microsoft.Android.Templates] Update EN l10n template strings (#8808) Bump to xamarin/Java.Interop/main@651de42 (#8809)
* main: LEGO: Merge pull request 8818 Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817) Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816) [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795) Localized file check-in by OneLocBuild Task (#8815) [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478) Localized file check-in by OneLocBuild Task (#8813) [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631)
* main: LEGO: Merge pull request 8818 Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817) Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816) [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795) Localized file check-in by OneLocBuild Task (#8815) [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478) Localized file check-in by OneLocBuild Task (#8813) [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631) [runtime] Remove the last vestiges of desktop builds (#8810) [ci] Don't auto-retry APK test suites. (#8811) [Microsoft.Android.Templates] Update EN l10n template strings (#8808) Bump to xamarin/Java.Interop/main@651de42 (#8809) [Mono.Android] is now "trimming safe" (#8778) [Mono.Android] Fix missing enum issues that cause BG8800 warnings. (#8707) Bump external/Java.Interop from `3436a30` to `5bca8ad` (#8803) Bump to xamarin/monodroid@77124dc1 (#8804) Bump to dotnet/installer@e911f5c82c 9.0.100-preview.3.24161.2 (#8802) Bump to xamarin/Java.Interop/main@3436a30 (#8799) [templates] Remove redundant "template" from display name. (#8773)
* main: LEGO: Merge pull request 8818 Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817) Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816) [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795) Localized file check-in by OneLocBuild Task (#8815) [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478) Localized file check-in by OneLocBuild Task (#8813) [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631) [runtime] Remove the last vestiges of desktop builds (#8810) [ci] Don't auto-retry APK test suites. (#8811) [Microsoft.Android.Templates] Update EN l10n template strings (#8808) Bump to xamarin/Java.Interop/main@651de42 (#8809) [Mono.Android] is now "trimming safe" (#8778) [Mono.Android] Fix missing enum issues that cause BG8800 warnings. (#8707) Bump external/Java.Interop from `3436a30` to `5bca8ad` (#8803) Bump to xamarin/monodroid@77124dc1 (#8804) Bump to dotnet/installer@e911f5c82c 9.0.100-preview.3.24161.2 (#8802) Bump to xamarin/Java.Interop/main@3436a30 (#8799)
* main: LEGO: Merge pull request 8818 Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817) Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816) [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795) Localized file check-in by OneLocBuild Task (#8815) [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478) Localized file check-in by OneLocBuild Task (#8813) [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631)
* main: (99 commits) LEGO: Merge pull request 8818 Bump to dotnet/installer@b40c44502d 9.0.100-preview.3.24165.20 (#8817) Bump com.android.tools:r8 from 8.2.47 to 8.3.37 (#8816) [Mono.Android] Prevent NullPointerException in TranslateStackTrace (#8795) Localized file check-in by OneLocBuild Task (#8815) [Xamarin.Android.Build.Tasks] Make all assemblies RID-specific (#8478) Localized file check-in by OneLocBuild Task (#8813) [Xamarin.Android.Build.Tasks] %(AndroidAsset.AssetPack) Support (#8631) [runtime] Remove the last vestiges of desktop builds (#8810) [ci] Don't auto-retry APK test suites. (#8811) [Microsoft.Android.Templates] Update EN l10n template strings (#8808) Bump to xamarin/Java.Interop/main@651de42 (#8809) [Mono.Android] is now "trimming safe" (#8778) [Mono.Android] Fix missing enum issues that cause BG8800 warnings. (#8707) Bump external/Java.Interop from `3436a30` to `5bca8ad` (#8803) Bump to xamarin/monodroid@77124dc1 (#8804) Bump to dotnet/installer@e911f5c82c 9.0.100-preview.3.24161.2 (#8802) Bump to xamarin/Java.Interop/main@3436a30 (#8799) [templates] Remove redundant "template" from display name. (#8773) Bump to xamarin/Java.Interop/main@a7e09b7 (#8793) ...
Context #4810
Google Android began supporting splitting up the app package into multiple
packs with the introduction of the
aab
package format. This format allowsthe developer to split the app up into multiple
packs
. Eachpack
can bedownloaded to the device either at install time or on demand. This allows
application developers to save space and install time by only installing
the required parts of the app initially. Then installing other
packs
as required.
There are two types of
pack
. The first is aFeature
pack, this typeof pack contains code and other resources. Code in these types of
pack
can be launched via the
StartActivity
API call. At this time due tovarious constraints .NET Android cannot support
Feature
packs.The second type of
pack
is theAsset
pack. This type of pack ONLYcontains
AndroidAsset
items. It CANNOT contain any code or otherresources. This type of
feature
pack can be installed at install-time,fast-follow or ondemand. It is most useful for apps which contain allot
of
Assets
, such as Games or Multi Media applications.See the documentation for details on how this all works.
.NET Android does not have any official support for this type of pack.
However a hack is available via the excellent @infinitespace-studios on
github.
This hack allows developers to place additional assets in a special
NoTargets
project. This project is built just after the finalaab
isproduced. It builds a zip file which is then added to the
@(AndroidAppBundleModules)
ItemGroup in the main application. This zip is then included into the
final app as an additional feature.
Asset Pack Specification
We want to provide our users the ability to use
Asset
packs withouthaving to implement the hack provided by @infinitespace-studios. Using
a separate project like in the hack is one way to go. It does have some
issues though.
special
type of project. It requires aglobal.json
which imports theNoTargets
sdk.Having the user go through a number of hoops to implement this for
.NET Android or .net Maui is not ideal. We need a simpler method.
The new idea is to make use of additional metadata on
AndroidAsset
Items to allow the build system to split up the assets into packs
automatically. So it is proposed that we implement support for something
like this
In this case the additional
AssetPack
attribute is used to tell thebuild system which pack to place this asset in. Since auto import of items
is common now we need a way for a user to add this additional attribute
to auto included items. Fortunately we are able to use the following.
This code uses the
Update
attribute to tell MSBuild that we are goingto update a specific item. Note in the sample we do NOT need to include
an
Update
for thedata.xml
, since this is auto imported it will stillend up in the main feature in the aab.
Additional attributes can be used to control what type of asset pack is
produced. The only extra one supported at this time is
DeliveryType
,this can have a value of
InstallTime
,FastFollow
orOnDemand
.Additional attributes do not need to be included on ALL items. Any one
will do, only the
AssetPack
attribute will be needed.See Google's documentation for details on what each item does.
If the
AssetPack
attribute is not present, the default behavior willbe to include the asset in the main application package.
If however you have a large number of assets it might be more efficient to make use of the
base
asset pack setting. In this scenario you update ALL assets to be in a single asset pack then use theAssetPack="base"
metadata to declare which specific assets end up in the base aab file. With this you can use wildcards to move most assets into the asset pack.In this example,
movie.mp4
andsome.png
will end up in thebase
aab file, but ALL the other assetswill end up in the
assets1
asset pack.Implementation Details
There are a few changes we need to make in order to support this feature.
One of the issues we will hit is the build times when dealing with large assets.
Current the assets which are to be included in the
aab
are COPIEDinto the
$(IntermediateOutputPath)assets
directory. This folder isthen passed to
aapt2
for the build process.The new system adds a new directory
$(IntermediateOutputPath)assetpacks
.This directory would contain a subdirectory for each
pack
that theuser wants to include.
All the building of the
pack
zip file would take place in these subfolders.The name of the pack will be based on the main "packagename" with the asset pack
name appended to the end. e.g
com.microsoft.assetpacksample.assets1
.During the build process we identify ALL the
AndroidAsset
items whichdefine an
AssetPack
attribute. These files are then copied to thenew
$(IntermediateOutputPath)assetpacks
directory rather than theexisting
$(IntermediateOutputPath)assets
directory. This allows us tocontinue to support the normal
AndroidAsset
behavior while adding thenew system.
Once we have collected and copied all the assets we then use the new
GetAssetPacks
Task to figure out which asset packs we need to create.We then call the
CreateDynamicFeatureManifest
to create a requiredAndroidManifest.xml
file for the asset pack. This file will endup in the same
$(IntermediateOutputPath)assetpacks
directory.We call this Task
CreateDynamicFeatureManifest
because it can be usedto create any feature pack if and when we get to implement full feature
packs.
We can then call
aapt2
to build these packs into.zip
files. A newtask
Aapt2LinkAssetPack
takes care of this. This is a special versionof
Aapt2Link
which implements linking for asset packs only.It also takes care of a few problems which
aapt2
introduces. For somereason the zip file that is created has the
AndroidManifest.xml
filein the wrong place. It creates it in the root of the zip file, but the
bundletool
expects it to be in amanifest
directory.bundletool
will error out if its not in the right place.So
Aapt2LinkAssetPack
takes care of this for us. It also removes aresources.pb
which gets added. Again,bundletool
will error if thisfile is in the zip file.
Once the zip files have been created they are then added to the
AndroidAppBundleModules
ItemGroup. This will ensure that when thefinal
.aab
file is generated they are included as asset packs.