0

I am trying to share a screenshot in my Unity Game on Android devices with the following error:

E/Unity: AndroidJavaException: java.lang.NoSuchMethodError: no static method with name='getUriForFile' signature='(Landroid.app.Application;Ljava/lang/String;Ljava.io.File;)Ljava/lang/Object;' in class Ljava.lang.Object;
java.lang.NoSuchMethodError: no static method with name='getUriForFile' signature='(Landroid.app.Application;Ljava/lang/String;Ljava.io.File;)Ljava/lang/Object;' in class Ljava.lang.Object;
    at com.unity3d.player.ReflectionHelper.getMethodID(Unknown Source:167)
    at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
    at com.unity3d.player.UnityPlayer.access$300(Unknown Source:0)
    at com.unity3d.player.UnityPlayer$e$1.handleMessage(Unknown Source:83)
    at android.os.Handler.dispatchMessage(Handler.java:101)
    at android.os.Looper.loop(Looper.java:173)
    at com.unity3d.player.UnityPlayer$e.run(Unknown Source:20)
  at UnityEngine.AndroidJNISafe.CheckException () [0x00000] in <00000000000000000000000000000000>:0 
  at UnityEngine.AndroidJNISafe.CallStaticObjectMethod (System.IntPtr clazz, System.IntP

From the Logs I can see that "getUriForFile" method doesn't exists.. I have already checked most of the questions (here, here, here, and many others..) regarding the problem I have but I still cannot fix it.

Here is the ShareScreenshot code I have:

private IEnumerator ShareScreenshot(string screenShotPath, string shareSubject, string shareLink, string textToShare)
{
    if (!Application.isEditor)
    {
        /// Get Activity then Context
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        AndroidJavaObject unityContext = currentActivity.Call<AndroidJavaObject>("getApplicationContext");

        /// Get the package Name
        string packageName = unityContext.Call<string>("getPackageName");
        string authority = packageName + ".fileprovider";

        AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
        string ACTION_VIEW = intentClass.GetStatic<string>("ACTION_VIEW");
        AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", ACTION_VIEW);

        int FLAG_ACTIVITY_NEW_TASK = intentClass.GetStatic<int>("FLAG_ACTIVITY_NEW_TASK");
        int FLAG_GRANT_READ_URI_PERMISSION = intentClass.GetStatic<int>("FLAG_GRANT_READ_URI_PERMISSION");

        AndroidJavaObject fileObj = new AndroidJavaObject("java.io.File", screenShotPath);
        AndroidJavaClass fileProvider = new AndroidJavaClass("androidx.core.content.FileProvider");
        AndroidJavaObject uri = fileProvider.CallStatic<AndroidJavaObject>("getUriForFile", unityContext, authority, fileObj);

        intent.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_STREAM"), uri);
        intent.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), textToShare + shareLink);
        intent.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_SUBJECT"), shareSubject);
        intent.Call<AndroidJavaObject>("setType", "image/png");

        intent.Call<AndroidJavaObject>("addFlags", FLAG_ACTIVITY_NEW_TASK);
        intent.Call<AndroidJavaObject>("addFlags", FLAG_GRANT_READ_URI_PERMISSION);

        currentActivity.Call("startActivity", intent);
    }

    yield return null;
}

Android Manifest:

 <provider android:name="androidx.core.content.FileProvider" android:authorities="com.mycompanyname.gamename.fileprovider" android:exported="false" android:grantUriPermissions="true">
  <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
</provider>

and the provider_paths.xml:

<external-path path="Android/data/com.mycompanyname.gamename" name="files_root" />
<external-path path="." name="external_storage_root" />

I was using android.support.v4.content.FileProvider but it's not working on Android version 9 and up so I tried androidx.core.content.FileProvider and I'm getting the error above.

Thank you.

Johny
  • 625
  • 2
  • 6
  • 26

2 Answers2

1

This method may be removed at build time if proguard enabled.

Try Adding

-keep class androidx.core.content.** { *; }

To

Assets/Plugins/Android/proguard-user.txt
0

Try this function to share screenshots:

public void shareScreen(string photoPath)
{
    StartCoroutine(ShareScreenshot(photoPath));
}

IEnumerator ShareScreenshot(string path)
{
    yield return new WaitForSecondsRealtime(0.5f);

    AndroidJavaClass intentClass = new AndroidJavaClass ("android.content.Intent");
        AndroidJavaObject intentObject = new AndroidJavaObject ("android.content.Intent");
        intentObject.Call<AndroidJavaObject> ("setAction", intentClass.GetStatic<string> ("ACTION_SEND"));

        //create image URI to add it to the intent
        AndroidJavaClass uriClass = new AndroidJavaClass ("android.net.Uri");
        AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject> ("parse", "file://" + path);

        //put image and string extra
        intentObject.Call<AndroidJavaObject> ("putExtra", intentClass.GetStatic<string> ("EXTRA_STREAM"), uriObject);
        intentObject.Call<AndroidJavaObject> ("setType", "image/png");
        intentObject.Call<AndroidJavaObject> ("putExtra", intentClass.GetStatic<string> ("EXTRA_SUBJECT"), shareSubject);
        intentObject.Call<AndroidJavaObject> ("putExtra", intentClass.GetStatic<string> ("EXTRA_TEXT"), shareMessage);

        AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject> ("currentActivity");
        AndroidJavaObject chooser = intentClass.CallStatic<AndroidJavaObject> ("createChooser", intentObject, "Share your score");
        currentActivity.Call ("startActivity", chooser);
}

To use this function properly, you need to provide the function a path where your screenshot is located

Cardstdani
  • 4,999
  • 3
  • 12
  • 31
  • 1
    I had this code but it's not working on new Android version 9 and 10. – Johny Jul 07 '20 at 10:32
  • @Johny, In Android 7+, this method does not work. We need to use FileProvider. [Refer this](https://agrawalsuneet.github.io/blogs/native-android-image-sharing-in-unity-using-fileprovider/), or search on Google **Native Android image sharing in Unity using FileProvider.** – Junaid Pathan Nov 14 '22 at 19:30