레이블이 안드로이드인 게시물을 표시합니다. 모든 게시물 표시
레이블이 안드로이드인 게시물을 표시합니다. 모든 게시물 표시

2016년 7월 18일 월요일

유니티에서 jni를 이용해 apk파일 위치 가져오기

유니티에서 apk파일 저장위치를 알아낼수 있는 함수를 제공하는지와 상관없이 개인적인 필요성에 의해 삽질을 시작함.

우선 테스트하기 위해 기본적인 자료를 찾아봄.

http://docs.unity3d.com/kr/current/Manual/PluginsForAndroid.html
위의 사이트 하단부에
http://docs.unity3d.com/kr/current/uploads/Main/AndroidJavaPluginProject.zip

테스트 프로젝트를 다운받아 시작함.
바로 안드로이드에서 실행이 안될수도 있는데 libjni.so 를 선택한 후 인스펙터를 보면 select platforms for plugin 에 Android가 체크 안되어 있을 수가 있음.

체크한 후 cpu 를 armv7로 설정한 후 apply 한 후 다시 시도하니 정상 작동함.

그 후 CallJavaCode.cs 파일을 분석한 후 삽질에 들어감.

이 부분이 기존 내용이고
// first we try to find our main activity..
IntPtr cls_Activity = JNI.FindClass("com/unity3d/player/UnityPlayer");
int fid_Activity = JNI.GetStaticFieldID(cls_Activity, "currentActivity", "Landroid/app/Activity;");
IntPtr obj_Activity = JNI.GetStaticObjectField(cls_Activity, fid_Activity);

이 뒤에 바로 아래 내용을 작성함.
IntPtr context =JNI.FindClass("android/content/Context");
int tt = JNI.GetMethodID(context, "getPackageName", "()Ljava/lang/String;");
// get the Java String object from the JavaClass object
IntPtr str_cacheDir = JNI.CallObjectMethod(obj_Activity, tt);
Debug.Log("str_cacheDir = " + str_cacheDir);

// convert the Java String into a Mono string
IntPtr stringPtr = JNI.GetStringUTFChars(str_cacheDir, 0);
Debug.Log("stringPtr = " + stringPtr);
String packagename = Marshal.PtrToStringAnsi(stringPtr);
JNI.ReleaseStringUTFChars(str_cacheDir, stringPtr);

Debug.Log("return value is = " + packagename);

IntPtr pmcls = JNI.FindClass("android/content/pm/PackageManager");

Debug.Log("pmcls = " + pmcls);

int getPackageManager = JNI.GetMethodID(context, "getPackageManager", "()Landroid/content/pm/PackageManager;");

Debug.Log("getPackageManager = " + getPackageManager);

IntPtr pm = JNI.CallObjectMethod(obj_Activity, getPackageManager);

Debug.Log("pm = " + pm);

int getApplicationInfo = JNI.GetMethodID(pmcls, "getApplicationInfo", "(Ljava/lang/String;I)Landroid/content/pm/ApplicationInfo;");

Debug.Log("getApplicationInfo = " + getApplicationInfo);

IntPtr message = JNI.NewStringUTF(packagename);
int aa = 0;
IntPtr zero = (IntPtr)aa;
// getApplicationInfo의 인자값으로 int를 넣어야 해서 그냥 해봤는데 되긴 했지만 찜찜함.

IntPtr ai = JNI.CallObjectMethod(pm, getApplicationInfo, message, zero);
Debug.Log("ai = " + ai);

IntPtr aicls = JNI.FindClass("android/content/pm/ApplicationInfo");
int aif = JNI.GetFieldID(aicls, "publicSourceDir", "Ljava/lang/String;");

IntPtr aiPtr = JNI.GetObjectField(ai, aif);

// convert the Java String into a Mono string
IntPtr aiPtrStr = JNI.GetStringUTFChars(aiPtr, 0);
Debug.Log("aiPtr = " + aiPtrStr);
String aiStr = Marshal.PtrToStringAnsi(aiPtrStr);
JNI.ReleaseStringUTFChars(aiPtr, aiPtrStr);

Debug.Log("return value is = " + aiStr);


위와 같이 작성하고 실행한 뒤 원하는 결과물을 얻었음.

AndroidJni인가를 이용해도 되고 방법은 여러가지였음.

참고사이트.
https://www.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html
http://samse.tistory.com/entry/JNI-%EC%9A%94%EC%95%BD-1
추가)
http://www.codeproject.com/Articles/18032/How-to-Marshal-a-C-Class

안드로이드 NDK 사용 기록(삽질기)

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE    := libjnitest
LOCAL_SRC_FILES := jnitest.cpp
include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_OPTIM        := release
APP_ABI          := armeabi
APP_PLATFORM     := android-8
APP_BUILD_SCRIPT := Android.mk

jnitest.cpp

float add(float x, float y)
{
return x + y;
}

build.bat

ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk


위 파일을 한폴더에 만들어 놓은 후 배치파일을 실행하면 빌드후 .so파일이 잘 생성된다.
기본적인 환경설정등을 맞춰놓은 후에 가능.