android_plugin.rst 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. .. _doc_android_plugin:
  2. Creating Android plugins
  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 things like:
  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. On iOS, you can write a C++ module and take advantage of the C++/ObjC
  27. intercommunication. Even using GDNative is possible to make it a plug-in.
  28. On Android, interfacing with C++ through JNI (Java Native Interface) isn't as flexible, so writing plugins
  29. is considerably more work.
  30. It is also possible that you just want to do modifications to the Android export template, and by using a plugin your project
  31. can remain compatible with newer Godot versions (as the android source template will get updated on each release).
  32. Maybe REST
  33. ----------
  34. Most of these APIs allow communication via REST/JSON APIs. If the API is relatively simple and does not require
  35. complex authentication, this may be a better idea than writing a specific Android plugin.
  36. Godot has great support for HTTP, HTTPS and JSON, so an API implemented this way
  37. will work on every platform, too.
  38. Of course, in most of the cases, it's easier to just write an Android plugin, so keep reading.
  39. Android plugin
  40. --------------
  41. Writing an Android plugin is now possible, beginning with Godot 3.2. It's also pretty easy! Re-compiling the engine is no longer needed.
  42. Before anything, make sure you understand how to set up a :ref:`custom build environment<doc_android_custom_build>` for Android.
  43. Your plugin needs to be in a folder other than *"build/"* inside the *"res://android"* directory (which was created by following the link above). Any name is fine, so name it according to the SDK you will implement (or just your plugin name).
  44. Once created, there are certain rules to follow, but they are simple.
  45. Android directories
  46. ^^^^^^^^^^^^^^^^^^^
  47. Inside your plugin folder, you can use the standard folders as if they were from an Android Gradle project. Examples of this are:
  48. .. code-block:: none
  49. src/ - For Java source code, same as in your Android project
  50. res/ - For resources
  51. aidl/ - For interfaces
  52. assets/ - For assets that will be included as-is on export
  53. libs/debug - For debug JNI libraries
  54. libs/release - For release JNI libraries
  55. Gradle will treat them as part of the project automatically when building, same as the default project files.
  56. "Chunk" files
  57. ^^^^^^^^^^^^^
  58. It is now possible to modify *"AndroidManifest.xml"* and *build.gradle* in *"res://android/build"* directly and Godot will keep your
  59. changes when building. The problem, however, is that if you update Godot, you will also need to update the *build/* folder and your
  60. changes will be lost.
  61. To overcome this, the Godot Android Plugin system lets you create *chunk* files, where you can specify little bits that can be
  62. inserted in both *"AndroidManifest.xml"* and *build.gradle*. They are inserted every time Godot builds the project for export or deploy.
  63. AndroidManifest.conf
  64. ~~~~~~~~~~~~~~~~~~~~
  65. This file allows to insert bits of chunk into *AndroidManifest.xml*, the following are supported tags and are entirely optional:
  66. .. code-block:: none
  67. [user_permissions]
  68. Any bit of text below this tag is inserted inside the <manifest> tag of the file. This is often used for permission tags.
  69. .. code-block:: none
  70. [application]
  71. Any bit of text below this tag inside the <application> tag of the file. Many SDKs require this.
  72. .. code-block:: none
  73. [application_attribs]
  74. These are attributes you can add at the end of the <application> tag. Some SDKs require this.
  75. gradle.conf
  76. ~~~~~~~~~~~
  77. This file allows to insert bits of chunk into *build.gradle*, the following are supported and are entirely optional:
  78. .. code-block:: none
  79. [buildscript_repositories]
  80. Any bit of text below this tag is inserted inside the buildscript.repositories section of the build file.
  81. .. code-block:: none
  82. [buildscript_dependencies]
  83. Any bit of text below this tag is inserted inside the buildscript.dependencies section of the build file.
  84. .. code-block:: none
  85. [allprojects_repositories]
  86. Any bit of text below this tag is inserted inside the allprojects.repositories section of the build file.
  87. .. code-block:: none
  88. [dependencies]
  89. Any bit of text below this tag is inserted inside the dependencies section of the build file.
  90. .. code-block:: none
  91. [android_defaultconfig]
  92. Any bit of text below this tag is inserted inside the android.defaultconfig section of the build file.
  93. .. code-block:: none
  94. [global]
  95. Any bit of text below this tag is inserted inside the global scope of the build file.
  96. Java singleton
  97. --------------
  98. An Android plugin will usually have a singleton class that will load it,
  99. this class inherits from ``Godot.SingletonBase``. Resource identifiers for
  100. any additional resources you have provided for the module will be in the
  101. ``com.godot.game.R`` class, so you'll likely want to import it.
  102. A singleton object template follows:
  103. .. code-block:: java
  104. package org.godotengine.godot;
  105. import android.app.Activity;
  106. import android.content.Intent;
  107. import android.content.Context;
  108. import com.godot.game.R;
  109. import javax.microedition.khronos.opengles.GL10;
  110. public class MySingleton extends Godot.SingletonBase {
  111. protected Activity appActivity;
  112. protected Context appContext;
  113. private Godot activity = null;
  114. private int instanceId = 0;
  115. public String myFunction(String p_str) {
  116. // A function to bind.
  117. return "Hello " + p_str;
  118. }
  119. public void getInstanceId(int pInstanceId) {
  120. // You will need to call this method from Godot and pass in the get_instance_id().
  121. instanceId = pInstanceId;
  122. }
  123. static public Godot.SingletonBase initialize(Activity p_activity) {
  124. return new MySingleton(p_activity);
  125. }
  126. public MySingleton(Activity p_activity) {
  127. // Register class name and functions to bind.
  128. registerClass("MySingleton", new String[]
  129. {
  130. "myFunction",
  131. "getInstanceId"
  132. });
  133. this.appActivity = p_activity;
  134. this.appContext = appActivity.getApplicationContext();
  135. // You might want to try initializing your singleton here, but android
  136. // threads are weird and this runs in another thread, so to interact with Godot you usually have to do.
  137. this.activity = (Godot)p_activity;
  138. this.activity.runOnUiThread(new Runnable() {
  139. public void run() {
  140. // Useful way to get config info from "project.godot".
  141. String key = GodotLib.getGlobal("plugin/api_key");
  142. // SDK.initializeHere();
  143. }
  144. });
  145. }
  146. // Forwarded callbacks you can reimplement, as SDKs often need them.
  147. protected void onMainActivityResult(int requestCode, int resultCode, Intent data) {}
  148. protected void onMainRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {}
  149. protected void onMainPause() {}
  150. protected void onMainResume() {}
  151. protected void onMainDestroy() {}
  152. protected void onGLDrawFrame(GL10 gl) {}
  153. protected void onGLSurfaceChanged(GL10 gl, int width, int height) {} // Singletons will always miss first 'onGLSurfaceChanged' call.
  154. }
  155. Calling back to Godot
  156. ^^^^^^^^^^^^^^^^^^^^^
  157. Calling back to Godot from Java is a little more difficult. The instance
  158. ID of the script must be known first, this is obtained by calling
  159. ``get_instance_ID()`` on the script. This returns an integer that can be
  160. passed to Java.
  161. From Java, use the ``calldeferred`` function to communicate back with Godot.
  162. Java will most likely run in a separate thread, so calls are deferred:
  163. .. code-block:: java
  164. GodotLib.calldeferred(<instanceid>, "<function>", new Object[]{param1, param2, etc});
  165. Godot will detect this singleton and initialize it at the proper time.
  166. Using it from GDScript
  167. ^^^^^^^^^^^^^^^^^^^^^^
  168. First you will need to add your singleton into the android modules to be loaded. Go to "Project > Project Settings".
  169. Then on the tab "General" go to the "Android" section, and fill the Modules part with your module name.
  170. The module should include the full Java path. For our example: ``org/godotengine/godot/MySingleton``.
  171. .. image:: img/android_modules.png
  172. Then, from your script:
  173. ::
  174. if Engine.has_singleton("MySingleton"):
  175. var singleton = Engine.get_singleton("MySingleton")
  176. print(singleton.myFunction("World"))
  177. Troubleshooting
  178. ---------------
  179. Godot crashes upon load
  180. ^^^^^^^^^^^^^^^^^^^^^^^
  181. Check ``adb logcat`` for possible problems, then:
  182. - Make sure libgodot_android.so is in the ``libs/armeabi`` folder
  183. - Check that the methods used in the Java singleton only use simple
  184. Java datatypes, more complex ones are not supported.
  185. Future
  186. ------
  187. Godot has an experimental Java API Wrapper that allows to use the
  188. entire Java API from GDScript.
  189. It's simple to use and it's used like this:
  190. .. code-block:: none
  191. class = JavaClassWrapper.wrap(<javaclass as text>)
  192. This is most likely not functional yet, if you want to test it and help
  193. us make it work, contact us on irc.freenode.org:#godotengine-devel.