creating_android_modules.rst 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. .. _doc_creating_android_modules:
  2. Creating Android modules
  3. ========================
  4. Introduction
  5. ------------
  6. Making video games portable is all fine and dandy, until mobile
  7. gaming monetization shows up.
  8. This area is complex, usually a mobile game that monetizes needs
  9. special connections to a server for stuff such as:
  10. - Analytics
  11. - In-app purchases
  12. - Receipt validation
  13. - Install tracking
  14. - Ads
  15. - Video ads
  16. - Cross-promotion
  17. - In-game soft & hard currencies
  18. - Promo codes
  19. - A/B testing
  20. - Login
  21. - Cloud saves
  22. - Leaderboards and scores
  23. - User support & feedback
  24. - Posting to Facebook, Twitter, etc.
  25. - Push notifications
  26. Oh yeah, developing for mobile is a lot of work. On iOS, you can just
  27. write a C++ module and take advantage of the C++/ObjC
  28. intercommunication, so this is rather easy.
  29. For C++ developers Java is a pain, the build system is severely bloated
  30. and interfacing it with C++ through JNI (Java Native Interface) is more
  31. pain that you don't want even for your worst enemy.
  32. Maybe REST?
  33. -----------
  34. Most of these APIs allow communication via REST+JSON APIs. Godot has
  35. great support for HTTP, HTTPS and JSON, so consider this as an option
  36. that works in every platform. Only write the code once and you are set
  37. to go.
  38. Popular engines that have half the share of apps published on mobile get
  39. special plugins written just for them. Godot does not have that luxury
  40. yet. So, if you write a REST implementation of a SDK for Godot, please
  41. share it with the community.
  42. Android module
  43. --------------
  44. Writing an Android module is similar to :ref:`doc_custom_modules_in_c++`, but
  45. needs a few more steps.
  46. Make sure you are familiar with building your own :ref:`Android export templates <doc_compiling_for_android>`,
  47. as well as creating :ref:`doc_custom_modules_in_c++`.
  48. config.py
  49. ~~~~~~~~~
  50. In the config.py for the module, some extra functions are provided for
  51. convenience. First, it's often wise to detect if android is being built
  52. and only enable building in this case:
  53. .. code:: python
  54. def can_build(plat):
  55. return plat=="android"
  56. If more than one platform can be built (typical if implementing the
  57. module also for iOS), check manually for Android in the configure
  58. functions:
  59. .. code:: python
  60. def can_build(plat):
  61. return plat=="android" or plat=="iphone"
  62. def configure(env):
  63. if env['platform'] == 'android':
  64. # android specific code
  65. Java singleton
  66. --------------
  67. An android module will usually have a singleton class that will load it,
  68. this class inherits from ``Godot.SingletonBase``. A singleton object
  69. template follows:
  70. .. code:: java
  71. // namespace is wrong, will eventually change
  72. package com.android.godot;
  73. public class MySingleton extends Godot.SingletonBase {
  74. public int myFunction(String p_str) {
  75. // a function to bind
  76. }
  77. static public Godot.SingletonBase initialize(Activity p_activity) {
  78. return new MySingleton(p_activity);
  79. }
  80. public MySingleton(Activity p_activity) {
  81. //register class name and functions to bind
  82. registerClass("MySingleton", new String[]{"myFunction"});
  83. // you might want to try initializing your singleton here, but android
  84. // threads are weird and this runs in another thread, so you usually have to do
  85. activity.runOnUiThread(new Runnable() {
  86. public void run() {
  87. //useful way to get config info from engine.cfg
  88. String key = GodotLib.getGlobal("plugin/api_key");
  89. SDK.initializeHere();
  90. }
  91. });
  92. }
  93. // forwarded callbacks you can reimplement, as SDKs often need them
  94. protected void onMainActivityResult(int requestCode, int resultCode, Intent data) {}
  95. protected void onMainPause() {}
  96. protected void onMainResume() {}
  97. protected void onMainDestroy() {}
  98. protected void onGLDrawFrame(GL10 gl) {}
  99. protected void onGLSurfaceChanged(GL10 gl, int width, int height) {} // singletons will always miss first onGLSurfaceChanged call
  100. }
  101. Calling back to Godot from Java is a little more difficult. The instance
  102. ID of the script must be known first, this is obtained by calling
  103. ``get_instance_ID()`` on the script. This returns an integer that can be
  104. passed to Java.
  105. From Java, use the ``calldeferred`` function to communicate back with Godot.
  106. Java will most likely run in a separate thread, so calls are deferred:
  107. .. code:: java
  108. GodotLib.calldeferred(<instanceid>, "<function>", new Object[]{param1,param2,etc});
  109. Add this singleton to the build of the project by adding the following
  110. to config.py:
  111. (Before Version 2.0)
  112. .. code:: python
  113. def can_build(plat):
  114. return plat=="android" or plat=="iphone"
  115. def configure(env):
  116. if env['platform'] == 'android':
  117. # will copy this to the java folder
  118. env.android_module_file("MySingleton.java")
  119. #env.android_module_file("MySingleton2.java") call again for more files
  120. (After Version 2.0)
  121. .. code:: python
  122. def can_build(plat):
  123. return plat=="android" or plat=="iphone"
  124. def configure(env):
  125. if env['platform'] == 'android':
  126. # will copy this to the java folder
  127. env.android_add_java_dir("Directory that contain MySingelton.java")
  128. AndroidManifest
  129. ---------------
  130. Some SDKs need custom values in AndroidManifest.xml. Permissions can be
  131. edited from the godot exporter so there is no need to add those, but
  132. maybe other functionalities are needed.
  133. Create the custom chunk of android manifest and put it inside the
  134. module, add it like this:
  135. (Before Version 2.0)
  136. .. code:: python
  137. def can_build(plat):
  138. return plat=="android" or plat=="iphone"
  139. def configure(env):
  140. if env['platform'] == 'android':
  141. # will copy this to the java folder
  142. env.android_module_file("MySingleton.java")
  143. env.android_module_manifest("AndroidManifestChunk.xml")
  144. (After Version 2.0)
  145. .. code:: python
  146. def can_build(plat):
  147. return plat=="android" or plat=="iphone"
  148. def configure(env):
  149. if env['platform'] == 'android':
  150. # will copy this to the java folder
  151. env.android_add_java_dir("Directory that contain MySingelton.java")
  152. env.android_add_to_manifest("AndroidManifestChunk.xml")
  153. SDK library
  154. -----------
  155. So, finally it's time to add the SDK library. The library can come in
  156. two flavors, a JAR file or an Android project for ant. JAR is the
  157. easiest to integrate, just put it in the module directory and add it:
  158. (Before Version 2.0)
  159. .. code:: python
  160. def can_build(plat):
  161. return plat=="android" or plat=="iphone"
  162. def configure(env):
  163. if env['platform'] == 'android':
  164. # will copy this to the java folder
  165. env.android_module_file("MySingleton.java")
  166. env.android_module_manifest("AndroidManifestChunk.xml")
  167. env.android_module_library("MyLibrary-3.1.jar")
  168. (After Version 2.0)
  169. .. code:: python
  170. def can_build(plat):
  171. return plat=="android" or plat=="iphone"
  172. def configure(env):
  173. if env['platform'] == 'android':
  174. # will copy this to the java folder
  175. env.android_add_java_dir("Directory that contain MySingelton.java")
  176. env.android_add_to_manifest("AndroidManifestChunk.xml")
  177. env.android_add_dependency("compile files('something_local.jar')") # if you have a jar
  178. env.android_add_maven_repository("maven url") #add a maven url
  179. env.android_add_dependency("compile 'com.google.android.gms:play-services-ads:8'") #get dependency from maven repository
  180. SDK project
  181. -----------
  182. When this is an Android project, things usually get more complex. Copy
  183. the project folder inside the module directory and configure it:
  184. ::
  185. c:\godot\modules\mymodule\sdk-1.2> android -p . -t 15
  186. As of this writing, Godot uses minsdk 10 and target sdk 15. If this ever
  187. changes, it should be reflected in the manifest template:
  188. `AndroidManifest.xml.template <https://github.com/godotengine/godot/blob/master/platform/android/AndroidManifest.xml.template>`
  189. Then, add the module folder to the project:
  190. (Before Version 2.0)
  191. .. code:: python
  192. def can_build(plat):
  193. return plat=="android" or plat=="iphone"
  194. def configure(env):
  195. if env['platform'] == 'android':
  196. # will copy this to the java folder
  197. env.android_module_file("MySingleton.java")
  198. env.android_module_manifest("AndroidManifestChunk.xml")
  199. env.android_module_source("sdk-1.2","")
  200. (After Version 2.0)
  201. Building
  202. --------
  203. As you probably modify the contents of the module, and modify your .java
  204. inside the module, you need the module to be built with the rest of
  205. Godot, so compile android normally.
  206. ::
  207. c:\godot> scons p=android
  208. This will cause your module to be included, the .jar will be copied to
  209. the java folder, the .java will be copied to the sources folder, etc.
  210. Each time you modify the .java, scons must be called.
  211. Afterwards, just continue the steps for compiling android :ref:`doc_compiling_for_android`.
  212. Using the module
  213. ~~~~~~~~~~~~~~~~
  214. To use the module from GDScript, first enable the singleton by adding
  215. the following line to engine.cfg:
  216. ::
  217. [android]
  218. modules="com/android/godot/MySingleton"
  219. More than one singleton module can be enabled by separating with commas:
  220. ::
  221. [android]
  222. modules="com/android/godot/MySingleton,com/android/godot/MyOtherSingleton"
  223. Then just request the singleton Java object from Globals like this:
  224. ::
  225. # in any file
  226. var singleton = null
  227. func _init():
  228. singleton = Globals.get_singleton("MySingleton")
  229. print(singleton.myFunction("Hello"))
  230. Troubleshooting
  231. ---------------
  232. (This section is a work in progress, report your problems here!)
  233. Godot crashes upon load
  234. ~~~~~~~~~~~~~~~~~~~~~~~
  235. Check ``adb logcat`` for possible problems, then:
  236. - Make sure libgodot_android.so is in the ``libs/armeabi`` folder
  237. - Check that the methods used in the Java singleton only use simple
  238. Java datatypes, more complex ones are not supported.
  239. Future
  240. ------
  241. Godot has an experimental Java API Wrapper that allows to use the
  242. entire Java API from GDScript.
  243. It's simple to use and it's used like this:
  244. ::
  245. class = JavaClassWrapper.wrap(<javaclass as text>)
  246. This is most likely not functional yet, if you want to test it and help
  247. us make it work, contact us through the `developer mailing
  248. list <https://groups.google.com/forum/#!forum/godot-engine>`__.