Androidプラグインの作成

はじめに

モバイルゲームの収益化が現われるまでは、ビデオゲームをポータブル型にするのはまったく問題ありません。

このエリアは複雑です。通常、収益化を行うモバイル ゲームでは、次のような目的でサーバーへの特別な接続が必要です。

  • 分析
  • アプリ内購入
  • 証明書の検証
  • トラッキングのインストール
  • 広告
  • 動画広告
  • クロスプロモーション
  • ゲーム内のソフト通貨とハード通貨
  • プロモーションコード
  • A/B テスト
  • ログイン
  • クラウド保存
  • ランキングとスコア
  • ユーザーサポートとフィードバック
  • Facebook、Twitterなどへの投稿。
  • プッシュ通知

On iOS, you can write a C++ module and take advantage of the C++/ObjC intercommunication. Even using GDNative is possible to make it a plug-in.

On Android, interfacing with C++ through JNI (Java Native Interface) isn't as flexible, so writing plugins is considerably more work.

It is also possible that you just want to do modifications to the Android export template, and by using a plugin your project can remain compatible with newer Godot versions (as the android source template will get updated on each release).

Maybe REST

Most of these APIs allow communication via REST/JSON APIs. If the API is relatively simple and does not require complex authentication, this may be a better idea than writing a specific Android plugin.

Godot has great support for HTTP, HTTPS and JSON, so an API implemented this way will work on every platform, too.

Of course, in most of the cases, it's easier to just write an Android plugin, so keep reading.

Androidプラグイン

Godot 3.2以降、Androidプラグインを作成できるようになりました。また、非常に簡単です!エンジンを再コンパイルする必要はなくなりました。

Before anything, make sure you understand how to set up a custom build environment for Android.

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).

Once created, there are certain rules to follow, but they are simple.

Android directories

Inside your plugin folder, you can use the standard folders as if they were from an Android Gradle project. Examples of this are:

src/ - For Java source code, same as in your Android project
res/ - For resources
aidl/ - For interfaces
assets/ - For assets that will be included as-is on export
libs/debug - For debug JNI libraries
libs/release - For release JNI libraries

Gradle will treat them as part of the project automatically when building, same as the default project files.

"Chunk" files

It is now possible to modify "AndroidManifest.xml" and build.gradle in "res://android/build" directly and Godot will keep your changes when building. The problem, however, is that if you update Godot, you will also need to update the build/ folder and your changes will be lost.

To overcome this, the Godot Android Plugin system lets you create chunk files, where you can specify little bits that can be inserted in both "AndroidManifest.xml" and build.gradle. They are inserted every time Godot builds the project for export or deploy.

AndroidManifest.conf

This file allows to insert bits of chunk into AndroidManifest.xml, the following are supported tags and are entirely optional:

[user_permissions]

Any bit of text below this tag is inserted inside the <manifest> tag of the file. This is often used for permission tags.

[application]

Any bit of text below this tag inside the <application> tag of the file. Many SDKs require this.

[application_attribs]

These are attributes you can add at the end of the <application> tag. Some SDKs require this.

gradle.conf

This file allows to insert bits of chunk into build.gradle, the following are supported and are entirely optional:

[buildscript_repositories]

Any bit of text below this tag is inserted inside the buildscript.repositories section of the build file.

[buildscript_dependencies]

Any bit of text below this tag is inserted inside the buildscript.dependencies section of the build file.

[allprojects_repositories]

Any bit of text below this tag is inserted inside the allprojects.repositories section of the build file.

[dependencies]

Any bit of text below this tag is inserted inside the dependencies section of the build file.

[android_defaultconfig]

Any bit of text below this tag is inserted inside the android.defaultconfig section of the build file.

[global]

Any bit of text below this tag is inserted inside the global scope of the build file.

Javaシングルトン

通常、Androidプラグインにはそれをロードするシングルトンクラスがあり、このクラスは Godot.SingletonBase を継承します。モジュールに指定した追加リソースのリソース識別子は com.godot.game.R クラスに含まれるため、インポートする必要があります。

シングルトンオブジェクトテンプレートは次のとおりです:

package org.godotengine.godot;

import android.app.Activity;
import android.content.Intent;
import android.content.Context;
import com.godot.game.R;
import javax.microedition.khronos.opengles.GL10;

public class MySingleton extends Godot.SingletonBase {

    protected Activity appActivity;
    protected Context appContext;
    private Godot activity = null;
    private int instanceId = 0;

    public String myFunction(String p_str) {
        // A function to bind.
        return "Hello " + p_str;
    }

    public void getInstanceId(int pInstanceId) {
        // You will need to call this method from Godot and pass in the get_instance_id().
        instanceId = pInstanceId;
    }

    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",
                "getInstanceId"
            });
        this.appActivity = p_activity;
        this.appContext = appActivity.getApplicationContext();
        // You might want to try initializing your singleton here, but android
        // threads are weird and this runs in another thread, so to interact with Godot you usually have to do.
        this.activity = (Godot)p_activity;
        this.activity.runOnUiThread(new Runnable() {
                public void run() {
                    // Useful way to get config info from "project.godot".
                    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 onMainRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {}

    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.

}

Godotにコールバックする

JavaからGodotにコールバックするのはもう少し難しいです。 最初にスクリプトのインスタンスIDを知る必要があります。これは、スクリプトで get_instance_ID() を呼び出すことで取得されます。 これは、Javaに渡すことができる整数を返します。

Javaから、 calldeferred 関数を使用してGodotと通信します。Javaは別のスレッドで実行される可能性が高いので、呼び出しは延期されます:

GodotLib.calldeferred(<instanceid>, "<function>", new Object[]{param1, param2, etc});

Godotはこのシングルトンを検出し、適切なタイミングで初期化します。

GDScriptから使用する

最初に、ロードするAndroidモジュールにシングルトンを追加する必要があります。 「プロジェクト -> プロジェクト設定」に進みます。次に、「一般」タブで「Android」セクションに移動し、モジュール部分にモジュール名を入力します。モジュールには完全なJavaパスが含まれている必要があります。例: org/godotengine/godot/MySingleton

../../../_images/android_modules.png

次に、スクリプトから:

if Engine.has_singleton("MySingleton"):
    var singleton = Engine.get_singleton("MySingleton")
    print(singleton.myFunction("World"))

トラブルシューティング

ロード時にGodotがクラッシュする

adb logcat で問題がないかチェックしてください:

  • 「libgodot_android.so」が `` libs / armeabi`` フォルダーにあることを確認してください
  • Javaシングルトンで使用されるメソッドは単純なJavaデータ型のみを使用し、より複雑なメソッドはサポートされていないことを確認します。

未来

Godotには実験的なJava APIラッパーがあり、GDScriptからJava API全体を使用できます。

使い方は簡単で、次のように使用します:

class = JavaClassWrapper.wrap(<javaclass as text>)

これはまだ機能していない可能性があります。テストして機能させるために、irc.freenode.org:#godotengine-develでご連絡ください。