unity3d 在Android应用程序上共享Unity游戏中的图像

vbopmzt1  于 2022-11-15  发布在  Android
关注(0)|答案(2)|浏览(143)

我在我的游戏中捕捉截图时,球员死亡。我有以下代码来捕捉屏幕截图。

RenderTexture rt = new RenderTexture (800, 600, 24);
    MainCamera.targetTexture = rt;
    Texture2D texture = new Texture2D (800, 600, TextureFormat.RGB24, false);
    MainCamera.Render ();
    RenderTexture.active = rt;
    texture.ReadPixels (new Rect (0, 0, 800, 600), 0, 0);
    MainCamera.targetTexture = null;
    RenderTexture.active = null;
    Destroy (rt);
    byte[] bytes = texture.EncodeToPNG ();
    Directory.CreateDirectory (Application.persistentDataPath + "/GameOverScreenShot");
    File.WriteAllBytes (Application.persistentDataPath + "/GameOverScreenShot" + "/DiedScreenShot.png", bytes);

我正在使用以下代码获取保存的屏幕截图。

byte[] bytes = File.ReadAllBytes (Application.persistentDataPath +"/GameOverScreenShot" + "/BirdDiedScreenShot.png");

Texture2D texture = new Texture2D (800, 600, TextureFormat.RGB24, false);
RectOffset tempOffset = new RectOffset (5, 5, 5, 5);
texture.filterMode = FilterMode.Trilinear;
texture.LoadImage (bytes);
Sprite sprite = Sprite.Create (texture, new Rect (0, 0, 800, 400), new Vector2 (0.5f, 0.0f), 2.0f);
ScreenShot_Image.GetComponent<Image> ().sprite = sprite;

现在,我想分享这个截图的android应用程序。根据我的研究,我有以下代码,但它是返回空白图像。

//instantiate the class Intent
AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");

//instantiate the object Intent
AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");

//call setAction setting ACTION_SEND as parameter
intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_SEND"));

//instantiate the class Uri
AndroidJavaClass uriClass = new AndroidJavaClass("android.net.Uri");

//instantiate the object Uri with the parse of the url's file
string destination = Application.persistentDataPath + "/GameOverScreenShot" + "/DiedScreenShot.png";
AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject>("parse","file://"+destination);

//call putExtra with the uri object of the file
intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_STREAM"), uriObject);

//set the type of file
intentObject.Call<AndroidJavaObject>("setType", "image/*");

//instantiate the class UnityPlayer
AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");

//instantiate the object currentActivity
AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");

//call the activity with our Intent
currentActivity.Call("startActivity", intentObject);

我应该在这方面改变什么??请帮助,前进谢谢

fruv7luv

fruv7luv1#

只需调用takeScreenShotAndShare()来拍摄屏幕快照并共享它。如果您已经有了要共享的图像,只需调用StartCoroutine(shareScreenshot(path));并传入图像的路径/位置。这只支持png图像。要共享jpeg,请更改

intentObject.Call<AndroidJavaObject>("setType", "image/png");

intentObject.Call<AndroidJavaObject>("setType", "image/jpeg");

整个代码:

void takeScreenShotAndShare()
{
    StartCoroutine(takeScreenshotAndSave());
}

private IEnumerator takeScreenshotAndSave()
{
    string path = "";
    yield return new WaitForEndOfFrame();

    Texture2D screenImage = new Texture2D(Screen.width, Screen.height);

    //Get Image from screen
    screenImage.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
    screenImage.Apply();

    //Convert to png
    byte[] imageBytes = screenImage.EncodeToPNG();

    System.IO.Directory.CreateDirectory(Application.persistentDataPath + "/GameOverScreenShot");
    path = Application.persistentDataPath + "/GameOverScreenShot" + "/DiedScreenShot.png";
    System.IO.File.WriteAllBytes(path, imageBytes);

    StartCoroutine(shareScreenshot(path));
}

