SDL: support for install-time asset pack for Android app bundle

This commit is contained in:
Sergii Pylypenko
2021-06-07 00:20:09 +03:00
parent 211ab6b8be
commit 077acc6880
14 changed files with 153 additions and 31 deletions

1
.gitignore vendored
View File

@@ -23,3 +23,4 @@
/project/app/build.gradle
/project/app/.gradle
/project/app/build
/project/assetpack/build

View File

@@ -166,7 +166,7 @@ echo >> AndroidAppSettings.cfg
echo "# Application user-visible version name (string)" >> AndroidAppSettings.cfg
echo AppVersionName=\"$AppVersionName\" >> AndroidAppSettings.cfg
echo >> AndroidAppSettings.cfg
echo "# Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...'" >> AndroidAppSettings.cfg
echo "# Specify path to download application data in zip archive in the form \"Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...\"" >> AndroidAppSettings.cfg
echo "# If you'll start Description with '!' symbol it will be enabled by default, '!!' will also hide the entry from the menu, so it cannot be disabled" >> AndroidAppSettings.cfg
echo "# If the URL in in the form ':dir/file.dat:http://URL/' it will be downloaded as binary BLOB to the application dir and not unzipped" >> AndroidAppSettings.cfg
echo "# If the URL does not contain 'http://' or 'https://', it is treated as file from 'project/jni/application/src/AndroidData' dir -" >> AndroidAppSettings.cfg
@@ -174,6 +174,14 @@ echo "# these files are put inside .apk package by the build system" >> AndroidA
echo "# You can specify Google Play expansion files in the form 'obb:main.12345' or 'obb:patch.12345' where 12345 is the app version for the obb file" >> AndroidAppSettings.cfg
echo "# You can mount expansion files created with jobb tool if you put 'mnt:main.12345' or 'mnt:patch.12345'" >> AndroidAppSettings.cfg
echo "# The mount directory will be returned by calling getenv(\"ANDROID_OBB_MOUNT_DIR\")" >> AndroidAppSettings.cfg
echo "# Android app bundles do not support .obb files, they use asset packs instead." >> AndroidAppSettings.cfg
echo "# This app project includes one pre-configured install-time asset pack." >> AndroidAppSettings.cfg
echo "# To put your data into asset pack, copy it to the directory AndroidData/assetpack" >> AndroidAppSettings.cfg
echo "# and run changeAppSettings.sh. The asset pack zip archive will be returned by" >> AndroidAppSettings.cfg
echo "# getenv(\"ANDROID_ASSET_PACK_PATH\"), this call will return NULL if the asset pack is not installed." >> AndroidAppSettings.cfg
echo "# You can put \"assetpack\" keyword to AppDataDownloadUrl, the code will check" >> AndroidAppSettings.cfg
echo "# if the asset pack is installed and will not download the data from other URLs." >> AndroidAppSettings.cfg
echo "# You can extract files from the asset pack the same way you extract files from the app assets." >> AndroidAppSettings.cfg
echo "# You can use .zip.xz archives for better compression, but you need to add 'lzma' to CompiledLibraries" >> AndroidAppSettings.cfg
echo "# Generate .zip.xz files like this: zip -0 -r data.zip your-data/* ; xz -8 data.zip" >> AndroidAppSettings.cfg
echo AppDataDownloadUrl=\"$AppDataDownloadUrl\" >> AndroidAppSettings.cfg
@@ -1116,6 +1124,10 @@ else
}
fi
if [ -z "`ls project/assetpack/src/main/assets/ 2>/dev/null`" ] ; then
$SEDI "/==ASSETPACK==/ d" project/app/build.gradle
fi
if [ -e project/jni/application/src/project.patch ]; then patch -p1 --dry-run -f -R < project/jni/application/src/project.patch > /dev/null 2>&1 || patch -p1 --no-backup-if-mismatch < project/jni/application/src/project.patch || exit 1 ; fi
rm -f project/lib

View File

