2016년 7월 18일 월요일

유니티에서 SharpZipLib 사용한 압축 저장방법

우선 아래 url에서
http://icsharpcode.github.io/SharpZipLib/

Download.zip 을 통해 프로젝트를 다운받음.

Visual Studio (2015)로 부른 후 ICSharpCode.SharpZipLib 시작프로젝트로 설정

project 메뉴에서 맨 아래쪽에 Properties - Application - Target framework 를
.Net Framework 2.0으로 변경

release 로 빌드한 ICSharpCode.SharpZipLib.dll 를 유니티 적당한 장소에 복사하면 준비 끝.

현재 프로젝트에서 로컬에 데이터를 압축저장하기 사용함.

압축 및 저장하기

        게임정보클래스 = gi;
        BinaryFormatter _binary_formatter = new BinaryFormatter();      
        FileStream _filestream = File.Create(Application.persistentDataPath + "/파일이름");
#if ZIP_NONE // 압축하지 않을 경우
        _binary_formatter.Serialize(_filestream, gi);
#elif ZIP_BZIP2
        MemoryStream buffer = null;
        MemoryStream m_msBZip2 = null;
        BZip2OutputStream m_osBZip2 = null;
        try
        {
            buffer = new MemoryStream();
            _binary_formatter.Serialize(buffer, gi);

            m_msBZip2 = new MemoryStream();

            _binary_formatter.Serialize(buffer, gi);

            Int32 size = (int)buffer.Length;
            // Prepend the compressed data with the length of the uncompressed data (firs 4 bytes)
            //
            using (BinaryWriter writer = new BinaryWriter(m_msBZip2, System.Text.Encoding.ASCII))
            {
                writer.Write(size);

                m_osBZip2 = new BZip2OutputStream(m_msBZip2);
                m_osBZip2.Write(buffer.ToArray(), 0, size);

                m_osBZip2.Close();

                BinaryWriter bw = new BinaryWriter(_filestream);
                bw.Write(m_msBZip2.ToArray(), 0, m_msBZip2.ToArray().Length);
             
                buffer.Close();
                m_msBZip2.Close();
                bw.Close();
                writer.Close();
            }
        }
        finally
        {
            if (m_osBZip2 != null)
            {
                m_osBZip2.Dispose();
            }
            if (m_msBZip2 != null)
            {
                m_msBZip2.Dispose();
            }
            if (buffer != null)
            {
                buffer.Dispose();
            }
        }
#endif
        _filestream.Close();  


압축 해제 및 불러오기

게임정보클래스 Load()
    {
        게임정보클래스 gi = null;

        bool _file_check = File.Exists(Application.persistentDataPath + "/파일이름");

        if (_file_check)
        {
            FileStream _filestream = null;

            try
            {
                BinaryFormatter _binary_formatter = new BinaryFormatter();
                _filestream = File.Open((Application.persistentDataPath + "/파일이름"), FileMode.Open);
#if ZIP_NONE
                gi = (GameInfo)_binary_formatter.Deserialize(_filestream);
#elif ZIP_BZIP2
                MemoryStream m_msBZip2 = null;
                BZip2InputStream m_isBZip2 = null;
                try
                {
                    using (BinaryReader reader = new BinaryReader(_filestream, System.Text.Encoding.ASCII))
                    {
                        Int32 size = reader.ReadInt32();

                        m_isBZip2 = new BZip2InputStream(_filestream);
                        byte[] bytesUncompressed = new byte[size];
                        m_isBZip2.Read(bytesUncompressed, 0, bytesUncompressed.Length);

                        m_msBZip2 = new MemoryStream(bytesUncompressed);

                        gi = (게임정보클래스)_binary_formatter.Deserialize(m_msBZip2);

                        m_isBZip2.Close();
                        m_msBZip2.Close();
                        reader.Close();
                    }
                }
                finally
                {
                    if (m_isBZip2 != null)
                    {
                        m_isBZip2.Dispose();
                    }
                    if (m_msBZip2 != null)
                    {
                        m_msBZip2.Dispose();
                    }
                }
#endif
                _filestream.Close();
            }
            catch (Exception e)
            {
                //Debug.Log("----- " + e.Message);
                _filestream.Close();

                gi = new 게임정보클래스();
            }
        }
        else
        {
            gi = new 게임정보클래스();
        }

        return gi;
    }


위와 같이 사용했음. 안드로이드, 아이폰 시뮬레이터에서 작동 확인함.
아이폰 실기기에서 테스트하진 않았지만 문제없을걸로 판단됨.

참고사이트.
http://qiita.com/satotin/items/4bd0ff1a43c700278071

유니티에서 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파일이 잘 생성된다.
기본적인 환경설정등을 맞춰놓은 후에 가능.