Android
Creating Apk
Signing Apk
Whenever you're using a jarsigner, don't rely on its default setting to sign the apk properly. Check google Sign apk page and use the suggested settings by default.
My original script looked like this:
"%jdkbindir%\jarsigner" -verbose ^ -keystore bin\LCLDebugBKKey.keystore -keypass 123456 -storepass 123456 ^ -signedjar bin\%APP_NAME%-unaligned.apk bin\%APP_NAME%-unsigned.apk LCLDebugBKKey
It worked fine on my Android device, but failed on others. What I was missing (per Google's page) is "sigalg" and "digestalg" modifiers:
"%jdkbindir%\jarsigner" -verbose ^ -sigalg SHA1withRSA ^ -digestalg SHA1 ^ -keystore bin\LCLDebugBKKey.keystore -keypass 123456 -storepass 123456 ^ -signedjar bin\%APP_NAME%-unaligned.apk bin\%APP_NAME%-unsigned.apk LCLDebugBKKey
Debugging such issues could be tricky. Since the only thing that a user sees is a message "App Not Installed". A savvy person will not be able to give you log to see packager error. I had to use one of the online Android test services (testdroid) to get the log
Running Apk
C:\android\sdk-windows\platform-tools\adb.exe shell am start -W -n %packagename%/%package activityname%
AdMobs
Admobs come with Google Play Services package. However, .jar file is not easy to find in revisions after 30.
The later revisions come with .aar files (specific to Google Android Studio?) under m2repository directory
androidsdk\extras\google\m2repository\com\google\android\gms\play-services-ads
Why do we have to have so many build systems?!
- The .aar contains "classes.jar" file. The file must be extracted and renamed to "ads.jar" (the name can be different from "ads.jar" but at least not "classes.jar" to prevent name conflicts. Or at least put into a separate directory (to avoid naming conflict as well)
- "play-services-ads" depends on "play-services-base" package. Classes file of ""play-services-base" should also be extracted (and renamed to "base.jar")
- during an Android project compilation from, the step converting Java Jar files are converted to Dex (dalvik format), should also take the both extracted .jar files (Ads and base) into account. The must be included in the final .dex file.
- todo:: there should be a way to avoid that. These .jar file never change, thus, there must be a way to convert them only once. However, .apk file expects "classes.dex" by default (would it be able to use more?)
- .. modify activity to include AdView
- modify AndroidManifest.xml and include ads version meta-data tag. For version 6.5.78 it looks like this:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" ... <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ... <application ... <meta-data android:name="com.google.android.gms.version" android:value="6587000" /> ... <activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" /> </application> </manifest>
AdActivity
W Ads : com.google.android.gms.ads.AdActivity requires the android:configChanges value to contain "screenSize". W Ads : com.google.android.gms.ads.AdActivity requires the android:configChanges value to contain "smallestScreenSize".
JNI
Whenever you want to keep an object reference in Native code, use GetGlobalRef from the object. By default Java passes Local reference. Local reference is INVALID right after the native method ends! GlobalReference however, MUST BE RELEASED! or it leaks. Read more here
Billing
Disclaimer: this whole process is done this way, because I don't want to study tricks and hints of Java and 3d-party build systems in depth. It will eventually come anyway (just because one have to understand what he/she doing) But for now, I just want it to compile. Compile from the plain command-line, using tools provided in SDK/NDK only!
As usual Android is full of tricks:
The first thing that is advised on [url=https://developer.android.com/google/play/billing/billing_integrate.html]the API page[/url] is to get .aidl file. Naturally, the page doesn't suggest how to handle the file w/o any build systems or IDEs.
However, a bit of googling suggest the use of "aidl" tool, that comes with SDK (sdk\build-tools\23.0.3\). While "aidl" doesn't have many parameters, very straight forward use, doesn't produce expected result
rem this is not the command-line you're looking for aidl IInAppBillingService.aidl
results in
IInAppBillingService.aidl:19: couldn't find import for class android.os.Bundle
error.
Some extra googling suggests, that each "android-xx" platform package comes with "frameworks.aidl" file. This while is "preprocessed" interface file, which should be used in order for the tool to find android.os.Bundle.
The command line parameter to pass the file is -p. However, even if you pass the full path (of the desired platform) to frameworks.aidl, it would still fail, requesting that IInAppBillingService.aidl is placed into a proper directory.
Thus, this is what I did. Created the folder structure (as suggested in API reference above, and the by the error message of aidl tool)
com\android\vending\billing\IInAppBillingService.aidl
then I run the command line
set buildtoolsdir=C:\android\sdk-windows\build-tools\23.0.3 set APK_SDK_PLATFORM=C:\android\sdk-windows\platforms\android-11 buildtoolsdir%\aidl -p%APK_SDK_PLATFORM%\framework.aidl com\android\vending\billing\IInAppBillingService.aidl
That's it. and after that I'm getting
com\android\vending\billing\IInAppBillingService.java
Presumably ready for building. I wonder how much different the generated .java file could be across different Android platforms.