I have a project where I use only voice command to perform some different function and one of them is to take a photo using Hololens. So I use the StartCoroutine(photoshoot()); function to call the IEnumerator photoshoot(). The IEnumerator photoshoot() call the TakePhotosnap();.
It takes the photo perfectly but I have issue after taking the photo it doesn't go back to IEnumerator.
It stops the code and can't perform any other function.
As you can see in my code ( I put some numbers to help me explain the function )
I call StartCoroutine(photoshoot()); line 11 and in IEnumerator photoshoot() called the TakePhotosnap(); line 12 and it performs taking photo till line 13 Debug.Log("we finish taking photo successfully "); and then stop. It should go to line 14 in IEnumerator photoshoot().
Here is some of my code
private void Takephoto()
{
// this function is to call to take a photo and save it in a special folder
Debug.Log("Take Photo function call is started");
11 StartCoroutine(photoshoot());
Debug.Log("Take Photo for Hololens");
}
IEnumerator photoshoot()
{
Debug.Log(" The taking photo coroutine is started ");
yield return new WaitForEndOfFrame();
Debug.Log("Take Photo");
12 TakePhotosnap();
14 Debug.Log("Finish taking Hi again ");
yield return new WaitForEndOfFrame();
GameObject.Find("Cube").transform.localPosition = new Vector3(Random.Range(-1, 1), 0, Random.Range(1, 3));
GameObject.Find("Cube").SetActive(true);
}
--------------------------------------------
private void TakePhotosnap()
{
Debug.Log("TakePhoto Call StartPhotoModeAsync () method to start the photo mode");
Debug.Log("snap pic taken");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}
void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
//Store objects, configure shooting parameters and start shooting mode.
Debug.Log("Start taking photo calling function");
photoCaptureObject = captureObject;
Debug.Log("set camera parameters");
Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
CameraParameters c = new CameraParameters();
/// c= CameraParameters
c.hologramOpacity = 1.0f;
c.cameraResolutionWidth = cameraResolution.width;
c.cameraResolutionHeight = cameraResolution.height;
c.pixelFormat = CapturePixelFormat.BGRA32;
Debug.Log("camera parameters finish");
captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted);
}
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
//string filename = string.Format(#"CapturedImage{0}_n.jpg", Time.time);
string filename = string.Format(#"alc.jpg", Time.time);
Debug.Log("FileName: =" + filename);
string filePath = System.IO.Path.Combine(Application.persistentDataPath, filename);
Debug.Log("filePath: =" + filePath);
/////
string targetPath = #"C: \Users\ABC\Pictures\Camera Roll";
string destFile = System.IO.Path.Combine(targetPath, filename);
Debug.Log("destFile: =" + destFile);
if (!System.IO.File.Exists(filePath))
{
//System.IO.File.Create(filePath);
System.IO.File.Create(filePath).Dispose();
}
// https://blog.csdn.net/Lee_gc/java/article/details/79919042
Debug.Log("filePath filePath: =" + filePath);
string filePath2 = System.IO.Path.Combine(Application.dataPath, filename);
Debug.Log("filePath2: =" + filePath2);
Debug.Log("finish to set photo file path and name");
//photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
Debug.LogError("Saved That Image Somewhere" + "FileName: =" + filename + " FilePath: = " + filePath + " FilePath2: = " + filePath2);
Debug.Log("finish to copy photo to new directory");
Debug.Log("finish photo");
photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
13 Debug.Log("we finish taking photo successfuly ");
}
else
{
Debug.LogError("Unable to start photo mode!");
}
}
// clean up
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
Debug.Log("result=" + result);
photoCaptureObject.Dispose();
photoCaptureObject = null;
}
void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
Debug.Log("Saved Photo to disk!");
photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
else
{
Debug.Log("Failed to save Photo to disk");
}
}
}
What is wrong with my code? Is there any other way to solve it?
In fact, code 14 runs earlier than you think. In TakePhotosnap function, when the asynchronous method PhotoCapture.CreateAsync() is run to, this method will return control to the calling method, and then "Finish taking Hi again" will be output Immediately.
In addition, also because of the asynchronous, code 13 will be output before any result returned from TakePhotoAsync method, so it does not mark the photo was taken successfully.
Therefore, we recommend that you add breakpoints to your code to determine whether code 14 is executed, and try to move the log statement to callback. For example:
photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
Debug.Log("we finish taking photo successfuly ");
=>
photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
Debug.Log("we finish taking photo successfuly ");
}
}
Besides, this doc is worth reading through for you: Asynchronous programming with async and await
Related
I'm writing a project, and the part I'm doing now is getting arrow shaped real fast. How can I remove the nested if statements, but still have the same behaviour?
The code below might not look so bad now, but I'm planning on refactoring to include more methods.
public async Task FirstDiffTestAsync()
{
string folderDir = "../../../";
string correctReportDir = folderDir + "Reports To Compare/Testing - Copy.pdf";
string OptyNumber = "122906";
//Making a POST call to generate report
string result = ReportGeneration(OptyNumber).Result;
Response reportResponse = JsonConvert.DeserializeObject<Response>(result);
string newURL = reportResponse.documentUrl;
//Logging the Response to a text file for tracking purposes
await File.WriteAllTextAsync(Context.TestRunDirectory + "/REST_Response.txt", result);
using (StreamWriter w = File.AppendText(Context.TestDir + "/../log.txt"))
{
//Checking if the Integration failed
if (reportResponse.Error == null)
{
//now we have the url, reading in the pdf reports
List<string> Files = new List<string> { correctReportDir, newURL };
List<string> parsedText = PdfToParsedText(Files);
DiffPaneModel diff = InlineDiffBuilder.Diff(parsedText[0], parsedText[1]);
// DiffReport is a customised object
DiffReport diffReport = new DiffReport(correctReportDir, newURL);
diffReport.RunDiffReport(diff);
//In-test Logging
string indent = "\n - ";
string logMsg = $"{indent}Opty Number: {OptyNumber}{indent}Activity Number: {reportResponse.ActivityNumber}{indent}File Name: {reportResponse.FileName}";
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
logMsg += $"{indent}Different lines: {diffReport.insertCounter} Inserted, {diffReport.deleteCounter} Deleted";
}
LogTesting(logMsg, w);
//Writing HTML report conditionally
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
}
Assert.IsTrue(diffReport.insertCounter + diffReport.deleteCounter == 0);
}
else
{
LogTesting($" Integration Failed: {reportResponse.Error}", w);
Assert.IsNull(reportResponse.Error);
}
}
}
As mentioned in the comment, the indentation level is fine for now, but its always better to minimize when possible, especially when you are repeating same blocks of code.
The best way to do this is to write a separate function that contains that block of code and then call that function instead of the nested if statements.
In your case it would be something like this:
private async void checkTotalDiff(diffReport) {
...
}
You could pass anything you might need in the parameters. This way in your main code, you could replace the if statements with checkTotalDiff(diffReport) and save the return (if any) to a variable.
Also note I used void for return but you could change the type depending on what the function returns.
I wouldn't consider this as having an excessive amount of nested if-statements. It is fine as is. Otherwise you could do the following (also suggested by #Caius Jard):
public async Task FirstDiffTestAsync()
{
string folderDir = "../../../";
string correctReportDir = folderDir + "Reports To Compare/Testing - Copy.pdf";
string OptyNumber = "122906";
//Making a POST call to generate report
string result = ReportGeneration(OptyNumber).Result;
Response reportResponse = JsonConvert.DeserializeObject<Response>(result);
//Checking if the Integration failed
if (reportResponse.Error != null)
{
LogTesting($" Integration Failed: {reportResponse.Error}", w);
Assert.IsNull(reportResponse.Error);
return;
}
string newURL = reportResponse.documentUrl;
//Logging the Response to a text file for tracking purposes
await File.WriteAllTextAsync(Context.TestRunDirectory + "/REST_Response.txt", result);
using (StreamWriter w = File.AppendText(Context.TestDir + "/../log.txt"))
{
//now we have the url, reading in the pdf reports
List<string> Files = new List<string> { correctReportDir, newURL };
List<string> parsedText = PdfToParsedText(Files);
DiffPaneModel diff = InlineDiffBuilder.Diff(parsedText[0], parsedText[1]);
// DiffReport is a customised object
DiffReport diffReport = new DiffReport(correctReportDir, newURL);
diffReport.RunDiffReport(diff);
//In-test Logging
string indent = "\n - ";
string logMsg = $"{indent}Opty Number: {OptyNumber}{indent}Activity Number: {reportResponse.ActivityNumber}{indent}File Name: {reportResponse.FileName}";
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
logMsg += $"{indent}Different lines: {diffReport.insertCounter} Inserted, {diffReport.deleteCounter} Deleted";
}
LogTesting(logMsg, w);
//Writing HTML report conditionally
if (diffReport.totalDiff != 0)
{
await File.WriteAllTextAsync(Context.TestRunDirectory + "/DiffReport.html", diffReport.htmlDiffHeader + diffReport.htmlDiffBody);
}
Assert.IsTrue(diffReport.insertCounter + diffReport.deleteCounter == 0);
}
}
I have a problem with an async function in my web-UI which is kind of hard to resolve.
I use a login-function for my program, where the login/session data is handled within the
myLocalStore-Object.
This object is initialized / "injected" at the start of the login-page:
#inject Blazored.LocalStorage.ILocalStorageService myLocalStore
Next, i have my login-function which does two things:
Create directory for user-related data (images, .csv files etc.)
Save Session-related data (User name, Session Path, ExpertMode etc..)
Now, i want to create my directory first, and save the session data aftewards:
public async void SaveSession()
{
ClearSession();
Message = "Session Saved";
string SessionPathRel = "_" + Login.Name + "/";
string SessionPathAbs = Directory.GetCurrentDirectory();
SessionPathAbs = SessionPathAbs + #"\wwwroot\" + "_" + Login.Name + #"\";
//CREATE DIRECTORY
Directory.CreateDirectory(SessionPathAbs);
//SAVE SESSION DATA
await myLocalStore.SetItemAsync("UserLoginName", Login.Name);
await myLocalStore.SetItemAsync("SessionPathAbs", SessionPathAbs);
await myLocalStore.SetItemAsync("SessionPathRel", SessionPathRel);
await myLocalStore.SetItemAsync("isLogged", true);
The problem now is that the program is running, it skips / jumps over the "Directory.CreateDirectory" line and finishes the function without a directory being created. When i use a breakpoint at the relating line, everything is running correctly.
We made some attempts already (using sync instead of async functions, returning Task<Blazored.LocalStorage.ILocalStorageService> instead of void for SaveSession) , but it all did not work out. Does anyone know a solution to this problem?
EDIT:
fixed it with use of the Task.Run() - command. Just paste the code as an example here:
public async Task SaveSession()
{
await ClearSession();
Message = "Session Saved";
string SessionPathRel = "_" + Login.Name + "/";
string SessionPathAbs = Directory.GetCurrentDirectory();
SessionPathAbs = SessionPathAbs + #"\wwwroot\" + "_" + Login.Name + #"\";
//CREATE DIRECTORY
await Task.Run(() => Directory.CreateDirectory(SessionPathAbs));
//SAVE SESSION DATA
await myLocalStore.SetItemAsync("UserLoginName", Login.Name);
await myLocalStore.SetItemAsync("SessionPathAbs", SessionPathAbs);
await myLocalStore.SetItemAsync("SessionPathRel", SessionPathRel);
await myLocalStore.SetItemAsync("isLogged", true);
//GlobalConfiguration.URL_Handler.updateURLWithSubname(Login.Name);
NavigationManager.NavigateTo(URL_Handler.DashboardURL, true);
}
public async Task ClearSession()
{
try{
string SessionPathAbs = await myLocalStore.GetItemAsync<string>("SessionPathAbs");
System.IO.DirectoryInfo SessionDirectoryAbs = new DirectoryInfo(SessionPathAbs);
await Task.Run(() => SessionDirectoryAbs.Delete(true));
//SessionDirectoryAbs.Delete(true);
}
catch
{
}
GlobalConfiguration.URL_Handler.clearURLWithSubname();
Message = "Session is clear";
SessionValue = "";
await myLocalStore.ClearAsync();
}
Good day everyone,
I need to say firstly, that I am not a C# developer in anyway, I have been tasked from my boss to "Make it work".
What I want is to have a thread that will spin off, not interrupt main(), call a function CcnDirSearch() and re perform this action after a certain amount of time.
My code currently runs in console about 1 time (sometimes 6 times) and then stops. I think the threads(or something like this) are ending before the function is completing.
Here is my code:
public int Run()
{
Task.Factory.StartNew(() => CcnDirFireAway());
...
...
//continues main();
>
public void CcnDirFireAway()
{
if (ScanDir != "")
{
Console.WriteLine("Starting Initial Scan on Directory: " + ScanDir + "\n\n\n");
TimerCallback tmCallback = CheckEffectExpiry;
Timer timer = new Timer(tmCallback, "test", 1000, 1000);
}
}
>
public void CheckEffectExpiry(object objectInfo)
{
//TODO put your code
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(DateTime.Now + " Starting Scan.....\n");
Console.ForegroundColor = ConsoleColor.White;
//Here is a call to my function that I want to call.
// I noticed that If I don't call it the programs continues to run harmoniously
Searcher.CcnDirSearch(ScanDir);
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(DateTime.Now + " Finished Scan.....\n");
Console.ForegroundColor = ConsoleColor.White;
}
>
Here is the code of the function I need to call off .
public static void CcnDirSearch(string sDir)
{
try
{
foreach (string file in Directory.EnumerateFiles(sDir, "*.*", SearchOption.AllDirectories))
{
using (var stream = File.OpenRead(file))
{
// Console.WriteLine(DateTime.Now + " Checking File : " + file);
bool Mcard = Searcher.CCNSearch(file, De.Thekid.INotify.Runner.MASTERCARD, false);
bool VCARD = Searcher.CCNSearch(file, De.Thekid.INotify.Runner.VISA, false);
bool ACARD = Searcher.CCNSearch(file, De.Thekid.INotify.Runner.AMEX, false);
if (Mcard)
{
Console.WriteLine(DateTime.Now + " MasterCard Number Found In File >> " + file);
//Inotifywatch.EventForward.UDPSend(512, RServer, ("<30>" + DateTime.Now + " MasterCard Number Found In File >> " + fullpath+ "\n"));
Logger.WriteEvent(DateTime.Now + " MasterCard Number Found In File >> " + file + "\n");
}
else if (VCARD)
{
Console.WriteLine(DateTime.Now + " Visa Card Number Found In File >> " + file);
//Inotifywatch.EventForward.UDPSend(512, RServer, ("<30>" + DateTime.Now + " Visa Card Number Found In File >> " + fullpath+ "\n"));
Logger.WriteEvent(DateTime.Now + " Visa Card Number Found In File >> " + file + "\n");
}
else if (ACARD)
{
Console.WriteLine(DateTime.Now + " AMEX Card Number Found In File >> " + file);
//Inotifywatch.EventForward.UDPSend(512, RServer, ("<30>" + DateTime.Now + " AMEX Card Number Found In File >> " + fullpath+ "\n"));
Logger.WriteEvent(DateTime.Now + " Amex Card Number Found In File >> " + file + "\n");
}
}
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
Console.Write("Finished the Search\n");
}
You could use a DispatcherTimer to call a function on a given time interval, then in that function create and start a new Thread in which you execute your function.
public static void Main(string[] args)
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(5000);;
timer.IsEnabled = true;
timer.Tick += OnTimerTick;
}
private void OnTimerTick(object sender, EventArgs e)
{
var thread = new Thread(new ThreadStart(()=>yourMethodToCall()));
thread.Start();
}
I want to Thanks everyone for all your help. I found a work around that worked for me.
As I said before , I am not a C# developer (I play one on T.V) so I am certain there are somethings where this code base can be improved .
If someone can write a better answer, I will happily accept it.
I just decided to launch the code differntly .
Timer x = new Timer(state => CheckEffectExpiry(1), null, 5000 /* When to start*/, 300000 /* when to retry */);
>
public void CheckEffectExpiry(object objectInfo)
{
//I hate C#'s way of accessing variables and such .
//So I am doing this...
Console.Write(DateTime.Now + " I was hit\n");
if (lockf == 1)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(DateTime.Now + " Starting Scan.....\n");
Console.ForegroundColor = ConsoleColor.White;
lockf = 0;
Searcher.CcnDirSearch(ScanDir);
lockf = 1;
Console.ForegroundColor = ConsoleColor.Red;
Console.Write(DateTime.Now + " Finished Scan.....\n");
Console.ForegroundColor = ConsoleColor.White;
}
}
I've made an app in Unity which has been on the Google Play Store for over a year. Today I wanted to deployt it on Apple App Market but the translations don't work there.
I use the following code to load my app translations
public bool LoadLocalizedText(SystemLanguage language)
{
localizedText = new Dictionary<string, string>();
string filePath = Path.Combine(Application.streamingAssetsPath, "localizedText_" + language + ".json");
WWW reader = new WWW(filePath);
if (reader.text == null || reader.text == "") return false;
while (!reader.isDone) { }
string dataAsJson;
dataAsJson = reader.text;
LocalizationData loadedData = JsonUtility.FromJson<LocalizationData>(dataAsJson);
for (int i = 0; i < loadedData.items.Length; i++)
{
localizedText.Add(loadedData.items[i].key, loadedData.items[i].value);
}
Debug.Log("Data loaded, dictionary contains: " + localizedText.Count + " entries");
if (localizedText.Count == 0) return false;
else
{
isReady = true;
return true;
}
}
Yet somehow, all text fields display "Localized Text Not Found" because it cannot find my Assets... what could this be?
Is this because the StreamingAssets folder isn't copied to xCode?
Is it because the location is different on iOS?
Something else?
This is my folder structure
The WWW or UnityWebRequest API is used to read files on the StreamingAssets on Android. For iOS, The any API from the System.IO namespace such as System.IO.File.ReadAllText should be used.
Something like this:
IEnumerator ReadFromStreamingAssets()
{
string filePath = System.IO.Path.Combine(Application.streamingAssetsPath, "MyFile");
string result = "";
if (filePath.Contains("://"))
{
UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequest.Get(filePath);
yield return www.SendWebRequest();
result = www.downloadHandler.text;
}
else
result = System.IO.File.ReadAllText(filePath);
}
Also, the WWW API is made to be used in a coroutine function so that you can wait or yield it until the download is complete. Your while (!reader.isDone) { } can freeze Unity. That should be while (!reader.isDone) yield return null; which waits every frame until download is finished. The LoadLocalizedText function must also be a coroutine function so the return type should be IEnumerator instead of bool. To make it return bool too, use Action<bool> as parameter.
After fixing both issues, below is what the new code should look like:
public IEnumerator LoadLocalizedText(SystemLanguage language, Action<bool> success)
{
localizedText = new Dictionary<string, string>();
string filePath = Path.Combine(Application.streamingAssetsPath, "localizedText_" + language + ".json");
string dataAsJson;
//Android
if (filePath.Contains("://"))
{
WWW reader = new WWW(filePath);
//Wait(Non blocking until download is done)
while (!reader.isDone)
{
yield return null;
}
if (reader.text == null || reader.text == "")
{
success(false);
//Just like return false
yield break;
}
dataAsJson = reader.text;
}
//iOS
else
{
dataAsJson = System.IO.File.ReadAllText(filePath);
}
LocalizationData loadedData = JsonUtility.FromJson<LocalizationData>(dataAsJson);
for (int i = 0; i < loadedData.items.Length; i++)
{
localizedText.Add(loadedData.items[i].key, loadedData.items[i].value);
}
Debug.Log("Data loaded, dictionary contains: " + localizedText.Count + " entries");
if (localizedText.Count == 0)
success(false);
else
{
isReady = true;
success(true);
}
}
And used like this:
StartCoroutine(LoadLocalizedText(languageInstance, (status) =>
{
if (status)
{
//Success
}
}));
JsonUtility has a problem with iOS so it doesn't work
and if you test in local use File.OpenRead(path) works in iOS
filePath = Application.streamingAssetsPath
StreamReader streamReader = new StreamReader(File.OpenRead(string.Format("{0}/{1}.txt", filePath, fileName)));
and streamingAssets read only if you want to write the file in iOS use this path -> Application.persistentDataPath
Actually the problem is that Application.streamingAssetsPath is not fully correct for iOS device. You need to add "file://" manually to the path as well. Please note that it should be done outside of Path.Combine() method because for some reason, Combine() method strips it =) I wasted couple of hours trying to understand what is going wrong and I hope my post will save someone's time. Proper way to do is: filePath = "file://" System.IO.Path.Combine(Application.streamingAssetsPath, "MyFile"); The rest of the code is the same (this is true for AssetBundles as well)
I'm attempting to capture a photo inside my hololens app. It seems to be working but saving the image to an obscure place that I cant access or view. I want to save it to my pictures library Described here I think. Or where should i save the image so I can see it in my photos on the hololens.
filePath = C:/Data/Users/JanikJoe/AppData/Local/Packages/HoloToolkit-Unity_pzq3xp76mxafg/LocalState\CapturedImage10.02831_n.jpg
filePath2 = C:/Data/Users/DefaultAccount/AppData/Local/DevelopmentFiles/HoloToolkit-UnityVS.Debug_x86.janik/Data\CapturedImage10.02831_n.jpg
using UnityEngine;
using UnityEngine.VR.WSA.WebCam;
using System.Linq;
public class PhotoCaptureFVTC : MonoBehaviour {
UnityEngine.VR.WSA.WebCam.PhotoCapture photoCaptureObject = null;
// Use this for initialization
void Start()
{
Debug.Log("snap pic taken");
PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}
public void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
photoCaptureObject = captureObject;
//Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
CameraParameters c = new CameraParameters();
c.hologramOpacity = 0.0f;
c.cameraResolutionWidth = cameraResolution.width;
c.cameraResolutionHeight = cameraResolution.height;
c.pixelFormat = CapturePixelFormat.BGRA32;
captureObject.StartPhotoModeAsync(c, false, OnPhotoModeStarted);
}
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
photoCaptureObject.Dispose();
photoCaptureObject = null;
}
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
string filename = string.Format(#"CapturedImage{0}_n.jpg", Time.time);
string filePath = System.IO.Path.Combine(Application.persistentDataPath, filename);
string filePath2 = System.IO.Path.Combine(Application.dataPath, filename);
photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
Debug.LogError("Saved That Image Somewhere" +"FileName: ="+ filename + " FilePath: = " + filePath + " FilePath2: = " + filePath2);
}
else
{
Debug.LogError("Unable to start photo mode!");
}
}
void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
Debug.Log("Saved Photo to disk!");
photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
else
{
Debug.Log("Failed to save Photo to disk");
}
}
}
It seems to be that it is not possible to save directly in the camera roll folder and there is no picture library on the HoloLens.
There is the same question here: https://forums.hololens.com/discussion/1458/capturing-photo-in-unity-and-saving-to-disk
I tried the workaround and it works fine. Just move the saved image to the camera roll folder.
#if !UNITY_EDITOR && UNITY_WINRT_10_0
var cameraRollFolder = Windows.Storage.KnownFolders.CameraRoll.Path;
File.Move(_filePath, Path.Combine(cameraRollFolder, _filename));
#endif