2018. 5. 3. 22:38 IT/유니티 Tip & 파헤치기
[unity][TIP] 이미지 공유하기 구현- Android N 대응하기
이미지 공유하기 기능을 구현하려다가 이미 구현되어있는게 있을법해서 찾아보니까 JNI로 깔끔하게 구현된게 있더군요! IOS까지!
https://github.com/tejas123/general-sharing-in-android-ios-in-unity
문제는 Android N 부터는 정책이 달라져서 저 코드의 이미지 공유하기를 실행시키면,
FileUriExposedException: exposed beyond app through ClipData.Item.getUri()
이런 에러코드가 뜹니다.
해결방법
1. 타겟 API를 안드로이드 6.0 이하로 내린다.
- 아주아주 간단하지만, 찝찝합니다. 권장하지 않아요.
- 안드로이드에서는 앞으로 위 정책으로 진행할텐데 계속 유지보수하는한 언젠가는 결국 수정해야하잖아요?
2. FileProvider 방식으로 변경한다.
- 안드로이드에서 권장하는 방법입니다.
- Android Native에서 구현 방법은 공식문서에서 이미 가이드를 하고 있으므로, 해당 가이드를 유니티에서 구현하도록 합니다.
- https://developer.android.com/reference/android/support/v4/content/FileProvider
- 가이드를 고대로 JNI로 unity에 구현하고, Manifest와 res만 수정하면 되겠네요. 아래부터 수정한 내역을 공유하도록 하겠습니다.
- Code 수정 (GIT의 코드를 가이드에 맞게 일부 수정한 내용입니다.)
IEnumerator SaveAndShare () { yield return new WaitForEndOfFrame (); #if UNITY_ANDROID byte[] bytes = MyImage.EncodeToPNG(); string path = Application.persistentDataPath + "/MyImage.png"; File.WriteAllBytes(path, bytes); AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent"); AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent"); intentObject.Call<androidjavaobject>("setAction", intentClass.GetStatic<string>("ACTION_SEND")); intentObject.Call<androidjavaobject>("setType", "image/*"); intentObject.Call<androidjavaobject>("putExtra", intentClass.GetStatic<string>("EXTRA_SUBJECT"), "Media Sharing "); intentObject.Call<androidjavaobject>("putExtra", intentClass.GetStatic<string>("EXTRA_TITLE"), "Media Sharing "); intentObject.Call<androidjavaobject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), "Media Sharing Android Demo"); AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject currentActivity = unity.GetStatic<androidjavaobject>("currentActivity"); //AndroidJavaClass uriClass = new AndroidJavaClass("android.net.Uri"); AndroidJavaClass uriClass = new AndroidJavaClass("android.support.v4.content.FileProvider"); AndroidJavaClass fileClass = new AndroidJavaClass("java.io.File"); AndroidJavaObject fileObject = new AndroidJavaObject("java.io.File", path);// Set Image Path Here AndroidJavaObject stringObject = new AndroidJavaObject("java.lang.String", "com.myproject.project.share.fileprovider");// Set Image Path Here //AndroidJavaObject uriObject = uriClass.CallStatic<androidjavaobject>("fromFile", fileObject); AndroidJavaObject uriObject = uriClass.CallStatic<androidjavaobject>("getUriForFile", currentActivity, stringObject, fileObject); // string uriPath = uriObject.Call<string>("getPath"); bool fileExist = fileObject.Call<bool>("exists"); Debug.Log("File exist : " + fileExist); if (fileExist) intentObject.Call<androidjavaobject>("putExtra", intentClass.GetStatic<string>("EXTRA_STREAM"), uriObject); currentActivity.Call("startActivity", intentObject); #endif }
- 작은 설명을 붙이자면, 기존에 Uri.fromFile 함수를 FileProvider.getUriForFile 함수로 함수와 매개변수를 수정한게 끝입니다.
- AndroidManifest.xml 추가
- 경로 - \Assets\Plugins\Android\Share\AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.myproject.project.share" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="25" /> <application> <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.myproject.project.share.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" /> </provider> </application> </manifest>
- res 추가
- 경로 - \Assets\Plugins\Android\Share\res\xml\filepaths.xml
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="storage/emulated" path="."/> </paths>
진행과정에서 발생했던 에러
android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
- 코드 상의 패키지 이름과 Provider의 authorities 오타 수정하여 통일
'IT > 유니티 Tip & 파헤치기' 카테고리의 다른 글
Firebase 사용기 - 1. 개요 (0) | 2019.05.18 |
---|---|
Unity ECS (Entity Component System) Study - 1. 개요 (5) | 2019.05.18 |
[unity][TIP] 유니티 무한루프 또는 튕겼을 때 씬 복구하기. (2) | 2018.04.20 |
[unity] 화면 흔들기 (camera shake) (0) | 2018.04.14 |
[unity] 유도탄 만들기 (벡터의 내적, 외적 활용) (1) | 2018.04.14 |