Unity、Activity、Service間のアクセスの方法。
最初に、各クラスの呼び出し方をシーケンスにしました。サンプルコードはこの記事の最後にあります。
この方法しかないわけではありません。
ただ、ゼロから探すよりは、一つの方法が分かっている方が、他の選択肢も検討しやすいかと思いました。
Unity → Activity
Unity側:AndroidJavaObject.Call()
Unity(C#)
AndroidJavaClass c = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject activity = c<AndroidJavaObject>("currentActivity"); activity.Call("callTestFunc");
3行目:Call() の第一引数は関数名、第二引数以降はAndroid側の呼び出し関数の引数です。
Android側:UnityPlayerActivity継承クラス+AndroidManifest.xml
UnityPlayerActivity継承クラス(Java)
package com.companyname.appname; import com.unity3d.player.UnityPlayerActivity; public class MyActivity extends UnityPlayerActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } public void callTestFunc() { Log.d( "[Unity Test]", "callTestFunc called" ); } }
11行目:Unityから呼び出される関数。
自作クラスをメインアクティビティにするため、併せて AndroidManifest.xml を設置します。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application> <activity android:name="com.companyname.appname.MyActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
4行目:"com.companyname.appname.MyActivity" の部分は、自作クラスの [パッケージ名.Activity名]。
Android → Unity
Android側:UnityPlayer.sendMessage()
UnityPlayerActivity継承クラス(Java)
import com.unity3d.player.UnityPlayer; UnityPlayer.UnitySendMessage("ゲームオブジェクト名", "関数名", "CALLBACK_ID");
3行目:UnitySendMessage()
第1引数:ゲームオブジェクト名
第2引数:コンポーネントの関数名
第3引数:string
第1引数は、クラス(コンポーネント名)でなく、そのコンポーネントを取り付けたゲームオブジェクト名です。
第3引数は、関数の呼び側と受け側でやりとりができる唯一の領域になります。そのため、IDを入れるのが通例ではないかと思います。
第1引数、第2引数は、UnityからActivityに名前を渡しておくことで、より汎用的に使用できます。
kan-kikuchi.hatenablog.com
Unity側:コールバック関数
Unity(C#)
public void onCallBack(string message) { if( message == "CALLBACK_ID" ){ Debug.Log( "Unity : called onCallBack" ); } }
関数の名称は任意です。
(先述の UnitySendMessage() 第2引数 に指定)
Activity → Service
Activity側:startService(Intent)+AndroidManifest.xml
UnityPlayerActivity継承クラス(Java)
import android.content.Intent; Intent serviceIntent = new Intent(MyActivity.this, サービス名.class); serviceIntent.putExtra( "REQUEST_CODE", 1 ); startService(serviceIntent);
3行目:Intentは使いづらいイメージがあるかもしれませんが、ただの容れ物です。値をセットして、様々な関数に引数で渡すだけです。
Intent(Context packageContext, Class cls)
第1引数:呼び元(Contextへの参照)
第2引数:呼び先(newしたいクラスの名前)
Service側:onStartCommand()
Service(Java)
package com.companyname.appname; import android.content.Intent; public class MyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { modeRequested = intent.getIntExtra( "REQUEST_CODE", 0 ); if( requestCode == 1 ){ Log.d("onStartCommand called"); } } }
特別な識別子(ID)を含めます。上のコードの場合は"REQUEST_CODE"というキーを使用して確認しています。
AndroidManifest.xml の <activity> タグ内にサービスの利用を宣言します。
AndroidManifest.xml
<application <!-- Service定義 --> <service android:name="com.companyname.appname.MyService" /> </application>
Service → Activity
Service側:Context.sendBroadcast(Intent)
Service(Java)
Intent broadcastIntent = new Intent(); broadcastIntent.putExtra( "REQUEST_CODE", 10 ); getBaseContext().sendBroadcast(broadcastIntent);
※BroadcastReceiveerを使わない方法もあるかもしれません。
Activity側:BroadcastReceiver.onReceive()
UnityPlayerActivity継承クラス(Java)
import android.content.BroadcastReceiver; // bradcastReceiverの定義 public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // intentからのデータの取り出し int requestCode = intent.getIntExtra("REQUEST_CODE", 0); if( requestCode == 10 ){ Log.e("[Unity Test]", "MyBroadcastReceiver received"); } } } // broadcastReceiverの登録 receiver = new MyBroadcastReceiver(); intentFilter = new IntentFilter(); intentFilter.addAction("MY_ACTION"); // 必ずActionを含める registerReceiver(receiver, intentFilter);
サンプルコード
[Unity]TestComponent.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestComponent : MonoBehaviour { void Start(){ AndroidJavaClass c = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject activity = c<AndroidJavaObject>("currentActivity"); activity.Call("callTestFunc"); } // Activity → Unity public void onCallBack(string message) { if( message == "CALLBACK_ID" ){ Debug.Log( "Unity : called onCallBack from Android." ); } } }
package com.companyname.appname; // Unity → Activity import com.unity3d.player.UnityPlayerActivity; // Activity → Unity import com.unity3d.player.UnityPlayer; // Activity → Service import android.content.Intent; // Service → Activity import android.content.BroadcastReceiver; public class MyActivity extends UnityPlayerActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } // Unity → Activity public void callTestFunc() { Log.d( "[Unity Test]", "callTestFunc called" ); // broadcastReceiverの登録 receiver = new MyBroadcastReceiver(); intentFilter = new IntentFilter(); intentFilter.addAction("MY_ACTION"); // 必ずActionを含める registerReceiver(receiver, intentFilter); // Activity → Service Intent serviceIntent = new Intent(MyActivity.this, MyService.class); serviceIntent.putExtra( "REQUEST_CODE", 1 ); startService(serviceIntent); } // Service → Activity public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // intentからのデータの取り出し int requestCode = intent.getIntExtra("REQUEST_CODE", 0); if( requestCode == 10 ){ Log.e("[Unity Test]", "MyBroadcastReceiver received"); // Activity → Unity UnityPlayer.UnitySendMessage(unityGameObjectName, unityCallbackFunc, "CALLBACK_ID"); } } } }
package com.companyname.appname; import android.content.Intent; public class MyService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { modeRequested = intent.getIntExtra( "REQUEST_CODE", 0 ); if( requestCode == 1 ){ Log.d("onStartCommand called"); // Service → Activity Intent broadcastIntent = new Intent(); broadcastIntent.putExtra( "REQUEST_CODE", 10 ); getBaseContext().sendBroadcast(broadcastIntent); } } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application> <activity android:name="com.companyname.appname.MyActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- Service定義 --> <service android:name="com.companyname.appname.MyService" /> </application> </manifest>
(以上)