Unity Android - Make Screenshot and share it

- Update 2016-05-04 -

We can write Java code inside Unity script by using the AndroidJavaObject class and the Call method.
So, it's easy to implement a "share screenshot" feature in your Unity Android Game.
The steps are:
  1. Save the actual screen to a Texture2D
  2. Save this texture to file (android filesystem)
  3. Create a new Intent class with ACTION_SEND action
  4. Execute this intent from the main Activity
This code could be inserted in a IEnumerator function.
Code Example:

using UnityEngine;
using System.Collections;
using System.IO;

/**
*  Share a Screenshot on Android (on Unity 5.3.4)
* 
*  Last update 2016-05-04
* 
*/
public class Screenshot : MonoBehaviour {

void OnGUI () {
    GUI.Box (new Rect (0,Screen.height - 100,220,70), "Action Menu");
    if(GUI.Button(new Rect(20,Screen.height-60,180,20), "Share Screenshot")) {
        StartCoroutine(ShareScreenshot());
    }
}

public IEnumerator ShareScreenshot() {
    
    // wait for graphics to render
    yield return new WaitForEndOfFrame();
    
    // prepare texture with Screen and save it
    Texture2D texture = new Texture2D(Screen.width, Screen.height,TextureFormat.RGB24,true);
    texture.ReadPixels(new Rect(0f, 0f, Screen.width, Screen.height),0,0);
    texture.Apply();
    
    // save to persistentDataPath File
    byte[] data = texture.EncodeToPNG();        
    string destination = Path.Combine(Application.persistentDataPath, 
                                      System.DateTime.Now.ToString("yyyy-MM-dd-HHmmss") + ".png");        
    File.WriteAllBytes(destination, data);
    
    if(!Application.isEditor)
    {
        #if UNITY_ANDROID
        string body = "Body of message to be shared";
        string subject = "Subject of message";

        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"), body );
        intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_SUBJECT"), subject);
        intentObject.Call<AndroidJavaObject>("setType", "image/jpeg");
        AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");
        
        // run intent from the current Activity
        currentActivity.Call("startActivity", intentObject);
        #endif
    }
}
}

Remember to set the "writeaccess" flag to TRUE.
You find it in: Edit -> Project -> Player -> Android Settings


Simple (but complete) Example


  1. Create a new scene
  2. Create an Empty Object (or use existing one)
  3. Attach the following script:

using UnityEngine;
using System.Collections;
using System.IO;

/**
*  Share a Screenshot on Android (on Unity 5.3.4)
* 
*  Last update 2016-05-04
* 
*/
public class Screenshot : MonoBehaviour {

void OnGUI () {
    GUI.Box (new Rect (0,Screen.height - 100,220,70), "Action Menu");
    if(GUI.Button(new Rect(20,Screen.height-60,180,20), "Share Screenshot")) {
        StartCoroutine(ShareScreenshot());
    }
}

public IEnumerator ShareScreenshot() {
    
    // wait for graphics to render
    yield return new WaitForEndOfFrame();
    
    // prepare texture with Screen and save it
    Texture2D texture = new Texture2D(Screen.width, Screen.height,TextureFormat.RGB24,true);
    texture.ReadPixels(new Rect(0f, 0f, Screen.width, Screen.height),0,0);
    texture.Apply();
    
    // save to persistentDataPath File
    byte[] data = texture.EncodeToPNG();        
    string destination = Path.Combine(Application.persistentDataPath, 
                                      System.DateTime.Now.ToString("yyyy-MM-dd-HHmmss") + ".png");        
    File.WriteAllBytes(destination, data);
    
    if(!Application.isEditor)
    {
        #if UNITY_ANDROID
        string body = "Body of message to be shared";
        string subject = "Subject of message";

        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"), body );
        intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_SUBJECT"), subject);
        intentObject.Call<AndroidJavaObject>("setType", "image/jpeg");
        AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");
        
        // run intent from the current Activity
        currentActivity.Call("startActivity", intentObject);
        #endif
    }
}
}

Comments

  1. Hey I tried your code, but its full of errors.
    Somehow I was able to get it running but figured out that it doesn't share snapshots but only shares an already existing image from project. It saves an image under android>data>project_identifier.. but doesnt use it for share.. please help me out.
    Thanks.

    ReplyDelete
    Replies
    1. Hi Nidhi! Thanks for your comment.
      Which Unity version are you using ? Which Android version?
      Did you enable WRITE ACCESS to External SD CARD?
      In the next days We'll post a complete example, in the Unity 5 format project, so stay tuned.

      Delete
    2. Hi Nidhi, due to the escaping syntax on blogger, some C# code was truncated.
      Now this works again. Remember to set the External SD to be able to save the screenshot before share it.

      Delete

Post a Comment