How to save a captured photo from unity in Android Image Gallery? - c#

I have a valid script that takes a photo with the AR camera and saves it in data files of Android, like so :
screenShotName = "Dorot" + System.DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") + ".png";
File.WriteAllBytes(Application.persistentDataPath + "/" + screenShotName, screenshot.EncodeToPNG());
GameObject.Find("MainCanvas").GetComponent<Canvas>().enabled = true;
How can I change the persistentDataPath with the right path of Android Image Gallery.
Thanks.

I am using Unity Native Gallery Plugin to do the same exact thing.
This is my code
public class ScreenshotTaker : MonoBehaviour
{
public bool takingScreenshot = false;
public void CaptureScreenshot()
{
StartCoroutine(TakeScreenshotAndSave());
}
private IEnumerator TakeScreenshotAndSave()
{
takingScreenshot = true;
yield return new WaitForEndOfFrame();
Texture2D ss = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
ss.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
ss.Apply();
// Save the screenshot to Gallery/Photos
string name = string.Format("{0}_Capture{1}_{2}.png", Application.productName, "{0}", System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
Debug.Log("Permission result: " + NativeGallery.SaveImageToGallery(ss, Application.productName + " Captures", name));
takingScreenshot = false;
}
}

You can do it as JackMini36 said in his answer by using the plugin. Or you can write you piece of code do that.
But the challenging part will be to make it cross platform and permission issues on Android devices. Here is nicely describe article where you can learn different way to save screenshot in gallery in unity applications.
http://unitydevelopers.blogspot.com/2018/09/save-screenshot-in-unity3d.html

Related

Unity Android save screenshot in gallery

I use this
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class ShareButton : MonoBehaviour {
public void ClickShare()
{
StartCoroutine(TakeSSAndShare());
}
private IEnumerator TakeSSAndShare()
{
string timeStamp = System.DateTime.Now.ToString("dd-MM-yyyy-HH-mm-ss");
yield return new WaitForEndOfFrame();
Texture2D ss = new Texture2D( Screen.width, Screen.height, TextureFormat.RGB24, false );
ss.ReadPixels( new Rect( 0, 0, Screen.width, Screen.height ), 0, 0 );
ss.Apply();
string filePath = Path.Combine( Application.persistentDataPath, "Tanks" + timeStamp + ".png" );
File.WriteAllBytes( filePath, ss.EncodeToPNG() );
Destroy( ss );
}
}
to save screenshot on button press. How can I save it in some folder so it could be found in Android gallery?
You need to get the correct path
In your current solution you would be able to find the screenshot in android/data/com_your_application/files and you probably want to save it in another place.
To save your screenshot in: /storage/emulated/0/DCIM/
You can use Unity's AndroidJavaClass and Object to get the path:
private string GetAndroidExternalStoragePath()
{
if (Application.platform != RuntimePlatform.Android)
return Application.persistentDataPath;
var jc = new AndroidJavaClass("android.os.Environment");
var path = jc.CallStatic<AndroidJavaObject>("getExternalStoragePublicDirectory",
jc.GetStatic<string>("DIRECTORY_DCIM"))
.Call<string>("getAbsolutePath");
return path;
}
This will give you the path to the public DCIM folder in Android and you can then pass that path into your File.WriteAllBytes call
Remember to set write permission to External(SDcard) in Player Settings for Android.
If you don't want your screenshots to appear in the root of the DCIM folder you can simply append a directory to the path.

Screen Captures Using Unity and ARKit

I'm taking a screenshot in a Unity application using
ScreenCapture.CaptureScreenshot ("screenshot.png", 2);
But the AR background being rendered by ARKit ends up being completely black with other GameObjects rendering correctly (floating in black space).
Have others encountered this issue?
Is there a known workaround?
There are too many bugs with ScreenCapture.CaptureScreenshot. Do not use this function to preform any screenshot in Unity at this moment. It's not just on iOS, there are also bug on with this function in the Editor.
Here is a remake of that function that can take screenshot in png, jpeg or exr format.
IEnumerator CaptureScreenshot(string filename, ScreenshotFormat screenshotFormat)
{
//Wait for end of frame
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();
string filePath = Path.Combine(Application.persistentDataPath, "images");
byte[] imageBytes = null;
//Convert to png/jpeg/exr
if (screenshotFormat == ScreenshotFormat.PNG)
{
filePath = Path.Combine(filePath, filename + ".png");
createDir(filePath);
imageBytes = screenImage.EncodeToPNG();
}
else if (screenshotFormat == ScreenshotFormat.JPEG)
{
filePath = Path.Combine(filePath, filename + ".jpeg");
createDir(filePath);
imageBytes = screenImage.EncodeToJPG();
}
else if (screenshotFormat == ScreenshotFormat.EXR)
{
filePath = Path.Combine(filePath, filename + ".exr");
createDir(filePath);
imageBytes = screenImage.EncodeToEXR();
}
//Save image to file
System.IO.File.WriteAllBytes(filePath, imageBytes);
Debug.Log("Saved Data to: " + filePath.Replace("/", "\\"));
}
void createDir(string dir)
{
//Create Directory if it does not exist
if (!Directory.Exists(Path.GetDirectoryName(dir)))
{
Directory.CreateDirectory(Path.GetDirectoryName(dir));
}
}
public enum ScreenshotFormat
{
PNG, JPEG, EXR
}
USAGE:
void Start()
{
StartCoroutine(CaptureScreenshot("screenshot", ScreenshotFormat.PNG));
}

Android not finding file path Unity 5

So I am using the streaming assets folder to hold some information that I need to run my program. Here is how I am determining the filepath to use:
// Location of the top part of the query
public string fileLocation_queryTop = "/Bro/bro_Headers_TOP.json";
// We are on android
if(Application.platform == RuntimePlatform.Android)
{
assetPath = "jar:file://" + Application.dataPath + "!/assets";
}
// We are on iPhone
else if(Application.platform == RuntimePlatform.IPhonePlayer)
{
assetPath = Application.dataPath + "/Raw";
}
// We are on mac or windows
else
{
assetPath = Application.dataPath + "/StreamingAssets";
}
_query_TOP = File.ReadAllText(assetPath + fileLocation_queryTop);
This works fine on Windows, but I am trying to build for Android today.
Here is error that I am getting
I got the info on what path to use from the Unity docs here
I guess what you are looking for is the Application.streamingAssetsPath. You can find more information about it here.
Since you are on Android, you will have to use the WWW class from Unity to retrieve your files.
EDIT:
Following this link you simply have to adjust the file name and store the result in your _query_TOP variable.
private IEnumerator LoadFile()
{
string filePath = System.IO.Path.Combine(Application.streamingAssetsPath, "file.txt");
if(filePath.Contains("://"))
{
WWW www = new WWW(filePath);
yield return www;
if(string.IsNullOrEmpty(www.error))
{
_query_TOP = www.text;
}
}
else
{
_query_TOP = System.IO.File.ReadAllText(filePath);
}
}

Why Unity3D Application.CaptureScreenshot for Android doesn't work?

I have tried all this links bellow:
Not getting image from Persistant path in Android using unity3d
https://developer.vuforia.com/forum/unity-3-extension-technical-discussion/capture-screen-problem-androidhelp
http://answers.unity3d.com/questions/731509/applicationcapturescreenshot-doesnt-save-anything.html
I need to set the path for saving the pictures with an application for Android and IOS with UNITY
http://answers.unity3d.com/questions/200173/android-how-to-refresh-the-gallery-.html#answer-893069
Every time i build an apk, install it on Android device, nothing happend.
Log doesn't exists, so i tryed all this links and then go to /DCIM/Camera/ to see if is it saved, no, nothing...
On iOS i did that, and work perfectly.
Here is some code where i stuck... or the things on Android wont work...
I don't know why no error appear or some file strange in folder
void saveImage()
{
#if UNITY_ANDROID
string theFileName = "Screenshot_" + System.DateTime.Now.ToString("MM_dd_yyyy") +"_"+ System.DateTime.Now.ToString("hh_mm_ss") +".png";
// Many different test, trying to discovery witch will work...
Application.CaptureScreenshot( Application.dataPath + "_" + theFileName );
Application.CaptureScreenshot( "../../../../DCIM/Camera/pathroot_" + theFileName );
Application.CaptureScreenshot( "/storage/emulated/0/DCIM/Camera/" + theFileName );
Application.CaptureScreenshot( "file:///storage/emulated/0/DCIM/Camera/" + theFileName );
StartCoroutine(TakeScreenshot()); // Different test
#endif
#if UNITY_IPHONE
// This work... so, does not need to be here...
#endif
}
This is the method that "Coroutine" calls ( copy from one of those links above ):
private IEnumerator TakeScreenshot()
{
yield return new WaitForEndOfFrame();
//INITIAL SETUP
string myFilename = "Screenshot_" + System.DateTime.Now.ToString("MM_dd_yyyy") +"_"+ System.DateTime.Now.ToString("hh_mm_ss") +".png";
string myDefaultLocation = Application.dataPath + "/" + myFilename;
//EXAMPLE OF DIRECTLY ACCESSING THE Camera FOLDER OF THE GALLERY
//string myFolderLocation = "/storage/emulated/0/DCIM/Camera/";
//EXAMPLE OF BACKING INTO THE Camera FOLDER OF THE GALLERY
//string myFolderLocation = Application.persistentDataPath + "/../../../../DCIM/Camera/";
//EXAMPLE OF DIRECTLY ACCESSING A CUSTOM FOLDER OF THE GALLERY
string myFolderLocation = "/storage/emulated/0/DCIM/Camera/";
string myScreenshotLocation = myFolderLocation + myFilename;
//ENSURE THAT FOLDER LOCATION EXISTS
if(!System.IO.Directory.Exists(myFolderLocation)){
System.IO.Directory.CreateDirectory(myFolderLocation);
}
//TAKE THE SCREENSHOT AND AUTOMATICALLY SAVE IT TO THE DEFAULT LOCATION.
Application.CaptureScreenshot(myFilename);
//MOVE THE SCREENSHOT WHERE WE WANT IT TO BE STORED
System.IO.File.Move(myDefaultLocation, myScreenshotLocation);
//REFRESHING THE ANDROID PHONE PHOTO GALLERY IS BEGUN
AndroidJavaClass classPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject objActivity = classPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaClass classUri = new AndroidJavaClass("android.net.Uri");
AndroidJavaObject objIntent = new AndroidJavaObject("android.content.Intent", new object[2]{"android.intent.action.MEDIA_MOUNTED", classUri.CallStatic<AndroidJavaObject>("parse", "file://" + myScreenshotLocation)});
objActivity.Call ("sendBroadcast", objIntent);
//REFRESHING THE ANDROID PHONE PHOTO GALLERY IS COMPLETE
//AUTO LAUNCH/VIEW THE SCREENSHOT IN THE PHOTO GALLERY
Application.OpenURL(myScreenshotLocation);
//AFTERWARDS IF YOU MANUALLY GO TO YOUR PHOTO GALLERY,
//YOU WILL SEE THE FOLDER WE CREATED CALLED "myFolder"
}
Try This: (Tested & Works):
Application.CaptureScreenshot ("screenshot.png");
store screenshot at:
Application.persistentDataPath, "screenshot.png" i.e data/data/package_name/files
void captureScreenshot(string result){
if (result == "true") {
StartCoroutine(CaptureScreen());
}
}
void OnGUI(){
if (GUI.Button (new Rect (20, 70, 100, 45), "Click"))
captureScreenshot ("true");
}
public IEnumerator CaptureScreen()
{
// Wait for screen rendering to complete
yield return new WaitForEndOfFrame();
Application.CaptureScreenshot ("screenshot.png");
string Origin_Path = System.IO.Path.Combine (Application.persistentDataPath, "screenshot.png");
Debug.Log ("Origin_Path save is " + Origin_Path);
// This is the path of my folder.
string Path = "/mnt/sdcard/" + "screenshot.png";
Debug.Log ("Path save is " + Path);
if (System.IO.File.Exists (Origin_Path)) {
System.IO.File.Move (Origin_Path, Path);
Debug.Log ("Path_move save is " + Path);
}
jo.Call<bool> ("screenshotHandler", "screenshot.png");
}
If you want to store in gallery without Move again then you can use:
Application.CaptureScreenshot ("../../../../DCIM/screenshot.png");
If Error: System.IO.File.Exists (Origin_Path)
//returns FALSE even though file exists at Origin_Path.
Please try this:
public IEnumerator CaptureScreen()
{
Application.CaptureScreenshot ("../../../../DCIM/"+fileName);
Debug.Log ("Sanky: Screen Captured");
while (!File.Exists (filePath)) {
Debug.Log ("Sanky: File exist at location"+filePath);
yield return 0;
}
/////// do whatever you want
}

Not getting image from Persistant path in Android using unity3d

I have a script to take screenshot and save that image and to show that image in a plane.
But not getting that texture.
private string path;
void Start () {
path = Application.persistentDataPath;
}
void captureScreeshot(){
Application.CaptureScreenshot(path + "/Screenshot.png");
alert.text = "saved";
StartCoroutine(saveScreenshot());
onetimeBool = false;
}
IEnumerator saveScreenshot(){
WWW imgfile = new WWW("file://" + path+ "/Screenshot.png");
yield return imgfile;
if(imgfile.error==null){
img = new Texture2D(200, 200, TextureFormat.RGB24, false);
imgfile.LoadImageIntoTexture(img);
alert.text = "got image";
GameObject.Find("plane").renderer.material.mainTexture = img;
}else{
print(imgfile.error);
}
}
Images gets saved.
But I cannot open (load) image in system and android.
Getting error in system :
Couldn't open file /Users/ether/AppData/LocalLow/Company/Project/Screenshot.png
How to get it ???
This is because your path is wrong, you should use: application.dataPath, instead of Application.persistentDataPath.

Categories