[Unity] SNS 공유하기 / Android N 대응 방법
SNS 공유하기 기능은 게임 앱 개발 시 많이 사용하는 기능중에 하나죠.
하지만 예전에 사용하던 코드가 Android N 부터는 정상작동을 하지 않고 에러가 나오더군요.
그래서 공유하기 기능을 fileprovider 방식으로 변경해야 했습니다.
아래는 제가 사용하는 fileprovider 방식으로 변경한 코드 입니다.
  private void ShareAndroidImageWithText(string path, string title, string text, Texture2D _textureShareImage)
    {
#if UNITY_ANDROID
        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"), title);
            intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TITLE"), title);
            intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), text);
            AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");
            AndroidJavaObject unityContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");
            AndroidJavaClass uriClass = new AndroidJavaClass("android.support.v4.content.FileProvider");
            AndroidJavaClass fileClass = new AndroidJavaClass("java.io.File");
            string packageName = unityContext.Call<string>("getPackageName");
            string authority = packageName + ".fileprovider";
            AndroidJavaObject fileObject = new AndroidJavaObject("java.io.File", path);
            
            AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject>("getUriForFile", unityContext, authority, fileObject);
            bool fileExist = fileObject.Call<bool>("exists");
            Debug.Log("[GeneralShare] File exist : " + fileExist);
            Debug.Log("[GeneralShare] file path : " + uriObject.Call<string>("getPath"));
            
            // Attach image to intent
            if (fileExist)
                intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_STREAM"), uriObject);
            AndroidJavaObject jChooser = intentClass.CallStatic<AndroidJavaObject>("createChooser", intentObject, KW.Get("SYS_SNS_SHARE"));
            currentActivity.Call("startActivity", jChooser);
        }
#endif
    }가운데 부분에 기존에 사용 하던 이런 형태의 코드에서
            AndroidJavaClass uriClass = new AndroidJavaClass("android.net.Uri"); 
            AndroidJavaClass fileClass = new AndroidJavaClass("java.io.File"); 
            AndroidJavaObject fileObject = new AndroidJavaObject("java.io.File", path);   
            AndroidJavaObject uriObject = uriClass.CallStatic("fromFile", fileObject); 
이런식으로 변경합니다.
            AndroidJavaClass uriClass = new AndroidJavaClass("android.support.v4.content.FileProvider"); 
            AndroidJavaClass fileClass = new AndroidJavaClass("java.io.File"); 
            string packageName = unityContext.Call("getPackageName"); 
            string authority = packageName + ".fileprovider"; 
            AndroidJavaObject fileObject = new AndroidJavaObject("java.io.File", path);  
            AndroidJavaObject uriObject = uriClass.CallStatic("getUriForFile", unityContext, authority, fileObject);
코드를 수정했으면
AndroidManifest.xml 파일에 fileprovider 를 사용할 수 있는 내용을 추가해야 합니다.
  <application>
    <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="[패키지 네임].fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
      <meta-data
          android:name="android.support.FILE_PROVIDER_PATHS"
          android:resource="@xml/filepaths" />
    </provider>
  </application>내용 중 패키지 네임은 자신이 만든 프로젝트의 패키지 네임을 입력하시면 됩니다.
패키지 네임은 com.xxxxx.xxxxx 이런식으로 되어 있죠.
위 내용을 AndroidManifest.xml 추가 했으면 추가한 해당 AndroidManifest.xml 파일이 있는 곳에
res 폴더를 만든 후(이미 있으면 그냥 사용해도 됩니다.) res 폴더 안에 xml 폴더를 만들고 filepaths.xml 파일을
만들고 아래의 코드를 입력합니다.
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
  <external-path path="Android/data/com.company.product" name="files_root" />
  <external-path path="." name="external_storage_root" />
</paths>
위 경로 예시는 저는AndroidManifest.xml 에 들어가는 fileprovider 내용을
구글 애드몹을 사용하기때문에 애드몹 플러그인에 같이 붙여 놓은 상태입니다.
꼭 이렇게 붙여놓을 필요는 없고 따로 AndroidManifest.xml 만들거나 다른 플러그인에 함께 사용해도 됩니다.
구현 중 또는 후에
android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
이런 오류나
NullPointerException when trying to get URI with FileProvider(Android)
이런식의 오류가 날 경우에는 AndroidManifest.xml 파일의 패키지 명이 정확하게 입력되어 있는지를 확인해보고
xml 파일이 정확한 경로 위치에 있는지 확인합니다.
res - xml - filepaths.xml
'Unity' 카테고리의 다른 글
| [Unity] 유니티 애드몹 전면 광고 적용하기 (AdMob Interstitial Ads) v3.17 (0) | 2019.06.02 | 
|---|---|
| [Unity] 애드몹 배너 광고 적용하기 (AdMob Banner) v3.17 (6) | 2019.05.30 | 
| [Unity] 유니티 2019 버전 업그레이드 후 오류 대응 / IL2CPP 빌드 (4) | 2019.05.27 | 
| 유니티에서 안드로이드폰 디버깅 (로그캣) (0) | 2019.05.21 | 
| [애드몹] 'GoogleMobileAds.Api.MobileAds' threw an exception 해결 방법 (0) | 2019.05.21 |