Sign Android apk with API > 29

Any topic not related to ZGE.

Moderator: Moderators

Post Reply
User avatar
Ats
Posts: 716
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Sign Android apk with API > 29

Post by Ats »

I didn't realize since I was only updating my already installed ZGE game on my phone, but Android now makes it difficult to install an apk with a targetSdkVersion <= 29:
install_apk_api_29.png
install_apk_api_29.png (31.35 KiB) Viewed 193 times
My phone's in French, but you get the idea: one needs to click twice on a link that doesn't even look like one, then enter the credentials in order to install the apk. I know where this is going, we will soon not be able to install old apk on our phones.

1- Install Android SDK and Apache-Ant

For starters, I don't want to install the new Android Studio. It's massive and goes against everything I like about ZGE. So let's prepare the Android SDK manually.

Create the folder C:\Android\

Download Apache ant
Extract it to C:\Android\

Create the folder C:\Android\android-sdk-windows\

Download Android SDK Platform latest version
You also need to download the minimal version you are targeting. Let's say API 23, which corresponds to Android 6. Before, I was targeting Android 4.1.2 (API 16) which was the newer one that you can choose in ZGameEditor Android settings. It's SUPER obsolete now. But you can install the min version you prefer based on the target device/audience you think is the best.

But from their documentation:
  • targetSdk will need to be 34+ for new apps and app updates by August 31, 2024.
  • Google Play services v23.30.99+ (August 2023) drops support for API levels below 21.
Extract those to C:\Android\android-sdk-windows\platforms
You'll notice that the platform names are inconsistent—sometimes they refer to the API level, and other times to the Android version number. However, this isn't an issue, as the folders are automatically detected using the source.properties file within them.

Download Android SDK Build-Tools 30.0.3
30.0.3 is the last version of Build-Tools that contains the necessary dx.bat. I need to search how to use d8.bat to bypass that.
Extract it to C:\Android\android-sdk-windows\build-tools

Download Android SDK Platform-tools latest version
Extract it to C:\Android\android-sdk-windows\platform-tools

Download Android SDK Tools 25.5.2
25.5.2 is the last version of Tools that contains the ant folder needed to compile an apk from ZGE.
Extract it to C:\Android\android-sdk-windows\tools

2- Install Java Development Kit

Download Java SE Development Kit 8u421
https://www.oracle.com/java/technologie ... a8-windows
or from here if download does not work on oracle website:
https://cfdownload.adobe.com/pub/adobe/ ... ws-x64.exe

The APK won't compile with a JDK version higher than 8. I'll look into it later.

During the installation, select only Development Tools. There's no need for Source Code and Public JRE.

Then you have to add java.exe to your Windows system path. Here's a bat file to do that easily:

Code: Select all

@echo off
REM Check for administrative privileges
openfiles >nul 2>&1
if %errorlevel% neq 0 (
    echo This script requires administrative privileges. Please run as administrator.
    pause
    exit /b 1
)

REM Get the current PATH variable
setlocal
set KEY_NAME="HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
set VALUE_NAME=Path

REM Set the JAVA_PATH to the specific Java path
set JAVA_PATH=C:\Program Files\Java\jdk-1.8\jre\bin

REM Display the JAVA_PATH being added
echo Attempting to add the following path to the system PATH:
echo %JAVA_PATH%

REM Check if the JAVA_PATH ends with a backslash and remove it
if "%JAVA_PATH:~-1%"=="\" (
    set JAVA_PATH=%JAVA_PATH:~0,-1%
)

REM Check if the JAVA_PATH already exists in the PATH
echo Checking if the path is already in the PATH...
for %%i in ("%JAVA_PATH%") do (
    if "%%~pi"=="%JAVA_PATH%\" (
        echo The path %JAVA_PATH% is already in the PATH.
        pause
        exit /b 0
    )
)

REM Update the PATH variable
echo Path not found in the PATH. Updating the system PATH...
for /f "tokens=2*" %%A in ('reg query %KEY_NAME% /v %VALUE_NAME% 2^>nul') do set CURRENT_PATH=%%B
setx /M Path "%CURRENT_PATH%;%JAVA_PATH%"

