Saving Screenshots to Android Gallery

I want to make a screenshot of the Android screen while playing the game by pressing a GUI button and save it to the android’s Gallery.

I found a tutorial that details how to save images to the android’s gallery using the SDK and java. Here’s the link http://developer.android.com/training/camera/photobasics.html

My problem is that I don’t understand how to use java with unity. My basic understanding is that I need to either make a library or a plugin. Is that correct? Can you point me to a tutorial that walks me through the process? Or suggest another approach?

Thanks!

Here is the code that saves Texture2D to Android gallery and does not require to scan media afterwards (picture will appear in gallery instantly)

        private const string MediaStoreImagesMediaClass = "android.provider.MediaStore$Images$Media";

         public static string SaveImageToGallery(Texture2D texture2D, string title, string description)
         {
             using (var mediaClass = new AndroidJavaClass(MediaStoreImagesMediaClass))
             {
                 using (var cr = Activity.Call<AndroidJavaObject>("getContentResolver"))
                 {
                     var image = Texture2DToAndroidBitmap(texture2D);
                     var imageUrl = mediaClass.CallStatic<string>("insertImage", cr, image, title, description);
                     return imageUrl;
                 }
             }
         }
 
         public static AndroidJavaObject Texture2DToAndroidBitmap(Texture2D texture2D)
         {
             byte[] encoded = texture2D.EncodeToPNG();
             using (var bf = new AndroidJavaClass("android.graphics.BitmapFactory"))
             {
                 return bf.CallStatic<AndroidJavaObject>("decodeByteArray", encoded, 0, encoded.Length);
             }
         }

After lots of digging, I've found a solution, but it's made me realize that this post probably should have been three separate questions.

RE: How to use Java Plugins in Unity

The documentation for Unity includes a page describing plugins. Under the Android section, there is a description of how to make a jar file and use AndroidJavaObject to access it in Unity.

RE: How to make and save an Android Screenshot

First, according to this post, androids have problems encoding to PNG. This post provided a link to an alternative jpg encoding.

Second, to view the screenshot from the android file manager, the file path needs to be set using `Application.persistentDataPath` . More in this post.

RE: Android Gallery

[EDIT] Still working on this… After taking a screenshot, the image does not show up in the gallery regardless of the filepath. However, on rebooting the phone, it does a media scan and automatically adds all image files to the gallery, again regardless of the filepath. There is a post about forcing a media scan, but I have yet to try out the answer

This GitHub repo contains functionality that will allow you to save screenshots and images to the gallery on Android and iOS:

I got a partial answer for the ‘saving an image in the users gallery on Android’ part of the question. That’s how we do it in native Android. I will look for a solution from Unity.

final Bitmap bitmap = INSERTSOMEVIEWHERE.getDrawingCache();
final File appSzenesFolder;
try {
	appSzenesFolder = directoryAndStorage.getOrCreatePictureDirectory("NameOfTheImageFolderInTheGallery");
	final Date now = new Date();
	final File file = new File(appSzenesFolder, (now.getTime() / 1000) + ".png");
	file.createNewFile();

	final FileOutputStream ostream = new FileOutputStream(file);
	bitmap.compress(CompressFormat.PNG, 100, ostream);
	ostream.close();

	// Tell the media scanner about the new file so that it is immediately available to the user.
	MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null, null);
} catch (IOException e) {
    // Insert error handling here :)
}

This is pretty much copy and paste from one of our previous projects. I removed some of the error handling (you have to check for the existence of the folder etc).

INSERTSOMEVIEWHERE is some view in Android. This code is basically meant to take a screenshot from a particular view ans save it in the gallery. You can take the root view if you want to take a screenshot of the whole app.

There is that external helper function directoryAndStorage.getOrCreatePictureDirectory I use to create a folder in the users gallery depending on which device we are running on (Some devices don’t have an external storage and the Nook does not have the function getExternalStoragePublicDirectory). The helper function is far from complete, you could add support for different Android versions aswell:

public File getOrCreatePictureDirectory(String directoryName) {
	final File picturesDir;
	if (Build.PRODUCT.equals("NOOKcolor")) {
		// The nook color uses a slightly different path for images and the
		// usual constant for the path does not work
		picturesDir = new File("/mnt/media");
	} else if (Build.PRODUCT.equals("NOOKTablet")) {
		picturesDir = new File("/mnt/media");
	} else {
		picturesDir = Environment
				.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
	}
	picturesDir.mkdirs();
	File dir = new File(picturesDir, directoryName);
	if (!dir.exists()) {
		Log.i(Config.LOG_TOKEN, "'" + dir
				+ "' does not exist, trying to create ...");
		if (dir.mkdirs() == false) {
			Log.e(Config.LOG_TOKEN, "Failed to create directory '" + dir
					+ "'!");
			return null;
		}
	}
	return dir;
}

That’s it so far. If you have questions, shoot. I’m going to post updates soon.

Hello Guys,

You should use this wonderful plugin with full support.

Use this code work for me

IEnumerator ScreenshotEncode()
{

    yield return new WaitForEndOfFrame();
	texture1 = new Texture2D(Screen.width-(int)Left_P.y, Screen.height, TextureFormat.RGB24, false);
	texture1.ReadPixels(new Rect(0+Left_P.y, 0, Screen.width-Left_P.y, Screen.height), 0, 0);
    texture1.Apply();
	for(int i =0 ; i< hiders.Length;i++)
		hiders*.SetActive(true);*

yield return 0;

  •   bytes = texture1.EncodeToPNG();*
    

File.WriteAllBytes( “/mnt/sdcard/DCIM/Images/” + “DrawCircuit " +save_Address+”.jpg",bytes );
}}

@tarasfromlviv where can i give the screenshot/image the path to be saved, so far is not working for me

We made a plugin which is compatible on iOS and Android , easy to use unified API and battle tested!

Cross Platform Native Plugins

Usage and Functionalities in Media Library