UnityとAndroidネイティブの連携:UnityからネイティブのActivityを呼び出す[part1]

UnityとAndroidネイティブの連携 の投稿一覧

先日の投稿では、UnityPlayerNativeActivityを拡張したActivityに定義したメソッドの呼び出し検証をしました。
今回は、AndroidネイティブのActivity呼び出しをUnityのButtonから行います。

環境

  • OSX Yosemite v10.10.4
  • Unity v5.1.2f1
  • AndroidStudio v1.3.1
  • 検証端末 Nexus7(2012) v5.1.1

Androidプラグインを生成するまで

  1. 空のプロジェクトを作成
  2. NativeActivity(:app)のbuild.gradleの編集
  3. ActivityLauncher(:caller)のbuild.gradleの編集
  4. javaクラスの作成
  5. jar出力
空のプロジェクトを作成

AndroidStudioで例のごとくプロジェクトを新規作成し、ActivityはAddNoActivityを選択します。
すると、appというモジュールができます。

NativeActivity(:app)のbuild.gradleの編集

apply pluginを修正
アプリケーションではなく、プラグインとして使用するため修正します。
applicationIdを削除
アプリケーションではなく、プラグインとして使用するため削除します。
.jarを2つ追加
AndroidネイティブからUnityPlayerActivityを使えるようにするためにclasses.jarを、
Androidの機能を使えるようにするためandroid.jarを、
JavaLibraryのbuild.gradleを開いてdependenciesに追記します。
gradleタスクを追記
ファイルの一番下に追記する。

//apply plugin: 'com.android.application'  /*Androidプラグインとして利用するため修正*/
apply plugin: 'com.android.library'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        //applicationId "com.example.callactivitytest"  /*Androidプラグインとして利用するため削除*/
        minSdkVersion 22
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile files('/Applications/Unity/Unity.app/Contents/PlaybackEngines/AndroidPlayer/release/bin/classes.jar')  /*Androidプラグインとして利用するため追加*/
    compile files('/Users/ユーザ名/Library/Android/sdk/platforms/android-22/android.jar')  /*Androidプラグインとして利用するため追加*/
}

task clearJar(type: Delete) {
    delete 'build/libs/' + 'plugin.jar'
}
task makeJar(type: Copy) {
    from('build/intermediates/bundles/release/')
    into('release/')
    include('classes.jar')
    rename('classes.jar', 'plugin.jar')
}
makeJar.dependsOn(clearJar, build)
ActivityLauncher(:caller)のbuild.gradleの編集

.jarを2つ追加
AndroidネイティブからUnityPlayerActivityを使えるようにするためにclasses.jarを、
Androidの機能を使えるようにするためandroid.jarを、
JavaLibraryのbuild.gradleを開いてdependenciesに追記します。

apply plugin: 'java'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile files('/Applications/Unity/Unity.app/Contents/PlaybackEngines/AndroidPlayer/release/bin/classes.jar')  /*Androidプラグインとして利用するため追加*/
    compile files('/Users/ユーザ名/Library/Android/sdk/platforms/android-22/android.jar')  /*Androidプラグインとして利用するため追加*/
}

追記後、AndroidStudioのSync Project with Gradle Filesを実行しておく。
syncgradle

Androidプラグインとなるjavaファイルの作成

今回は2つのファイルを作成します。

  1. 呼び出され、Toast表示を行うActivity
  2. package com.example.callactivitytest;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.Toast;
    
    import com.unity3d.player.UnityPlayer;
    
    public class NativeActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle bundle) {
            super.onCreate(bundle);
    
            showToast();
        }
    
        public void showToast() {
            final Activity activity = UnityPlayer.currentActivity;
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(activity, "successful!", Toast.LENGTH_LONG).show();
                }
            });
        }
    }
  3. Activityのランチャー
  4. package com.example.util;
    
    import android.app.Activity;
    import android.content.Intent;
    
    public class ActivityLauncher {
    
        public static void launchActivity(String type, final Activity m_activity) {
            Intent i = new Intent();
            i.setAction(Intent.ACTION_MAIN);
            i.setClassName(m_activity,type);
    
            m_activity.startActivity(i);
        }
    }

それぞれ作成が終わった後の階層例
project_window

jar出力

jarを出力するためAndroidStudioのTerminalを開き、プロジェクトのrootに移動します。

  1. plugin.jar
  2. ./gradlew app:clean app:assembleDebug app:makeJar

    TerminalウィンドウにBUILD SUCCESSFULと表示されれば、jar出力は成功です。
    app/release直下にplugin.jarが出力されています。

  3. caller.jar
  4. ./gradlew jar

    caller/build/libs直下にcaller.jarが出力されています。

AndroidStudioでの操作は終わり、ここからはUnityの操作に移ります。

Unityから生成したAndroidプラグインを呼び出すまで

Androidプラグインの呼び出し方法として、今回はUnityのButtonを利用します。

  1. 空のプロジェクトを作成
  2. jarファイルとAndroidManifestの配置
  3. Buttonを作成する
  4. Buttonの押下イベントスクリプトを作成し、アタッチする
  5. ビルド、実機で実行できるか確認
空のプロジェクトを作成

Unityの新規プロジェクトを作成します。

jarファイルとAndroidManifestの配置

配置先のディレクトリを作成
プロジェクトを新規作成した段階ではAssets/Plugins/Androidは存在しないので、自分で作成します。
.jarファイルの配置
Assets/Plugins/Android/直下に、先ほど作成した.jarファイル2つを配置します。
AndroidManifestファイルの作成、配置
AndroidのActivityを呼び出す場合、AndroidManifestファイルが必要になります。
作成したファイルはAndroidプラグインの.jarファイルと同じディレクトリに配置します。




    
        
        
            
            
            
                  /*最初に起動するActivityに指定する*/
                  /*ホームのアイコンから起動可能にする*/
            
        
        
		
		
    
	
Buttonを作成する

Hierarchyウィンドウを右クリックし、UI > Buttonを選択しButtonを作成します。

Buttonの押下イベントスクリプトを作成し、アタッチする

この時点ではまだ何もButtonの押下イベントは定義されていません。
On Click()に対して、次の設定をしていきます。

  1. 押下イベントのスクリプトを作成する
  2. using UnityEngine;
    using System.Collections;
    
    public class ActivityLauncher : MonoBehaviour {
    
    	public void LaunchActivity() {
    		 
    		AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); 
    		AndroidJavaObject currentUnityActivity = unityPlayer.GetStatic("currentActivity"); 
    		
    		AndroidJavaClass plugin = new AndroidJavaClass("com.example.util.ActivityLauncher"); 
    		plugin.CallStatic("launchActivity", "com.example.callactivitytest.NativeActivity", currentUnityActivity );
    	}
    }
  3. Inspectorからスクリプトをアタッチ
  4. AddComponentから作成したスクリプトを選択するか、そのままInspectorウィンドウにスクリプトアイコンをドロップすればアタッチできます。

  5. 押下イベントのメソッドを設定
  6. 押下時に発火するメソッドを指定します。今回は、LaunchActivity指定してあります。

設定後のInspectorウィンドウ
inspector_button

ビルド、実機で実行できるか確認

calltest_ss1 calltest_ss2
ボタンを押すとネイティブのActivity画面が開き、Toast表示が正常に動いた。
1枚目が起動直後。ボタン押下時に2枚目が表示される。
デバイスのソフトウェアバックボタンを押すことで、2枚目のActivity画面から1枚目のUnity画面に戻る。

UnityEditor上では検証できない。
実行しようとしても、”Exception: JNI: Init’d AndroidJavaClass with null ptr!”のエラーとなる。