티스토리 뷰
출처 : 안드로이드(Android) 유니티(Unity3D) 연동 ,값전달, Toast, Dialog 등...
[android] 메시지 핸들러(Handler) 사용하기
[안드로이드] 유니티 C# 클래스와 자바 클래스간의 연동
Trying to create a simple AlertDialog plugin, crash occurs
Platform Dependent Compilation
20. 카드 짝찾기 게임(7) - 안드로이드용으로 변환 (Keystore 사용 빌드)
Unity에서 Android Activity와 연동하기 위해 Unity C# 소스 작성
Unity의 AndroidJavaObject 객체를 이용해서 Android에 호출하고 호출한 결과값은 바로 받을 수 없어 로직이 끝나고 다시 Android Activity에서 Unity C# 함수를 호출해서 결과 값을 받을 수 있습니다.
아래 예제는 Cs_CubeManager을 싱글톤 객체로 만들어서 AndroidJavaObject 객체를 Unity 전체에서 사용하도록 했으며, Cs_AndroidManager에서 AndroidJavaObject 객체를 할당 받도록 했습니다.
Android호출시 다른 Activity를 생성하거나 Toast 메시지 출력시 아래와 같이 오류가 발생하므로 Handle 사용해야 합니다.
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
개발시나 iOS에서는 동작하지 않도록 preprocessor로 UNITY_ANDROID를 사용하여, Android에서만 동작할 수 있도록 소스작성 합니다.
#if UNITY_ANDROID // 유니티가 동작하는 액티비티를 저장하는 변수. public AndroidJavaObject activity = null; #endif
Android Activity와 연동하기 위해서 C# AndroidJavaObject 객체를 아래와 같이 할당 받아야 합니다.
AndroidJavaObject activity = null; AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); cubeMng.activity = jc.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject 객체의 Call 메소드를 호출 하여 Android Activity의 메소드를 호출합니다.
public void NativeAlert(string message) { #if UNITY_ANDROID // 유니티가 동작하는 액티비티를 저장하는 변수. activity.Call("AlertMessage", message); #endif }
Cs_AndroidManager.cs
using UnityEngine; public class Cs_AndroidManager : MonoBehaviour { //private static Cs_AndroidManager _instance = null; private Cs_CubeManager cubeMng; public string androidLog = "No Log"; void Start() { cubeMng = Cs_CubeManager.getInstance(); cubeMng.device_model = "test"; #if UNITY_ANDROID AndroidCall(); #endif } #if UNITY_ANDROID // 유니티가 동작하는 액티비티를 저장하는 변수. //public AndroidJavaObject activity = null; void AndroidCall() { // 현재 실행 중인 유니티 액티비티를 가져와서 변수에 저장. //AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); cubeMng.activity = jc.GetStatic<AndroidJavaObject>("currentActivity"); cubeMng.activity.Call("initActivity", "Cs_AndroidManager"); } #endif // 자바 클래스로부터 전달받은 로그를 보여줍니다. public void AndroidLog(string newAndroidLog) { androidLog = newAndroidLog; } public void SetCountryCode(string code) { cubeMng.country_code = code; } public void SetDeviceID(string did) { cubeMng.device_id = did; } public void SetDeviceModel(string dModel) { cubeMng.device_model = dModel; } /* public static Cs_AndroidManager Instance { get { if (_instance == null) { Debug.Log("------------- _instance.0 = " + _instance); _instance = FindObjectOfType(typeof(Cs_AndroidManager)) as Cs_AndroidManager; Debug.Log("------------- _instance.1 = " + _instance); if (_instance == null) { _instance = new GameObject("Cs_AndroidManager").AddComponent<Cs_AndroidManager>(); } Debug.Log("------------- _instance.2 = " + _instance); } return _instance; } } */ }
Cs_CubeManager.cs
using UnityEngine; using System; public class Cs_CubeManager { // 싱글톤 인스턴스 private static Cs_CubeManager instance = null; public string country_code = "KOR"; public string device_id = ""; public string device_model = ""; #if UNITY_ANDROID // 유니티가 동작하는 액티비티를 저장하는 변수. public AndroidJavaObject activity = null; #endif private Cs_CubeManager() { /* if (Camera.mainCamera != null && Camera.mainCamera.GetComponent("WWWWiki") != null) wWWWiki = Camera.mainCamera.GetComponent("WWWWiki") as WWWWiki; */ } public static Cs_CubeManager getInstance() { if (instance == null) { instance = new Cs_CubeManager(); } return instance; } public void NativeAlert(string message) { #if UNITY_ANDROID // 유니티가 동작하는 액티비티를 저장하는 변수. activity.Call("AlertMessage", message); #endif } }
Unity3D 에서 Android 소스로 Export 하기
1. 메뉴 [Build Settings...] 선택합니다.
2. [Build Settings] 화면에서 Platform 목록에서 Android 항목을 선택합니다.
3. Bundle Identifier에 Android에서 사용할 Package 명을 입력합니다.
4. 다시 [Build Settings] 화면에서 Create Eclipse project 체크 박스를 선택하고, 버튼 [Export]을 선택합니다.
5. Export 받을 경로를 선택하고, 버튼 [폴더 선택]을 선택합니다.
6. 탐색기로 아래와 같이 Export 받은 파일 목록을 확인 합니다.
파일 목록에서 classes.jar 파일을 확인 할 수 있는데,
C:\Program Files (x86)\Unity\Editor\Data\PlaybackEngines\androidplayer\bin 폴더의 classes.jar 파일과 동일한 파일로
Unity에서 Export 받으면 자동으로 classes.jar 파일을 복사해서 빌드 라이브러리에 자동으로 추가 됩니다.
7. [Package Explorer] 에서 오른쪽 버튼을 선택해서, 팝업 메뉴에서 메뉴 [Import...]를 선택합니다.
8. 메뉴 [Existing Projects into Workspace]를 선택합니다.
9. 버튼 [Browse...]을 선택합니다.
10. Unity에서 Export 받은 폴더를 선택합니다.
11. 버튼 [Finish]을 선택합니다.
12. Import 된 파일 목록을 확인합니다.
Android 소스 작성
Unity에서 Export 받은 소스에는 UnityPlayerActivity 를 상속 받지 않아서,
UnityPlayerActivity 겍체를 상속 받아 CubeMainActivity 소스를 작성하고, AndroidManifest.xml에서 Main Activity를 CubeMainActivity 수정했습니다.
Unity에서 호출 받은 로직을 처리하기 위해서 Handler 상속 받아서 Unity3DHandler.java 소스를 작성합니다.
CubeMainActivity.java
package com.azanghs.cube; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Bundle; import android.os.Message; import android.provider.Settings.Secure; import android.telephony.TelephonyManager; import android.util.Log; import com.example.android.trivialdrivesample.util.IabHelper; import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; public class CubeMainActivity extends UnityPlayerActivity { private static String TAG = CubeMainActivity.class.getSimpleName(); private TelephonyManager m_telephonyManager; String androidId = "KOR"; // The helper object IabHelper mHelper; private Unity3DHandler handler = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); handler = new Unity3DHandler(this); m_telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); Log.i(TAG, "Build.MODEL = " + Build.MODEL); Log.i(TAG, "Build.DEVICE = " + Build.DEVICE); Log.i(TAG, "Build.PRODUCT = " + Build.PRODUCT); } @Override public void onBackPressed() { this.finishMessage(); } public void QuitApplication() { handler.sendEmptyMessage(0); } public void AlertMessage(final String message) { Message msg = handler.obtainMessage(1); msg.obj = message; handler.sendMessage(msg); } public void finishMessage() { new AlertDialog.Builder(this).setMessage("프로그램을 종료하시겠습니까?") .setPositiveButton("확인", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { //System.exit(0); UnityPlayer.UnitySendMessage("GameObject", "FinishApp", ""); } }).setNegativeButton("취소", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }).show(); } //요 부분입니다. 이걸... Thread가 불필요하다면 public void initActivity(final String messageFromUnity) { Log.i(TAG, "여기 호출 Build.MODEL = " + Build.MODEL); UnityPlayer.UnitySendMessage("GameObject", "SetCountryCode", getResources().getConfiguration().locale.getISO3Country()); UnityPlayer.UnitySendMessage("GameObject", "SetDeviceModel", Build.MODEL); // 디바이스 ID String androidId = Secure.getString(getContentResolver(), Secure.ANDROID_ID); UnityPlayer.UnitySendMessage("GameObject", "SetDeviceID", androidId); // //UnityPlayer.UnitySendMessage("Cs_AndroidManager", "AndroidLog", "4/[" + tagFromUnity + "]" + messageFromUnity); } public void alert(String message) { AlertDialog.Builder bld = new AlertDialog.Builder(this); bld.setMessage(message); bld.setNeutralButton("OK", null); Log.d(TAG, "Showing alert dialog: " + message); bld.create().show(); } }
Unity3DHandler.java
package com.azanghs.cube; import android.os.Handler; import android.os.Message; public class Unity3DHandler extends Handler { private CubeMainActivity mainActivity = null; public Unity3DHandler(CubeMainActivity mainActivity) { this.mainActivity = mainActivity; } public void handleMessage(Message msg) { switch (msg.what) { case 0: mainActivity.finishMessage(); break; case 1: mainActivity.alert((String)msg.obj); break; default: break; } } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="preferExternal" android:theme="@android:style/Theme.NoTitleBar" package="com.azanghs.cube" android:versionName="1.0" android:versionCode="1"> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" /> <application android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false"> <activity android:name=".CubeMainActivity" android:launchMode="singleTask" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|uiMode|touchscreen" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- <activity android:name="com.azanghs.cube.CubeProxyActivity" android:launchMode="singleTask" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.azanghs.cube.CubeActivity" android:launchMode="singleTask" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:screenOrientation="portrait"> </activity> <activity android:name="com.azanghs.cube.CubeNativeActivity" android:launchMode="singleTask" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:screenOrientation="portrait"> <meta-data android:name="android.app.lib_name" android:value="unity" /> <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" /> </activity> --> </application> <uses-feature android:glEsVersion="0x00020000" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.touchscreen" /> <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" /> <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="17" /> </manifest>
Android 프로젝트를 Unity Plugin Jar로 Export 하기
1. 해당 프로젝트를 선택하고 메뉴 [Export...] 선택합니다.
2. 메뉴 [JAR file] 선택합니다.
3. 아래와 같이 선택합니다.
Jar 파일이 생성되는 파일 경로 Unity 소스 폴더의 %소스경로%\Assets\Plugins\Android 로 합니다. (변경불가)
4. 버튼 [Next >] 버튼 선택합니다.
5. 버튼 [Finish] 버튼 선택합니다.
6. Unity에서 Build 하면 Android 폰에 실행된 결과를 확인 할 수 있습니다.
- 설명 작성하려니 귀찬니즘이 발생해서 나중에 시간이 나면 다시 작성하도록 하겠음
- Total
- Today
- Yesterday
- Spring MVC
- Delphi Tip
- 레이싱모델 익스트림 포토 페스티벌
- Linux
- flex
- 송주경
- ffmpeg
- android
- ble
- KOBA
- 튜닝쇼 2008
- Mac
- 전예희
- oracle
- SAS
- Java
- ubuntu
- Delphi
- Spring
- JavaScript
- NDK
- Xcode
- 동경
- BPI-M4
- koba2010
- 일본여행
- 지스타2007
- sas2009
- 서울오토살롱
- MySQL
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |