いんでぃーづ

ゲームいろいろ、いろいろ自由

Unity : Androidプラグインを作る一番簡単な方法

AndroidiPhoneの通知機能やらなにやらを使いたいときはよくあります。 アセット使えば手っ取り早いんですけど、かゆいところに届かないところもあるので、自前で用意する方法をちょろっと書いてみます。

今回はAndroidです。 Android開発やったことない人には、ちんぷんかんぷんかと思いますのでご注意。


目次

AndroidStudioでプラグインを作る

もはやAndroid開発でEclipseなんて使ってるのは相当アレなエンジニアもしくはアレな案件に従事している方だと思いますが、いちおう断りを入れておくと今回はAndroidStudio(2.2.1)を使います。

https://developer.android.com/studio/index.html

新規プロジェクトを作る

まずは普通にプロジェクトを作りましょう。Activityはあってもなくてもいいです。

ライブラリ用モジュールの作成

プロジェクトを作成したら、メニューから新規モジュールを作成します。

File > New > New Module

f:id:sugar_affordance:20161209151137p:plain

モジュールの種別選択でAndroid Libraryを選択してください。

f:id:sugar_affordance:20160714122247p:plain

ここではモジュール名をDialog-Pluginとしておきます。

Unityからアクセスするクラスを作成する

ライブラリ用モジュールにクラスを作成します。

package jp.co.test.dialog_plugin;

import android.app.AlertDialog;
import android.content.Context;

public class NativeDialog {

    static public void showMessage(Context context, String title, String message) {

        new AlertDialog.Builder(context)
                .setTitle(title)
                .setMessage(message)
                .setPositiveButton("YES, YES, YES!", null)
                .setNegativeButton("...No?", null)
                .show();
    }
}

呼び出したいメソッドは static関数 として定義しておきます。 Context渡してるけどUnityからどうやって受け取るねん! という心配はご無用なのでまんじゅうでも食っててください。

ライブラリのビルド

次にGradleスクリプトを実行してライブラリをビルドします。 Gradleペイン を開き、dialog-pluginモジュールのTasks > build > assembleをダブルクリックします。

f:id:sugar_affordance:20160714122353p:plain

すると、プロジェクトフォルダ内のdialog-plugin/build/outputs/aar フォルダにdialog-plugin-debug.aar、dialog-plugin-release.aarというファイルが作成されます。これがライブラリの本体です。
どっち使ってもいいんですが、今回は dialog-plugin-debug.aar を使っておきます。

ライブラリの拡張子について

アセットなどで拡張子が .jar になっているファイルを見たことがあると思いますが、今回作成したのは .aar です。 aarはAndroid用のライブラリ用の拡張子で、リソースファイルやManifestファイルも内包されています。 Unityはjarだけでなくaar形式にも対応していて、こっちのほうがあつかいが簡単です。

Unityからプラグインを呼び出す

とりあえず適当にプロジェクトを作りましょう。

aarを配置する

Assets/Plugins/Android という構造でフォルダを作り、Androidフォルダの中に dialog-plugin-debug.aar を置きます。

f:id:sugar_affordance:20160714122433p:plain

これだけでJavaのメソッドを呼び出す準備は完了です。

あ、プロジェクト設定はAndroidにSwitchPlatformしておきましょう。

プラグインを呼び出す

Unity側のソースは以下のようにします。

using UnityEngine;
using System.Collections;

public class AndroidDialogTest : MonoBehaviour {

    void Start () {
        ShowDialog ();
    }
    
    void Update () {
    
    }

    void ShowDialog() {
        #if UNITY_ANDROID
        // Javaのオブジェクトを作成
        AndroidJavaClass nativeDialog = new AndroidJavaClass ("jp.co.test.dialog_plugin.NativeDialog");

        // Context(Activity)オブジェクトを取得する
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); 
        AndroidJavaObject context  = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

        // AndroidのUIスレッドで動かす
        context.Call ("runOnUiThread"new AndroidJavaRunnable(() => {

            // ダイアログ表示のstaticメソッドを呼び出す
            nativeDialog.CallStatic (
                "showMessage",
                context,
                "おっさんの主張",
                "もうやってられまへーん"
            );
        }));
        #endif
    }

}

プラグインのクラスにアクセスするには AndroidJavaClass を使用します。引数には作成したクラスのパッケージ名を与えます。 Unityアプリを実行しているActivityやContextを取得する際も同様です。

ビルドして端末にインストール

USBで端末接続してBuild & Run すれば、みっともないダイアログが出るのでやってみよう!

プラグインからUnityの関数を呼び出す

長くなるのでこちらにまとめました

indie-du.com

注意するエラー

minSdkVersionがあってない

下のようなエラーが出る場合、minSdkVersionの設定が合ってないです。

Error: [Temp/StagingArea/AndroidManifest-main.xml:12, /xxxxxxx/AndroidManifest.xml:3] Main manifest has <uses-sdk android:minSdkVersion='9'> but library uses minSdkVersion='19'

AndroidStudioのdialog-pluginのbuild.gradleを開くと、

applyplugin:'com.android.library'

android{
  compileSdkVersion 23
  buildToolsVersion "23.0.3"

  defaultConfig{
    minSdkVersion 19
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
  }
...

こんな感じになってると思いますが、minSdkVersion 19 となってますね。

ひるがえってUnityでBuildSettingsからPlayerSettingsを開くと、

f:id:sugar_affordance:20160714122514p:plain

デフォルト値が API Level9になっています。 ここをプラグインより大きい値にする必要があります。

なんか知らんが動かん

logcat でエラーが出てないかチェックしましょう。 java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() とか出てる場合、UIスレッドで動かないといけないので注意。 今回のソースの

context.Call ("runOnUiThread"new AndroidJavaRunnable(() => {

の部分ね。

あとインターネット接続してるのにManifestにパーミッション書いてないとかね。

    <uses-permission android:name="android.permission.INTERNET" />

を追加しろよね!

iPhoneは?

いつか書く。

・参考 http://docs.unity3d.com/ja/current/ScriptReference/AndroidJavaClass.html


“Unity” and Unity logos are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere, and are used under license.


免責事項

当サイトの広告バナー、リンクによって提供される情報、サービス内容について、当サイトは一切の責任を負いません。

また、当サイトの情報を元にユーザ様が不利益を被った場合にも、当サイトは一切の責任を負いません。

すべて自己責任でお願いします。