tweaselORG / appstraction

An abstraction layer for common instrumentation functions (e.g. installing and starting apps, setting preferences, etc.) on Android and iOS.
MIT License
4 stars 1 forks source link

Support for xapks #63

Closed zner0L closed 1 year ago

zner0L commented 1 year ago

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.

zner0L commented 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" }]
}
zner0L commented 1 year ago

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.

zner0L commented 1 year ago

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.

baltpeter commented 1 year ago

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.

zner0L commented 1 year ago

Since these .xapks 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 .xapks, but none of them seem to care about install_location:

zner0L commented 1 year ago

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!