くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

【チラ裏】Androidのダイアログを呼び出すUnityPlayerNativeActivity

チラ裏。本当のメモです。あしからず

UnityでAndroidを開発している時の試行錯誤の末路。
AndroidのMainActivityを生成するときのテンプレート(UnityPlayerNativeActivity)をカスタマイズし、 UnityのC#からAndroid標準のファイルChoserを呼び出してファイルパスを取得できるようにやったときのめも。うまくいっている気はする。

呼び出され側

<Unity_home>\Editor\Data\PlaybackEngines\androidplayer\com\unity3d\player のUnityPlayerNatieActivity.javaを編集

package com.unity3d.player;

import android.app.NativeActivity;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.net.Uri;
import android.content.Intent;

public class UnityPlayerNativeActivity extends NativeActivity
{
    private static final int REQUEST_GALLERY = 0;
    private boolean isRoad = false;
    private String filepath = null;

    protected UnityPlayer mUnityPlayer;        // don't change the name of this variable; referenced from native code

    // Setup activity layout
    @Override protected void onCreate (Bundle savedInstanceState)
    {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);

        getWindow().takeSurface(null);
        setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
        getWindow().setFormat(PixelFormat.RGB_565);

        mUnityPlayer = new UnityPlayer(this);
        if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
            getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
                                   WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(mUnityPlayer);
        mUnityPlayer.requestFocus();
    }

    // Quit Unity
    @Override protected void onDestroy ()
    {
        mUnityPlayer.quit();
        super.onDestroy();
    }

    // Pause Unity
    @Override protected void onPause()
    {
        super.onPause();
        mUnityPlayer.pause();
    }

    // Resume Unity
    @Override protected void onResume()
    {
        super.onResume();
        mUnityPlayer.resume();
    }

    // This ensures the layout will be correct.
    @Override public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        mUnityPlayer.configurationChanged(newConfig);
    }

    // Notify Unity of the focus change.
    @Override public void onWindowFocusChanged(boolean hasFocus)
    {
        super.onWindowFocusChanged(hasFocus);
        mUnityPlayer.windowFocusChanged(hasFocus);
    }

    // For some reason the multiple keyevent type is not supported by the ndk.
    // Force event injection by overriding dispatchKeyEvent().
    @Override public boolean dispatchKeyEvent(KeyEvent event)
    {
        if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
            return mUnityPlayer.injectEvent(event);
        return super.dispatchKeyEvent(event);
    }

    // Pass any events not handled by (unfocused) views straight to UnityPlayer
    @Override public boolean onKeyUp(int keyCode, KeyEvent event)     { return mUnityPlayer.injectEvent(event); }
    @Override public boolean onKeyDown(int keyCode, KeyEvent event)   { return mUnityPlayer.injectEvent(event); }
    @Override public boolean onTouchEvent(MotionEvent event)          { return mUnityPlayer.injectEvent(event); }
    /*API12*/ public boolean onGenericMotionEvent(MotionEvent event)  { return mUnityPlayer.injectEvent(event); }


    // Extend
    public void pickPhoto() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(intent, REQUEST_GALLERY);
        isRoad = true;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        if(requestCode == REQUEST_GALLERY && resultCode == RESULT_OK) {
            try {
                String[] columns = { MediaColumns.DATA };
                Cursor cursor = getContentResolver().query(data.getData(),
                        columns, null, null, null);
                if (cursor.moveToFirst()) {
                    File file = new File(cursor.getString(0));
                    filepath = file.getAbsolutePath();
                }
            } catch (Exception e) {
                filepath = null;
            } finally {
                isRoad = false;
            }
        } 
    }

    public boolean isRoading() {
        return isRoad;
    }

    public String getPath() {
        return filepath;
    }
}

呼び出す側

using UnityEngine;
using System.Collections;

public class PickPhoto : MonoBehaviour {
    private static string activity = "com.unity3d.player.UnityPlayer";
    enum PpState {PICKSTART, PICKING, DEFAULT};
    private PpState state = PpState.DEFAULT;
    private AndroidJavaClass cUnityPlayer;
    private AndroidJavaObject oCurrentActivity;

    // Use this for initialization
    void Start () {
        // Find the UnityPlayer and get the static current activity
        cUnityPlayer = new AndroidJavaClass (activity);
        oCurrentActivity = cUnityPlayer.GetStatic<AndroidJavaObject> ("currentActivity");
    }
    
    // Update is called once per frame
    void Update () {
        switch (state) {
            case PpState.PICKING:
                if(!IsRoading()) {
                    state = PpState.DEFAULT;
                    SetImage(GetPath());
                }
                break;
            case PpState.PICKSTART:
                PickStart();
                state = PpState.PICKING;
                break;
            case PpState.DEFAULT:
                if (Input.GetMouseButtonDown(0)) {
                    state = PpState.PICKSTART;
                }           
                break;
        }
    }

    void PickStart() {
        oCurrentActivity.Call("pickPhoto");
    }

    bool IsRoading() {
        return oCurrentActivity.Call<bool>("isRoading");
    }

    string GetPath() {
        return oCurrentActivity.Call<string>("getPath");
    }

    void SetImage(string filepath) {
        // Debug.Log("path:" + GetPath());

        GameObject go = GameObject.Find("GameMaster");
        go.GetComponent<GMSelectChara>().setImage(filepath);
    }
}

[PR] めもらばではこんなあぷりを作っています!