mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-03 05:48:42 +03:00
Revamping of the docs organisation for a more coherent TOC
Only the pages were moved so far and some empty ones created,
the up-to-date toctrees come in the next commit.
(cherry picked from commit b408bdb918)
This commit is contained in:
committed by
Rémi Verschelde
parent
6a730cb057
commit
5e05011eae
397
development/cpp/creating_android_modules.rst
Normal file
397
development/cpp/creating_android_modules.rst
Normal file
@@ -0,0 +1,397 @@
|
||||
.. _doc_creating_android_modules:
|
||||
|
||||
Creating Android modules
|
||||
========================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Making video games portable is all fine and dandy, until mobile
|
||||
gaming monetization shows up.
|
||||
|
||||
This area is complex, usually a mobile game that monetizes needs
|
||||
special connections to a server for stuff such as:
|
||||
|
||||
- Analytics
|
||||
- In-app purchases
|
||||
- Receipt validation
|
||||
- Install tracking
|
||||
- Ads
|
||||
- Video ads
|
||||
- Cross-promotion
|
||||
- In-game soft & hard currencies
|
||||
- Promo codes
|
||||
- A/B testing
|
||||
- Login
|
||||
- Cloud saves
|
||||
- Leaderboards and scores
|
||||
- User support & feedback
|
||||
- Posting to Facebook, Twitter, etc.
|
||||
- Push notifications
|
||||
|
||||
Oh yeah, developing for mobile is a lot of work. On iOS, you can just
|
||||
write a C++ module and take advantage of the C++/ObjC
|
||||
intercommunication, so this is rather easy.
|
||||
|
||||
For C++ developers Java is a pain, the build system is severely bloated
|
||||
and interfacing it with C++ through JNI (Java Native Interface) is more
|
||||
pain that you don't want even for your worst enemy.
|
||||
|
||||
Maybe REST?
|
||||
-----------
|
||||
|
||||
Most of these APIs allow communication via REST+JSON APIs. Godot has
|
||||
great support for HTTP, HTTPS and JSON, so consider this as an option
|
||||
that works in every platform. Only write the code once and you are set
|
||||
to go.
|
||||
|
||||
Popular engines that have half the share of apps published on mobile get
|
||||
special plugins written just for them. Godot does not have that luxury
|
||||
yet. So, if you write a REST implementation of a SDK for Godot, please
|
||||
share it with the community.
|
||||
|
||||
Android module
|
||||
--------------
|
||||
|
||||
Writing an Android module is similar to :ref:`doc_custom_modules_in_c++`, but
|
||||
needs a few more steps.
|
||||
|
||||
Make sure you are familiar with building your own :ref:`Android export templates <doc_compiling_for_android>`,
|
||||
as well as creating :ref:`doc_custom_modules_in_c++`.
|
||||
|
||||
config.py
|
||||
~~~~~~~~~
|
||||
|
||||
In the config.py for the module, some extra functions are provided for
|
||||
convenience. First, it's often wise to detect if android is being built
|
||||
and only enable building in this case:
|
||||
|
||||
.. code:: python
|
||||
|
||||
def can_build(plat):
|
||||
return plat=="android"
|
||||
|
||||
If more than one platform can be built (typical if implementing the
|
||||
module also for iOS), check manually for Android in the configure
|
||||
functions:
|
||||
|
||||
.. code:: python
|
||||
|
||||
def can_build(plat):
|
||||
return plat=="android" or plat=="iphone"
|
||||
|
||||
def configure(env):
|
||||
if env['platform'] == 'android':
|
||||
# android specific code
|
||||
|
||||
Java singleton
|
||||
--------------
|
||||
|
||||
An android module will usually have a singleton class that will load it,
|
||||
this class inherits from ``Godot.SingletonBase``. Resource identifiers for
|
||||
any additional resources you have provided for the module will be in the
|
||||
``com.godot.game.R`` class, so you'll likely want to import it.
|
||||
|
||||
A singleton object template follows:
|
||||
|
||||
.. code:: java
|
||||
|
||||
// package com.android.godot; // for 1.1
|
||||
package org.godotengine.godot; // for 2.0
|
||||
|
||||
import com.godot.game.R;
|
||||
|
||||
public class MySingleton extends Godot.SingletonBase {
|
||||
|
||||
public int myFunction(String p_str) {
|
||||
// a function to bind
|
||||
}
|
||||
|
||||
static public Godot.SingletonBase initialize(Activity p_activity) {
|
||||
return new MySingleton(p_activity);
|
||||
}
|
||||
|
||||
public MySingleton(Activity p_activity) {
|
||||
//register class name and functions to bind
|
||||
registerClass("MySingleton", new String[]{"myFunction"});
|
||||
|
||||
// you might want to try initializing your singleton here, but android
|
||||
// threads are weird and this runs in another thread, so you usually have to do
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
//useful way to get config info from engine.cfg
|
||||
String key = GodotLib.getGlobal("plugin/api_key");
|
||||
SDK.initializeHere();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// forwarded callbacks you can reimplement, as SDKs often need them
|
||||
|
||||
protected void onMainActivityResult(int requestCode, int resultCode, Intent data) {}
|
||||
|
||||
protected void onMainPause() {}
|
||||
protected void onMainResume() {}
|
||||
protected void onMainDestroy() {}
|
||||
|
||||
protected void onGLDrawFrame(GL10 gl) {}
|
||||
protected void onGLSurfaceChanged(GL10 gl, int width, int height) {} // singletons will always miss first onGLSurfaceChanged call
|
||||
|
||||
}
|
||||
|
||||
Calling back to Godot from Java is a little more difficult. The instance
|
||||
ID of the script must be known first, this is obtained by calling
|
||||
``get_instance_ID()`` on the script. This returns an integer that can be
|
||||
passed to Java.
|
||||
|
||||
From Java, use the ``calldeferred`` function to communicate back with Godot.
|
||||
Java will most likely run in a separate thread, so calls are deferred:
|
||||
|
||||
.. code:: java
|
||||
|
||||
GodotLib.calldeferred(<instanceid>, "<function>", new Object[]{param1,param2,etc});
|
||||
|
||||
Add this singleton to the build of the project by adding the following
|
||||
to config.py:
|
||||
|
||||
(Before Version 2.0)
|
||||
|
||||
.. code:: python
|
||||
|
||||
def can_build(plat):
|
||||
return plat=="android" or plat=="iphone"
|
||||
|
||||
def configure(env):
|
||||
if env['platform'] == 'android':
|
||||
# will copy this to the java folder
|
||||
env.android_module_file("MySingleton.java")
|
||||
#env.android_module_file("MySingleton2.java") call again for more files
|
||||
|
||||
|
||||
(After Version 2.0)
|
||||
|
||||
.. code:: python
|
||||
|
||||
def can_build(plat):
|
||||
return plat=="android" or plat=="iphone"
|
||||
|
||||
def configure(env):
|
||||
if env['platform'] == 'android':
|
||||
# will copy this to the java folder
|
||||
env.android_add_java_dir("Directory that contain MySingleton.java")
|
||||
|
||||
|
||||
|
||||
AndroidManifest
|
||||
---------------
|
||||
|
||||
Some SDKs need custom values in AndroidManifest.xml. Permissions can be
|
||||
edited from the godot exporter so there is no need to add those, but
|
||||
maybe other functionalities are needed.
|
||||
|
||||
Create the custom chunk of android manifest and put it inside the
|
||||
module, add it like this:
|
||||
|
||||
(Before Version 2.0)
|
||||
|
||||
.. code:: python
|
||||
|
||||
def can_build(plat):
|
||||
return plat=="android" or plat=="iphone"
|
||||
|
||||
def configure(env):
|
||||
if env['platform'] == 'android':
|
||||
# will copy this to the java folder
|
||||
env.android_module_file("MySingleton.java")
|
||||
env.android_module_manifest("AndroidManifestChunk.xml")
|
||||
|
||||
(After Version 2.0)
|
||||
|
||||
.. code:: python
|
||||
|
||||
def can_build(plat):
|
||||
return plat=="android" or plat=="iphone"
|
||||
|
||||
def configure(env):
|
||||
if env['platform'] == 'android':
|
||||
# will copy this to the java folder
|
||||
env.android_add_java_dir("Directory that contain MySingelton.java")
|
||||
env.android_add_to_manifest("AndroidManifestChunk.xml")
|
||||
|
||||
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
In order to provide additional resources with your module you have to
|
||||
add something like this:
|
||||
|
||||
.. code:: python
|
||||
|
||||
def configure(env):
|
||||
if env['platform'] == 'android':
|
||||
# [...]
|
||||
env.android_add_res_dir("Directory that contains resource subdirectories (values, drawable, etc.)")
|
||||
|
||||
Now you can refer to those resources by their id (``R.string.my_string``, and the like)
|
||||
by importing the ``com.godot.game.R`` class in your Java code.
|
||||
|
||||
SDK library
|
||||
-----------
|
||||
|
||||
So, finally it's time to add the SDK library. The library can come in
|
||||
two flavors, a JAR file or an Android project for ant. JAR is the
|
||||
easiest to integrate, just put it in the module directory and add it:
|
||||
|
||||
(Before Version 2.0)
|
||||
|
||||
.. code:: python
|
||||
|
||||
def can_build(plat):
|
||||
return plat=="android" or plat=="iphone"
|
||||
|
||||
def configure(env):
|
||||
if env['platform'] == 'android':
|
||||
# will copy this to the java folder
|
||||
env.android_module_file("MySingleton.java")
|
||||
env.android_module_manifest("AndroidManifestChunk.xml")
|
||||
env.android_module_library("MyLibrary-3.1.jar")
|
||||
|
||||
|
||||
(After Version 2.0)
|
||||
|
||||
.. code:: python
|
||||
|
||||
def can_build(plat):
|
||||
return plat=="android" or plat=="iphone"
|
||||
|
||||
def configure(env):
|
||||
if env['platform'] == 'android':
|
||||
# will copy this to the java folder
|
||||
env.android_add_java_dir("Directory that contain MySingelton.java")
|
||||
env.android_add_to_manifest("AndroidManifestChunk.xml")
|
||||
env.android_add_dependency("compile files('something_local.jar')") # if you have a jar, the path is relative to platform/android/java/gradlew, so it will start with ../../../modules/module_name/
|
||||
env.android_add_maven_repository("maven url") #add a maven url
|
||||
env.android_add_dependency("compile 'com.google.android.gms:play-services-ads:8'") #get dependency from maven repository
|
||||
|
||||
|
||||
SDK project
|
||||
-----------
|
||||
|
||||
When this is an Android project, things usually get more complex. Copy
|
||||
the project folder inside the module directory and configure it:
|
||||
|
||||
::
|
||||
|
||||
c:\godot\modules\mymodule\sdk-1.2> android -p . -t 15
|
||||
|
||||
As of this writing, Godot uses minsdk 10 and target sdk 15. If this ever
|
||||
changes, it should be reflected in the manifest template:
|
||||
`AndroidManifest.xml.template <https://github.com/godotengine/godot/blob/master/platform/android/AndroidManifest.xml.template>`
|
||||
|
||||
Then, add the module folder to the project:
|
||||
|
||||
(Before Version 2.0)
|
||||
|
||||
.. code:: python
|
||||
|
||||
def can_build(plat):
|
||||
return plat=="android" or plat=="iphone"
|
||||
|
||||
def configure(env):
|
||||
if env['platform'] == 'android':
|
||||
# will copy this to the java folder
|
||||
env.android_module_file("MySingleton.java")
|
||||
env.android_module_manifest("AndroidManifestChunk.xml")
|
||||
env.android_module_source("sdk-1.2","")
|
||||
|
||||
(After Version 2.0)
|
||||
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
As you probably modify the contents of the module, and modify your .java
|
||||
inside the module, you need the module to be built with the rest of
|
||||
Godot, so compile android normally.
|
||||
|
||||
::
|
||||
|
||||
c:\godot> scons p=android
|
||||
|
||||
This will cause your module to be included, the .jar will be copied to
|
||||
the java folder, the .java will be copied to the sources folder, etc.
|
||||
Each time you modify the .java, scons must be called.
|
||||
|
||||
Afterwards, just continue the steps for compiling android :ref:`doc_compiling_for_android`.
|
||||
|
||||
Using the module
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
To use the module from GDScript, first enable the singleton by adding
|
||||
the following line to engine.cfg (Godot Engine 2.0 and greater):
|
||||
|
||||
::
|
||||
|
||||
[android]
|
||||
|
||||
modules="org/godotengine/godot/MySingleton"
|
||||
|
||||
For Godot Engine 1.1 is
|
||||
|
||||
::
|
||||
|
||||
[android]
|
||||
|
||||
modules="com/android/godot/MySingleton"
|
||||
|
||||
More than one singleton module can be enabled by separating with commas:
|
||||
|
||||
::
|
||||
|
||||
[android]
|
||||
|
||||
modules="com/android/godot/MySingleton,com/android/godot/MyOtherSingleton"
|
||||
|
||||
Then just request the singleton Java object from Globals like this:
|
||||
|
||||
::
|
||||
|
||||
# in any file
|
||||
|
||||
var singleton = null
|
||||
|
||||
func _init():
|
||||
singleton = Globals.get_singleton("MySingleton")
|
||||
print(singleton.myFunction("Hello"))
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
(This section is a work in progress, report your problems here!)
|
||||
|
||||
Godot crashes upon load
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Check ``adb logcat`` for possible problems, then:
|
||||
|
||||
- Make sure libgodot_android.so is in the ``libs/armeabi`` folder
|
||||
- Check that the methods used in the Java singleton only use simple
|
||||
Java datatypes, more complex ones are not supported.
|
||||
|
||||
Future
|
||||
------
|
||||
|
||||
Godot has an experimental Java API Wrapper that allows to use the
|
||||
entire Java API from GDScript.
|
||||
|
||||
It's simple to use and it's used like this:
|
||||
|
||||
::
|
||||
|
||||
class = JavaClassWrapper.wrap(<javaclass as text>)
|
||||
|
||||
This is most likely not functional yet, if you want to test it and help
|
||||
us make it work, contact us through the `developer mailing
|
||||
list <https://groups.google.com/forum/#!forum/godot-engine>`__.
|
||||
Reference in New Issue
Block a user