REM Confirm the update
echo %JAVA_PATH% has been added to the PATH. Please reboot the computer.
pause
endlocal

3- Create your Signature key (Signature Scheme v1)

(I don't remember how I did that. I'll edit the post later on)
But in the end, you'll obtain a yourkeystore.keystore file that you need to store somewhere, and you'll get a storepass, an alias and a keypass that goes with it. Don't lose them.

4- Compile your project in debug mode

In ZGameEditor, go to Tools / Settings / Android
Set the paths as needed:

Code: Select all

Android SDK Path: C:\Android\android-sdk-windows
Android Sdcard Path: /sdcard/
Apache Ant Path: C:\Android\apache-ant-1.10.15

Keystore File: <path to your keystore file>
Keystore Alias: <your keystore alias>
You can now build your ZGE project for Android in debug mode. This will create the export folder (ex: com.txori.cube).

6- Store your keystore credentials

Now, to the release mode. To avoid the compiler asking about your keystore credentials each time you compile your project, you'll need to add an ant.properties file. Create the file ant.properties inside that folder (ex: com.txori.cube) and edit it like this:

Code: Select all

key.store=C:\Path\To\yourkeystore.keystore
key.alias=<your keystore alias>
key.store.password=<your storepass>
key.alias.password=<your keypass>
Now compile for Android release once more. It is located in the bin folder (ex: com.txori.cube/bin/cube-release.apk)
It works, but you'll get the annoying installation that I presented at the start of this tutorial. Let's continue.

7- Update your AndroidManifest

Inside your export folder (ex: com.txori.cube), open AndroidManifest.xml and set your minSdkVersion and targetSdkVersion numbers, based on what you previously installed:

<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="34"/>

When targeting version 31 or above, you also need to add this line within the code in activity
android:exported="true"

Example:

Code: Select all

<activity
    android:name="org.zgameeditor.ZgeActivity"
    android:exported="true">
</activity>
Now compile for Android release once more.
You can try your apk on your phone. It is located in the bin folder (ex: com.txori.cube/bin/cube-release.apk)
Surprise, you can't install it. Why? An apk with a targetSdkVersion > 29 needs to be signed differently. Don't panic.

8- Sign your apk with the newer system (Signature Scheme v2/v3)

I created a batch file to do that quickly. Just create sign.bat inside your android export folder (ex: com.txori.cube). And edit it with:

Code: Select all

@echo off

REM Set your paths and variables
set "KEYSTORE_PATH=C:\Path\To\yourkeystore.keystore"
set "ALIAS=yourkeystorealias"
set "APK_PATH=C:\Path\To\Your\ZGE\Project\com.txori.cube\bin\cube-release.apk"
set "OUTPUT_APK=C:\Path\To\Your\ZGE\Project\com.txori.cube\bin\cube-release-signed.apk"
set "APKSIGNER_PATH=C:\Android\android-sdk-windows\build-tools\30.0.3\apksigner.bat"
set "ANT_PROPERTIES_PATH=C:\Path\To\Your\ZGE\Project\cube\com.txori.cube\ant.properties"

REM Read passwords from ant.properties
for /f "tokens=1,2 delims==" %%i in ('findstr /r "^key\.store\.password=" "%ANT_PROPERTIES_PATH%"') do set "KEYSTORE_PASSWORD=%%j"
for /f "tokens=1,2 delims==" %%i in ('findstr /r "^key\.alias\.password=" "%ANT_PROPERTIES_PATH%"') do set "KEY_ALIAS_PASSWORD=%%j"

REM Sign the APK using Signature Scheme v2/v3 and passwords from ant.properties
echo Signing the APK...
call "%APKSIGNER_PATH%" sign --ks "%KEYSTORE_PATH%" --ks-key-alias %ALIAS% --ks-pass pass:%KEYSTORE_PASSWORD% --key-pass pass:%KEY_ALIAS_PASSWORD% --out "%OUTPUT_APK%" --v3-signing-enabled true --v2-signing-enabled true --v1-signing-enabled false "%APK_PATH%"

