- Home /
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!
Hey, any update here? I'm hitting on the same wall, so some pointers would be great.
related: http://answers.unity3d.com/questions/22954/how-to-save-a-picture-take-screenshot-from-a-camer.html - btw did you ever got to a good solution for this? it's quite annoying we can't simply replicate the native android's (or iPhone) native screenshot button behavior.
Capture and Save is a great plugin can be use for this requirement.
Answer by cmauceri · Jan 21, 2012 at 04:48 PM
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
I don't think it's so complicated that you will have to write a Plugin... You just need to have the user specify where their Android Gallery path is (if it's different than the default) ... then use the method to capture the screen @ http://answers.unity3d.com/questions/59944/accessing-the-iphone-or-android-camera-for-screens.html
I came to the conclusion that no plugins were necessary too, but since it was part of my original question, I thought I should answer that part too.
I used your post as a starting point actually about two weeks ago, but at the time I didn't have commenting or upvoting privileges. :) Thanks for the help.
I think ins$$anonymous$$d of messing with plugins, I'm going to allow the automatic media scan to take care of updating the gallery, and simply inform the user that the image will be available there on reboot.
You have to send an update to the media content provider for the image to show up right after you saved it. I have to dig for the code in one of our projects, do you still need it?
Answer by tarasfromlviv · Jul 15, 2016 at 02:01 PM
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);
}
}
Hi tarasfromlviv,
I think you're missing some part of the script: What is $$anonymous$$ediaStoreImages$$anonymous$$ediaClass? Should'nt it be a string like "Android.Provider.$$anonymous$$ediaStore.Images.$$anonymous$$edia"?
How/Where do you declare Activity?
Do you import namespaces?
Thanks.
Yeah, sorry I missed some things,
$$anonymous$$ediaStoreImages$$anonymous$$ediaClass is
private const string $$anonymous$$ediaStoreImages$$anonymous$$ediaClass = "android.provider.$$anonymous$$ediaStore$Images$$$anonymous$$edia";
Activity is retrieved as
public static AndroidJavaObject Activity { get { if (_activity == null) { var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); _activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"); } return _activity; } }
This code is actually the part of my asset: https://www.assetstore.unity3d.com/en/#!/content/67473
Still, _activity is not defined. Probably private static AndroidJavaObject _activity; Though, if it's part of your paying asset, you probably don't want to share everything. That's understandable. Thanks.
Finally, THAN$$anonymous$$ YOU! This solution is quick and works great. Thumbs up. This IS the answer.
You are welcome, btw there is also a free version of my plugin https://www.assetstore.unity3d.com/#!/content/66662 which has lots of good AndroidJavaObject examples.
where is it going to save the screenshot/image, so far is not working and is not leting me put private const string $$anonymous$$ediaStoreImages$$anonymous$$ediaClass = "android.provider.$$anonymous$$ediaStore$Images$$$anonymous$$edia"; any help??
Hello Sir, Can you please tell the logic behind these ...
Taras, could you help? Your approach is working really good - i was able to save my screenshot to internal Gallery, but i also need to get the real file path for the image (not only Uri).
I've found lots of examples of how to do it in native Java (check below), but how to make it in c# for Unity?
And one more thing - it seems that even you encode the texture2d as PNG, in gallery - it has Jpg. extension and seems to be JPG file?
public String getRealPathFromURI(Uri contentUri)
{
String[] proj = { $$anonymous$$ediaStore.Audio.$$anonymous$$edia.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow($$anonymous$$ediaStore.Audio.$$anonymous$$edia.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
do you need the plugin for this code to work? Please help if someone tried. It doesn't seem to do anything for me.
Answer by zoooom · Apr 05, 2013 at 12:55 PM
This GitHub repo contains functionality that will allow you to save screenshots and images to the gallery on Android and iOS:
The plugin did the trick to me too. It means there is no simple solution. It offers a compiled library for android and another one for iphone. Awesome plugin! Though this should be default in Unity, which is lame.
Here is cross platform solution to save screenshot to gallery. http://unitydevelopers.blogspot.in/2014/06/capture-and-save-to-camera-roll-and.html
There are 2 versions so you have freedom to select as per your need.
Answer by marsbear · Aug 16, 2012 at 02:10 PM
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.
Thanks for the code, but I'm capturing a snap from Unity, so I can't use that code to update the sdcard.
I'm actually using [code] sendBroadcast(new Intent(Intent.ACTION_$$anonymous$$EDIA_$$anonymous$$OUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()))); [/code] which doesn't give me any errors. I just downloaded eclipse with the Android plugin, to compile it to a .jar and to use it as JNI... but yet, I have no idea on what I'm doing, so I haven't achieved anything yet.
$$anonymous$$y code would only be half the solution. You 'just' have to get your image into a Java plugin within your project. I can test how to do that but not before monday or tuesday.
Answer by alok.kr.029.hotmail · Jul 29, 2014 at 04:32 PM
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[i].SetActive(true);
yield return 0;
bytes = texture1.EncodeToPNG();
File.WriteAllBytes( "/mnt/sdcard/DCIM/Images/" + "DrawCircuit " +save_Address+".jpg",bytes ); }}
must check this blog for best solution http://unitydevelopers.blogspot.in/2014/06/capture-and-save-to-camera-roll-and.html
Your answer
Follow this Question
Related Questions
Screenshot 0 Answers
Black screenshot of the Unity app from Android 0 Answers
Admob 2.1 in Unity. How to ? 1 Answer
Screenshot is not saving to Gallery and folder 2 Answers
How do I save a screenshot to the gallery on Android Kitkat 4.4.2 or above? 1 Answer