Difference between revisions of "Android"

From havefunsoft wiki
Jump to: navigation, search
m (Running Apk)
m (=Api and Engine)
 
(16 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
'''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!''
 
==Creating Apk==
 
==Creating Apk==
 
===Signing Apk===
 
===Signing Apk===
Line 38: Line 41:
 
  <?xml version="1.0" encoding="utf-8"?>
 
  <?xml version="1.0" encoding="utf-8"?>
 
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 
  <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
 
     <application
 
         ...
 
         ...
 
  <meta-data android:name="com.google.android.gms.version" android:value="6587000" />
 
  <meta-data android:name="com.google.android.gms.version" android:value="6587000" />
 
         ...
 
         ...
 +
       
 +
        <!--Include the AdActivity configChanges and theme. -->
 +
        <activity android:name="com.google.android.gms.ads.AdActivity"
 +
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
 +
            />
 
     </application>
 
     </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.
 +
[http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/design.html#wp1242 Read more here]
 +
 +
 +
*[http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html GetMethodID reference]
 +
==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
 
   
 
   
  </manifest>
+
  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 would be across different Android platforms.
 +
 
 +
 
 +
The file should be added to javac compilation list (make sure the specify the full path)
 +
javac
 +
  ...
 +
    .\com\android\vending\billing\IInAppBillingService.java
 +
===Api and Engine===
 +
It's somewhat a downside for a "native" based engines, that a purchase APIs are Java based only and there's no way to have a NDK counterpart. However, since the purchase process from UI point of view, has to happen within managed environment (switching Activities), etc, it makes sense. It also plays to a benefit, since whoever, does the implementation of In-app billing for the first time, will actually be forced to rewrite the any example (i.e. TrivialBilling) to something more convenient to their need.
  
 
[[Category:Dev]]
 
[[Category:Dev]]

Latest revision as of 23:59, 9 February 2017

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!

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%

am start reference

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 would be across different Android platforms.


The file should be added to javac compilation list (make sure the specify the full path)

javac
 ...
   .\com\android\vending\billing\IInAppBillingService.java

Api and Engine

It's somewhat a downside for a "native" based engines, that a purchase APIs are Java based only and there's no way to have a NDK counterpart. However, since the purchase process from UI point of view, has to happen within managed environment (switching Activities), etc, it makes sense. It also plays to a benefit, since whoever, does the implementation of In-app billing for the first time, will actually be forced to rewrite the any example (i.e. TrivialBilling) to something more convenient to their need.