REM Check if the signing was successful
echo Error level after signing: %ERRORLEVEL%
if %ERRORLEVEL% neq 0 (
    echo Signing failed with error code %ERRORLEVEL%.
    pause
    exit /b %ERRORLEVEL%
)

REM Verify the APK signature
echo Verifying APK signature...
call "%APKSIGNER_PATH%" verify --verbose "%OUTPUT_APK%"

REM Check if the verification was successful
echo Error level after verification: %ERRORLEVEL%
if %ERRORLEVEL% neq 0 (
    echo APK verification failed with error code %ERRORLEVEL%.
    pause
    exit /b %ERRORLEVEL%
)

echo APK signed and verified successfully: "%OUTPUT_APK%"
pause
(you need to set the paths and variables in it)


Launch sign.bat
Once done, you have your ZGE project compiled as a newly signed apk, with the latest API 8)
You can now send your apk (ex: cube-release-signed.apk) to your phone, and everything should be fine.
Last edited by Ats on Fri Aug 30, 2024 8:35 am, edited 35 times in total.
User avatar
Ats
Posts: 716
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Sign Android apk with API > 29

Post by Ats »

Now for the fun part. I'd like to simplify all this in ZGE and maybe revamp the entire 'Android version' folder system. To start, I’d like to automate the creation of the sign.bat file when building a ZGE project for Android, just like the m.bat and run.bat files.

For example, in ZGameEditor\Android\Template\base\ the file run.bat:

Code: Select all

"$sdkpath_normal$\platform-tools\adb" install -r "$apkpath$"
IF %ERRORLEVEL% NEQ 0 GOTO error
"$sdkpath_normal$\platform-tools\adb" shell am start -n $package$/org.zgameeditor.ZgeActivity
IF %ERRORLEVEL% NEQ 0 GOTO error
"$sdkpath_normal$\platform-tools\adb" logcat -s "ZgeAndroid"
IF %ERRORLEVEL% NEQ 0 GOTO error
goto end
:error
pause
:end
becomes in your project:

Code: Select all

"C:\Android\android-sdk-windows\platform-tools\adb" install -r "C:\Path\To\Your\ZGE\project\com.txori.cube\bin\ZGE cube-debug.apk"
IF %ERRORLEVEL% NEQ 0 GOTO error
"C:\Android\android-sdk-windows\platform-tools\adb" shell am start -n com.txori.cube/org.zgameeditor.ZgeActivity
IF %ERRORLEVEL% NEQ 0 GOTO error
"C:\Android\android-sdk-windows\platform-tools\adb" logcat -s "ZgeAndroid"
IF %ERRORLEVEL% NEQ 0 GOTO error
goto end
:error
pause
:end
But I'm still searching how to pass the ZGE Android settings to the bat file, such as:
%ZZDC_PATH%
%ANDROID_SDK_PATH%
%ANT_TOOL%
%ANT_PARAMS%
$apkpath$
$sdkpath_normal$
$antpath$
User avatar
Ats
Posts: 716
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Sign Android apk with API > 29

Post by Ats »

I edited sign.bat so it doesn't ask for the credentials each time you run it.
I also added some trace in order to verify that everything was running nicely. For starters, I'm now calling the C:\Android\android-sdk-windows\build-tools\30.0.3\apksigner.bat instead of running it directly, so it doesn't terminate the whole thing right after signing the apk.

So now I see that, even if the apk is running fine, there is an error to be solved: "Missing META-INF/MANIFEST.MF"
I'll see what can be done about that.
User avatar
Ats
Posts: 716
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Sign Android apk with API > 29

Post by Ats »

I just revisited my old tutorial and discovered that LazToAPK no longer has the necessary components. So, I rewrote the entire first part to handle it manually. Tomorrow, I'll try replacing the new signature bat file with a proper build.xml that achieves the same result.

Edit:
It's overly complicated. It needs gradle to replace ant, unless I build a new ant build script from scratch.
So, for now, I stick to targetSdkVersion 29...
Post Reply