private IEnumerator shareScreenshot(string destination)
{
    string ShareSubject = "Picture Share";
    string shareLink = "Test Link" + "\nhttp://stackoverflow.com/questions/36512784/share-image-on-android-application-from-unity-game";
    string textToShare = "Text To share";

    Debug.Log(destination);

    if (!Application.isEditor)
    {

        AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
        AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");
        intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_SEND"));
        AndroidJavaClass uriClass = new AndroidJavaClass("android.net.Uri");
        AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject>("parse", "file://" + destination);

        intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_STREAM"), uriObject);
        intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), textToShare + shareLink);
        intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_SUBJECT"), ShareSubject);
        intentObject.Call<AndroidJavaObject>("setType", "image/png");
        AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");
        currentActivity.Call("startActivity", intentObject);
    }
    yield return null;
}
643ylb08

643ylb082#

在Android 8+中,此方法无效。我们需要使用FileProvider
Google更改了使用FileProvider的共享方式,使其更加安全,我们不能将文件对象直接共享给任何其他应用程序。我们需要使用FileProvider并授予读取URI权限,使其可供任何其他应用程序访问。

  • 在Android Studio中创建一个新项目,并选择模板作为Android库
  • 在我们的库中创建一个名为“provider_paths.xml”的新XML资源文件。
<?xml version="1.0" encoding="utf-8"? >
 <paths xmlns:android="http://schemas.android.com/apk/res/android" >
     <external-path name="external_files" path="."/ >
 </paths>
  • 在库的manifest.xml文件中定义提供程序。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jk.pluginexample">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application>
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>
    </application>
</manifest>
  • 将其作为Android存档文件(.aar)从Android Studio导出。
  • 最后在Unity项目中添加C#代码:
#if UNITY_ANDROID
    public IEnumerator ShareScreenshotInAnroid()    // New Sharing, using FileProvider that works in Android 7+
    {
        isProcessing = true;
        // wait for graphics to render
        yield return new WaitForEndOfFrame();

        string screenShotPath = Application.persistentDataPath + "/" + screenshotName;
        ScreenCapture.CaptureScreenshot(screenshotName, 1);
        yield return new WaitForSeconds(0.5f);

        if (!Application.isEditor)
        {
            //current activity context
            AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");

            //Create intent for action send
            AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
            AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");
            intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_SEND"));

            //old code which is not allowed in Android 8 or above
            //create image URI to add it to the intent
            //AndroidJavaClass uriClass = new AndroidJavaClass ("android.net.Uri");
            //AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject> ("parse", "file://" + screenShotPath);

            //create file object of the screenshot captured
            AndroidJavaObject fileObject = new AndroidJavaObject("java.io.File", screenShotPath);

            //create FileProvider class object
            AndroidJavaClass fileProviderClass = new AndroidJavaClass("androidx.core.content.FileProvider");

            object[] providerParams = new object[3];
            providerParams[0] = currentActivity;
            providerParams[1] = "com.YOURCOMPANY.YOURPACKAGENAME.provider";
            providerParams[2] = fileObject;

            //instead of parsing the uri, will get the uri from file using FileProvider
            AndroidJavaObject uriObject = fileProviderClass.CallStatic<AndroidJavaObject>("getUriForFile", providerParams);

            //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);

            //additionally grant permission to read the uri
            intentObject.Call<AndroidJavaObject>("addFlags", intentClass.GetStatic<int>("FLAG_GRANT_READ_URI_PERMISSION"));

            AndroidJavaObject chooser = intentClass.CallStatic<AndroidJavaObject>("createChooser", intentObject, "Share your high score");
            currentActivity.Call("startActivity", chooser);
        }

        yield return new WaitUntil(() => isFocus);
        isProcessing = false;
    }
#endif

我使用了androidx.core.content.FileProvider,因为所有库都迁移到AndroidX。您也可以使用android.support.v4.content.FileProvider
完整的Post by Suneet Agrawal is here。我只提供了关键步骤。

相关问题