Closed zner0L closed 1 year ago
I extracted an .xapk
to test ("Pixel Strike 3D" – apparently these are popular with games) and it seems indeed to be the case. It contained an .apk
, an Android
folder, an icon.png
and most interestingly a manifest.json
. This is hwo that looked like:
{
"xapk_version": 2,
"package_name": "com.pixellabs.pixelstrike3d",
"name": "PixelStrike3D",
"locales_name": {
"af": "PixelStrike3D",
"...": "..."
"zu": "PixelStrike3D"
},
"version_code": "272",
"version_name": "10.0.0",
"min_sdk_version": "22",
"target_sdk_version": "31",
"permissions": [
"android.permission.INTERNET",
"android.permission.VIBRATE",
"android.permission.ACCESS_NETWORK_STATE",
"android.permission.READ_EXTERNAL_STORAGE",
"com.google.android.gms.permission.AD_ID",
"com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE",
"com.android.vending.BILLING",
"android.permission.WAKE_LOCK",
"android.permission.RECEIVE_BOOT_COMPLETED",
"android.permission.FOREGROUND_SERVICE",
"android.permission.ACCESS_WIFI_STATE",
"com.google.android.c2dm.permission.RECEIVE",
"com.pixellabs.pixelstrike3d.permission.C2D_MESSAGE",
"android.permission.POST_NOTIFICATIONS",
"android.permission.CHANGE_WIFI_STATE",
"android.permission.CHANGE_NETWORK_STATE"
],
"total_size": 938291868,
"icon": "icon.png",
"expansions": [
{
"file": "Android/obb/com.pixellabs.pixelstrike3d/main.272.com.pixellabs.pixelstrike3d.obb",
"install_location": "EXTERNAL_STORAGE",
"install_path": "Android/obb/com.pixellabs.pixelstrike3d/main.272.com.pixellabs.pixelstrike3d.obb"
}
],
"split_apks": [{ "file": "com.pixellabs.pixelstrike3d.apk", "id": "base" }]
}
The topic of what unzipping library to use is unfortunately a very sad one. There are several ones and none of them are what we wish for. I haven't seen any with types included. Kudos to this stackoverflow answer which sums it up pretty nicely. I decided to use https://github.com/thejoshwolfe/yauzl because it seemed relatively easy to use, well maintained and recommended.
I would really like to just stream the files to the device, but adb
doesn't seem to support that. One option would be to use named pipes, but that seems like overkill. so I decided against that, but the downside is, that we need quite a lot of free space on the host machine, because the unpacked xapk assests tend to be fairly big.
the downside is, that we need quite a lot of free space on the host machine, because the unpacked xapk assests tend to be fairly big.
Shouldn't be too much of an issue if we delete them after installing.
Since these .xapk
s conveniently contain a manifest.json
for the installer, in wanted to use it. For the split apks this is easy enough: Just install all files (matching the correct ABIs) mentioned in split_apks
. But for the extentions you need to copy the files to the correct location. Luckily, the objects in the extensions
property contain a install_path
, where we can copy the files, but it is not complete. The other part of this path comes form the mysterious install_location
. All examples I have seen always have EXTERNAL_STORAGE
in there, which I guess from the ApkPure manual(who apparently invented that format) is supposed to mean /SDCARD/storage/emulated/0
.
Unfortunately their "XAPK Installer" App isn’t open-source, so I can’t check how they handle it. There are several different tools to handle .xapk
s, but none of them seem to care about install_location
:
EXTERNAL_STORAGE
to it regardless (https://github.com/BryghtShadow/xapktool/blob/master/xapktool.py#L43)install_location
is anything other than EXTERNAL_STORAGE
(https://github.com/adhu2018/xapkInstaller/blob/main/xapkInstaller.py#L682-L688)https://github.com/david-lev/apkfile just ignores expansions altogether
All of that makes a lot of sense considering Google itself says that the files must be stored in a shared location obtained by [getExternalStorageDirectory()
](https://developer.android.com/reference/android/os/Environment#getExternalStorageDirectory()). In conclusion, there seems to be no point in the install_location
property and I will only the handle the case for EXTERNAL_STORAGE
.
And apparently [getExternalStorageDirectory()
](https://developer.android.com/reference/android/os/Environment#getExternalStorageDirectory()) is just the content of $EXTERNAL_STORAGE
(https://android.stackexchange.com/a/14106). Great!
Some of our early users asked for support of xapks, which shouldn't be too hard, as a
.xapk
seems to just be a zip file containing the apk and some additional foo. At least this stackexchange answer seems to suggest that.