@@ -3,36 +3,38 @@
ARCHES="arm64-v8a armeabi-v7a x86 x86_64"
if [ "$1" = "pack-binaries" -o "$1" = "pack-binaries-bundle" ]; then
[ -e jni/application/src/AndroidData/lib ] || exit 0
[ -e jni/application/src/AndroidData/binaries*.zip ] && {
echo "Error: binaries.zip no longer supported in Android 10"
echo "Copy your executable binaries to AndroidData/lib/arm64-v8a"
echo "Then execute them using \$LIBDIR or getenv(\"LIBDIR\")"
[ -e jni/application/src/AndroidData/lib ] || exit 0
[ -e jni/application/src/AndroidData/binaries*.zip ] && {
echo "Error: binaries.zip no longer supported in Android 10"
echo "Copy your executable binaries to AndroidData/lib/arm64-v8a"
echo "Then execute them using \$LIBDIR or getenv(\"LIBDIR\")"
exit 0
}
APK="`pwd`/$2"
echo "Copying binaries to .apk file"
cd jni/application/src/AndroidData/ || exit 1
if [ "$1" = "pack-binaries-bundle" ]; then
rm -rf base
mkdir -p base
cp -L -r lib base/
zip -r -D "$APK" base || exit 1
rm -rf base
else
zip -r -D "$APK" lib || exit 1
fi
cd ../../../../
exit 0
}
APK="`pwd`/$2"
echo "Copying binaries to .apk file"
cd jni/application/src/AndroidData/ || exit 1
if [ "$1" = "pack-binaries-bundle" ]; then
rm -rf base
mkdir -p base
mv lib base/
zip -r -D "$APK" base || exit 1
mv base/lib ./
rm -rf base
else
zip -r -D "$APK" lib || exit 1
fi
cd ../../../../
exit 0
fi
echo "Copying app data files from project/jni/application/src/AndroidData to project/assets"
mkdir -p project/assets
rm -f -r project/assets/*
if [ -d "project/jni/application/src/AndroidData" ] ; then
cp -L -r project/jni/application/src/AndroidData/* project/assets/
rm -rf project/assets/lib
for F in project/jni/application/src/AndroidData/*; do
[ "$F" = "project/jni/application/src/AndroidData/lib" ] && continue
[ "$F" = "project/jni/application/src/AndroidData/assetpack" ] && continue
cp -L -r "$F" project/assets/
done
fi
exit 0

View File

@@ -27,10 +27,13 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
assetPacks = [":assetpack"] // ==ASSETPACK==
dependencies { compile 'com.google.android.gms:play-services-games:21.0.0' } // ==GOOGLEPLAYGAMESERVICES==
dependencies { compile 'com.google.android.gms:play-services-drive:17.0.0' } // ==GOOGLEPLAYGAMESERVICES==
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.play:core:1.10.0'
}

View File

@@ -0,0 +1,8 @@
apply plugin: 'com.android.asset-pack'
assetPack {
packName = "assetpack"
dynamicDelivery {
deliveryType = "install-time"
}
}

View File

@@ -0,0 +1 @@
../../../jni/application/src/AndroidData/assetpack

View File

@@ -59,7 +59,11 @@ import android.content.pm.PackageManager;
import android.os.storage.StorageManager;
import android.os.storage.OnObbStateChangeListener;
//import com.google.android.play.core.assetpacks.AssetPackManagerFactory;
//import com.google.android.play.core.assetpacks.AssetPackManager;
import android.content.res.AssetManager;
import android.content.pm.PackageManager;
import android.content.pm.ApplicationInfo;
class CountingInputStream extends BufferedInputStream
{
@@ -323,7 +327,66 @@ class DataDownloader extends Thread
partialDownloadLen = partialDownload.length();
}
Status.setText( downloadCount + "/" + downloadTotal + ": " + res.getString(R.string.connecting_to, url) );
if( url.indexOf("obb:") == 0 || url.indexOf("mnt:") == 0 ) // APK expansion file provided by Google Play
if( url.equals("assetpack") )
{
Log.i("SDL", "Checking for asset pack");
/*
try
{
AssetPackManager assetPackManager = AssetPackManagerFactory.getInstance(Parent.getApplicationContext());
Log.i("SDL", "Parent.getApplicationContext(): " + Parent.getApplicationContext() + " assetPackManager " + assetPackManager);
if( assetPackManager != null )
{
Log.i("SDL", "assetPackManager.getPackLocation(): " + assetPackManager.getPackLocation("assetpack"));
if( assetPackManager.getPackLocation("assetpack") != null )
{
String assetPackPath = assetPackManager.getPackLocation("assetpack").assetsPath();
Parent.assetPackPath = assetPackPath;
if( assetPackPath != null )
{
Log.i("SDL", "Asset pack is installed at: " + assetPackPath);
return true;
}
}
}
}
catch( Exception e )
{
Log.i("SDL", "Asset pack exception: " + e);
}
*/
try
{
if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP )
{
ApplicationInfo info = Parent.getPackageManager().getApplicationInfo(Parent.getPackageName(), 0);
if( info.splitSourceDirs != null )
{
for( String apk: info.splitSourceDirs )
{
Log.i("SDL", "Package apk: " + apk);
if( apk.endsWith("assetpack.apk") )
{
Parent.assetPackPath = apk;
}
}
}
}
}
catch( Exception e )
{
Log.i("SDL", "Asset pack exception: " + e);
}
if( Parent.assetPackPath != null )
{
Log.i("SDL", "Found asset pack: " + Parent.assetPackPath);
return true;
}
Log.i("SDL", "Asset pack is not installed");
downloadUrlIndex++;
continue;
}
else if( url.indexOf("obb:") == 0 || url.indexOf("mnt:") == 0 ) // APK expansion file provided by Google Play
{
boolean tmpMountObb = ( url.indexOf("mnt:") == 0 );
url = getObbFilePath(url);

View File

@@ -1501,6 +1501,7 @@ public class MainActivity extends Activity
public boolean writeExternalStoragePermissionDialogAnswered = false;
public String ObbMountPath = null;
public String assetPackPath = null; // Not saved to the config file
}
// *** HONEYCOMB / ICS FIX FOR FULLSCREEN MODE, by lmak ***

