Unity

UnityのAndroid向けプラグインで、Unity側からServiceを停止する方法

プラグイン開発についての記事

Unityで開発している時にどうしても付けたい機能が、OS側のネイティブプラグインにあることが多々あります。

ゲーム作成ではどうしても避けられないプラグイン開発。なんとか実装できるようになったので、今回は初歩的なものから紹介していきます。

ただし自己流ですので間違ってたり、効率が悪かったり、スマートなやり方でないかもしれません。修正案等ありましたらコメントで教えていただけると幸いです。

テーマはUnity側からServiceを停止させる。

簡単にできるような気がしてたのですが、割とどこにも見当たらなかったので無理やり作りました。

まずはプラグインの作り方??という方には

こちらで詳しい解説をして下さっています。

さて本題に入ります。

Seviceを開始するときはActivityから起動するというのが基本だと理解しているのですが、今回の設計ではSeviceの開始と終了には同じActivityを呼び出して、IntentにputExtraしたidで挙動を識別しました。

ますはActivityを見ます。

public class DemoActivity  extends Activity {

    //サービスを起動するアクティビティー

    Intent intent;
    private int st;
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        intent = new Intent(getApplicationContext(), DemoServise.class);
        Intent intent = getIntent();
        st = intent.getIntExtra("pre_id", 1);
        intent.putExtras(intent);

    }

    @Override
    public void onStart() {
        super.onStart();

        //DemoServise開始時はIDが1、終了時は0が投げられる
        if(st == 1){
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
                startForegroundService(intent);
            }else{
                startService(intent);
            }
        }
        else{stopService(intent);}

        finish();
    }

    public void onDestroy() {
        super.onDestroy();
    }
}

例としてDemoActivityを記述しました。

Intentに”pre_id”として0か1を入れておきます。今回の例では開始時には1を入れます。stにgetIntExtraでidを格納して、onStart()の時に分岐でstartServiceかstopServiceへ進みます。

バックグラウンド処理用にForegroundServiceとの分岐も入れてみました。

Unity側のコード

今度はUnity側のコードを見ます。

    public static void LocalServiceStart()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
		    m_plugin.CallStatic("DemoLoad", context, 1);
#else
        Debug.LogWarning("This asset is for Android only. It will not work inside the Unity editor!");
#endif
    }

    public static void LocalServiceEnd()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
		    m_plugin.CallStatic("StopService", context, 0);   
#else
        Debug.LogWarning("This asset is for Android only. It will not work inside the Unity editor!");
#endif
    }

m_pluginにはAndroidJavaObjectを入れてください。

この例では直接Activityを呼び出すのではなくて、一旦Managerクラス内の関数をコールします。そのためAndroidJavaObjectにはManagerクラスを格納します。

contextは

		unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); 
		context  = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

このようなものが入ってます。

Staticな関数を呼び出していますのでCallStaticしています。

上で開始準備をして、サービス終了のタイミングになったら今度は下の関数で、サービス終了の準備をコールします。

どちらも第2引数にIntを入れます。開始側には1を、終了側には0を入れます。

Java側のマネージャークラスを見ます。

    //サービスを実行するためのアクティビティ開始
    public static void startDemoActivity(Context con,  int preid){
        Intent intent = new Intent(con, DemoActivity.class);

        intent.putExtra("pre_id", preid); //開始用ID

        con.startActivity(intent); //アクティビティーを作りそこからサービスを開始する
    }

    //サービスを停止するためのアクティビティ開始
    public  static void StopDemoActivity(Context con, int st){
        Intent intent = new Intent(con, DemoActivity.class);
        intent.putExtra("pre_id", st); //停止用ID
        con.startActivity(intent); //アクティビティーを作り停止する
    }

Unity側からのコールはすべてManagerクラスで受けます。

引数で受け取ったpreidをputExtraを使ってIntentに追加します。

まとめ

以上でUnity側からJavaのServiceを停止する方法でした。

何かもっといい方法があるかもしれませんが現状知っているのはこれと、もう一つで、サービス内のtimerオブジェクトでStaticな変数フラグを0.1秒に1回確認させておいて、マネージャークラスからStaticな変数フラグを変更してstopSelf()させるというもの。

最初に後者を思いついたのですがあまり冴えた方法ではないかと思い、今回の方法へシフトしました。

他にもっといい方法があるというご意見があればぜひコメントで教えてくださると嬉しいです。

それではご精読ありがとうございました。

 

 

0件のコメントを表示

コメントする