View File

@@ -690,6 +690,10 @@ public class Settings
{
nativeSetEnv( "ANDROID_OBB_MOUNT_DIR", p.ObbMountPath );
}
if( p.assetPackPath != null )
{
nativeSetEnv( "ANDROID_ASSET_PACK_PATH", p.assetPackPath );
}
try {
nativeSetEnv( "ANDROID_APP_NAME", p.getString(p.getApplicationInfo().labelRes) );
} catch (Exception eeeeee) {}

View File

@@ -1,2 +1,3 @@
/AndroidData/*.pk3
/AndroidData/assetpack
/*.so

View File

@@ -7,10 +7,10 @@ AppName="OpenArena"
AppFullName=ws.openarena.sdl
# Application version code (integer)
AppVersionCode=08841
AppVersionCode=08844
# Application user-visible version name (string)
AppVersionName="0.8.8.41"
AppVersionName="0.8.8.44"
# Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...'
# If you'll start Description with '!' symbol it will be enabled by default, '!!' will also hide the entry from the menu, so it cannot be disabled
@@ -20,6 +20,14 @@ AppVersionName="0.8.8.41"
# You can specify Google Play expansion files in the form 'obb:main.12345' or 'obb:patch.12345' where 12345 is the app version for the obb file
# You can mount expansion files created with jobb tool if you put 'mnt:main.12345' or 'mnt:patch.12345'
# The mount directory will be returned by calling getenv("ANDROID_OBB_MOUNT_DIR")
# Android app bundles do not support .obb files, they use asset packs instead.
# This app project includes one pre-configured install-time asset pack.
# To put your data into asset pack, copy it to the directory AndroidData/assetpack
# and run changeAppSettings.sh. The asset pack zip archive will be returned by
# getenv("ANDROID_ASSET_PACK_PATH"), this call will return NULL if the asset pack is not installed.
# You can put "assetpack" keyword to AppDataDownloadUrl, the code will check
# if the asset pack is installed and will not download the data from other URLs.
# You can extract files from the asset pack the same way you extract files from the app assets.
# You can use .zip.xz archives for better compression, but you need to add 'lzma' to CompiledLibraries
# Generate .zip.xz files like this: zip -0 -r data.zip your-data/* ; xz -8 data.zip
AppDataDownloadUrl="!Game data|mnt:main.8839|obb:main.8828|https://github.com/pelya/openarena-engine/releases/download/0.8.8.39/data-0.8.8.zip|https://sourceforge.net/projects/libsdl-android/files/OpenArena/data-0.8.8.28.zip/download^!Game logic|:baseoa/pak7-android.pk3:pak7-android.pk3"

View File

@@ -1 +1,2 @@
include ':app'
include ':assetpack'

View File

@@ -134,11 +134,17 @@ env CXXFLAGS='-frtti -fexceptions' ../setEnvironment.sh ./configure
Application data may be bundled with app itself, or downloaded from the internet on the first run -
if you want to put app data inside .apk file - create a .zip archive and put it into the directory
project/jni/application/src/AndroidData (create it if it doesn't exist), then run ChangeAppSettings.sh
and specify the file name there. If the data files are more than 10 Mb it's a good idea to put them
on public HTTP server - you may specify URL in ChangeAppSettings.sh, also you may specify several files.
and specify the file name there. If the data files are more than 150 Mb then it's a good idea to put them
on public HTTP server - you may specify URL in AppDataDownloadUrl in AndroidAppSettings.cfg, also you may specify several files.
If you'll release new version of data files you should change download URL or data file name and update your app as well -
the app will re-download the data if URL does not match the saved URL from previous download.
AppDataDownloadUrl can have several URLs in the form "Description|URL|MirrorURL^Description2|URL2|MirrorURL2^..."
If you'll start Description with '!' symbol it will be enabled by default, '!!' will also hide the entry from the menu, so it cannot be disabled.
If the URL in in the form ':dir/file.dat:http://URL/' it will be downloaded as binary BLOB to the application dir and not unzipped.
If the URL does not contain 'http://' or 'https://', it is treated as file from 'project/jni/application/src/AndroidData' dir -
these files are put inside .apk package by the build system.
You can also create .obb file using jobb tool, and attach it to your app on Play Store:
jobb -pn xyz.yourserver.yourapp -pv 123 -d ./data -o main.123.xyz.yourserver.yourapp.obb
@@ -160,6 +166,17 @@ AppDataDownloadUrl="!!Game data|mnt:main.123|https://yourserver.xyz/gamedata.zip
You also need to specify ReadObbFile=y inside AndroidAppSettings.cfg.
Android app bundles do not support .obb files, they use asset packs instead.
This app project includes one pre-configured install-time asset pack.
To put your data into asset pack, copy it to the directory AndroidData/assetpack
and run changeAppSettings.sh. The asset pack zip archive will be returned by
getenv("ANDROID_ASSET_PACK_PATH"), this call will return NULL if the asset pack is not installed.
You can put "assetpack" keyword to AppDataDownloadUrl, the code will check
if the asset pack is installed and will not download the data from other URLs.
You can extract files from the asset pack the same way you extract files from the app assets.
AppDataDownloadUrl="!!Game data|assetpack|https://yourserver.xyz/gamedata.zip"
All devices have different screen resolutions, you may toggle automatic screen resizing
in ChangeAppSettings.sh and draw to virtual 640x480 screen - it will be HW accelerated
and will not impact performance. Automatic screen resizing does not work in SDL 1.3/2.0.