Google Firebase and Unity (C#): Unable to download png from bucket - c#

Specs
Unity editor version: 2018.2.8f1
Firebase Unity SDK version: 5.5.0
Additional SDKs: SimpleFirebaseUnity
Developing on: Mac
Export Platform: Android
Issue
I'm having troubles setting up a system to download pictures from storage. I'm not an expert in databases, but I wanted to give it try, just to learn how it is done.
I found Firebase very useful to store metadata on the real-time database and easy to approach even for an entry level programmer like me.
The problem is that I'm trying to download a .png file from a folder in storage, but I can't manage to find if the file is actually downloaded or if it's just lost in the process. I don't get any errors in the console, but when I open the folder in which the files should be, it's empty.
Code
private SimpleFirebaseUnity.Firebase firebaseDatabase;
private FirebaseQueue firebaseQueue;
private FirebaseStorage firebaseStorage;
private StorageReference m_storage_ref;
// Setup refernece to database and storage
void SetupReferences()
{
// Get a reference to the database service, using SimpleFirebase plugin
firebaseDatabase = SimpleFirebaseUnity.Firebase.CreateNew(FIREBASE_LINK, FIREBASE_SECRET);
// Get a reference to the storage service, using the default Firebase App
firebaseStorage = FirebaseStorage.DefaultInstance;
// Create a storage reference from our storage service
m_storage_ref = firebaseStorage.GetReferenceFromUrl(STORAGE_LINK);
// Create a queue, using SimpleFirebase
firebaseQueue = new FirebaseQueue(true, 3, 1f);
}
// ...
IEnumerator DownloadImage(string address, string fileName)
{
var local_path = Application.persistentDataPath + THUMBNAILS_PATH;
var content_ref = m_storage_ref.Child(THUMBNAILS_PATH + fileName + ".png");
content_ref.GetFileAsync(local_path).ContinueWith(task => {
if (!task.IsFaulted && !task.IsCanceled)
{
Debug.Log("File downloaded.");
}
});
yield return null;
}

There can be many reason for why this is not working for you including:
security rules are not setup properly
paths to files are not correct
you are testing it on wrong platform (Firebase is not working well in the editor)
your device is blocking the connection
etc...
In order to get error messages you need to log them:
IEnumerator DownloadImage(string address, string fileName)
{
var local_path = Application.persistentDataPath + THUMBNAILS_PATH;
var content_ref = m_storage_ref.Child(THUMBNAILS_PATH + fileName + ".png");
content_ref.GetFileAsync(local_path).ContinueWith(task => {
if (!task.IsFaulted && !task.IsCanceled)
{
Debug.Log("File downloaded.");
}
else
{
Debug.Log(task.Exception.ToString());
}
});
yield return null;
}
Keep in mind testing it in the editor may not work.

Related

Unity, MacOS, cannot load audio from StreamingAssets using www.SendWebRequest()

I am working on an app targeting Windows, built in Unity.
All the audio files are in streamingAssets so the client can replace them and customize the app.
I have the following code loading the audio files into Audio Sources and it's working fine on Windows.
void SetAudioFromStreamingAssets()
{
if (string.IsNullOrEmpty(StreamingAssetFilePath)) return;
string fullpath = Application.streamingAssetsPath + "/" + StreamingAssetFilePath;
if (!File.Exists(fullpath)) return;
StartCoroutine(SetAudioClipFromFile(source,fullpath));
}
IEnumerator SetAudioClipFromFile(AudioSource audioSource, string path)
{
using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(path, AudioType.UNKNOWN))
{
yield return www.SendWebRequest();
if (www.isNetworkError)
{
VisDebug.AppendTxt("ERROR. Could not load music file: " + www.error, true);
}
else
{
AudioClip myClip = DownloadHandlerAudioClip.GetContent(www);
audioSource.clip = myClip;
}
}
}
A colleage of mine is trying to work on the project but he only has a mac. And the audio is not loading on his mac.
The code is reaching this line..
VisDebug.AppendTxt("ERROR. Could not load music file: " + www.error, true);
So File.Exists is true, and also www.isNetworkError is true.
and the www.error is...
Cannot connect to destination host
EDIT
The answer below is correct and just fyi here is an example of what the path needs to look like on macos.
file:///Users/spoopy/Documents/GitHub/Thing/Assets/StreamingAssets/GameLoad.wav
You have to prefix your path with file:// on MacOS and Linux.
You could put something like this after your variable definition.
#if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
fullpath ="file://" + path);
#endif
Source

How can I open a .pdf file in the browser from a Xamarin UWP project?

I have a Xamarin Project where I generate a .pdf file from scratch and save it in my local storage. This works perfectly fine and can find it and open it in the disk where I saved it. However, I need to open the .pdf file immediately after creation programmatically.
I already tried different variations using Process and ProcessStartInfo but these just throw errors like "System.ComponentModel.Win32Exception: 'The system cannot find the file specified'" and "'System.PlatformNotSupportedException'".
This is basically the path I am trying to open using Process.
var p = Process.Start(#"cmd.exe", "/c start " + #"P:\\Receiving inspection\\Inspection Reports\\" + timestamp + ".pdf");
I also tried ProcessStartInfo using some variations but I'm getting the same errors all over and over.
var p = new Process();
p.StartInfo = new ProcessStartInfo(#"'P:\\Receiving inspection\\Inspection Reports\\'" + timestamp + ".pdf");
p.Start();
The better way is that use LaunchFileAsync method to open file with browser. You could create FileLauncher DependencyService to invoke uwp LaunchFileAsync method from xamarin share project.
Interface
public interface IFileLauncher
{
Task<bool> LaunchFileAsync(string uri);
}
Implementation
[assembly: Dependency(typeof(UWPFileLauncher))]
namespace App14.UWP
{
public class UWPFileLauncher : IFileLauncher
{
public async Task<bool> LaunchFileAsync(string uri)
{
var file = await Windows.Storage.StorageFile.GetFileFromPathAsync(uri);
bool success = false;
if (file != null)
{
// Set the option to show the picker
var options = new Windows.System.LauncherOptions();
options.DisplayApplicationPicker = true;
// Launch the retrieved file
success = await Windows.System.Launcher.LaunchFileAsync(file, options);
if (success)
{
// File launched
}
else
{
// File launch failed
}
}
else
{
// Could not
}
return success;
}
}
}
Usage
private async void Button_Clicked(object sender, EventArgs e)
{
await DependencyService.Get<IFileLauncher>().LaunchFileAsync("D:\\Key.pdf");
}
Please note if you want to access D or C disk in uwp, you need add broadFileSystemAccess capability. for more please refer this .
Update
If the UWP files are network based, not local zone based, you could use Xamarin.Essentials to open file with browser. And you must specify the privateNetworkClientServer capability in the manifest. For more please refer this link.

Vision API C# - reading stored image's URL in Azure

//If the user uploaded an image, read it, and send it to the Vision API
if (activity.Attachments.Any() && activity.Attachments.First().ContentType.Contains("image"))
{
//stores image url (parsed from attachment or mess`enter code here`age)
string uploadedImageUrl = activity.Attachments.First().ContentUrl; ;
uploadedImageUrl = HttpUtility.UrlDecode(uploadedImageUrl.Substring(uploadedImageUrl.IndexOf("file=") + 5));
using (Stream imageFileStream = File.OpenRead(uploadedImageUrl))
{
try
{
analysisResult = await visionClient.AnalyzeImageAsync(imageFileStream, visualFeatures);
}
catch (Exception e)
{
analysisResult = null; //on error, reset analysis result to null
}
}
}
//Else, if the user did not upload an image, determine if the message contains a url, and send it to the Vision API
else
{
try
{
analysisResult = await visionClient.AnalyzeImageAsync(activity.Text, visualFeatures);
}
catch (Exception e)
{
analysisResult = null; //on error, reset analysis result to null
}
}
I am trying the code above. I got the code from here: https://docs.botframework.com/en-us/bot-intelligence/vision/#example-vision-bot.
As is, the code does what it can do when ran locally, but reading the image's URL from an uploaded file doesn't work after I published my bot to Azure and ran it from there.
I attempted to debug by attaching Visual Studio directly to my published webapp bot in Azure. It looked like the webapp is unable read the stored image's URL from the Azure server temp storage location or can't access the temp storage location.
This line:
uploadedImageUrl = HttpUtility.UrlDecode(uploadedImageUrl.Substring(uploadedImageUrl.IndexOf("file=") + 5));
Shows this value:
"https://bcattachmentsprod.blob.core.windows.net/at4984/Gv4cOx6OdSl- original"
Then, this line:
using (Stream imageFileStream = File.OpenRead(uploadedImageUrl))
Changes the value to:
"s://bcattachmentsprod.blob.core.windows.net/at4984/Gv4cOx6OdSl-original"
And then it just stops.
Has anyone ran into an issue like this? How do I go about solving this issue?
Thanks!
If you have a image URL, you should simply call AnalyzeImageAsync with that URL instead of creating a stream as you have. The File class should be used for files on your local drive/network. By creating a stream, you download the image once to your VM, then upload it to the vision service, doubling the work.

Encode existing blob instead of uploading from a local folder

I have a C# program that upload-encode-publish a video from my local folder.I want to change the "filepath" to a "URI of blob" in azure storage account. ie instead of uploading a video and encode-publish, process an uploaded video and encode-publish. Anyone kindly suggest a method to implement this.
namespace OnDemandEncodingWithMES
{
class Program
{
// Read values from the App.config file.
static void Main(string[] args)
{
try
{
// Create and cache the Media Services credentials in a static class variable.
_cachedCredentials = new MediaServicesCredentials(_mediaServicesAccountName,_mediaServicesAccountKey);
Console.WriteLine("Upload a file.\n");
IAsset inputAsset =
UploadFile(Path.(_mediaFiles, #"video.mp4"), AssetCreationOptions.None);
Console.WriteLine("Generate thumbnails and get URLs.\n");
IAsset thumbnailAsset = GenerateThumbnail(inputAsset, AssetCreationOptions.None);
PublishAssetGetURLs(thumbnailAsset, false, ".bmp");
Console.WriteLine("Encode to audio and get an on demand URL.\n");
IAsset audioOnly = EncodeToAudioOnly(inputAsset, AssetCreationOptions.None);
PublishAssetGetURLs(audioOnly);
Console.WriteLine("Encode to adaptive bitraite MP4s and get on demand URLs.\n");
IAsset encodedAsset =
EncodeToAdaptiveBitrateMP4s(inputAsset, AssetCreationOptions.StorageEncrypted);
PublishAssetGetURLs(encodedAsset);
}
}
}
}
Check https://azure.microsoft.com/en-us/documentation/articles/media-services-copying-existing-blob/. Example shows how to create azure media services asset from existing azure storage account

How to check a folder exists in DropBox using DropNet

I'm programming an app that interact with dropbox by use DropNet API. I want to check if the folder is exist or not on dropbox in order to I will create one and upload file on it after that. Everything seen fine but if my folder is exist it throw exception. Like this:
if (isAccessToken)
{
byte[] bytes = File.ReadAllBytes(fileName);
try
{
string dropboxFolder = "/Public/DropboxManagement/Logs" + folder;
// I want to check if the dropboxFolder is exist here
_client.CreateFolder(dropboxFolder);
var upload = _client.UploadFile(dropboxFolder, fileName, bytes);
}
catch (DropNet.Exceptions.DropboxException ex) {
MessageBox.Show(ex.Response.Content);
}
}
I'm not familiar with dropnet, but looking at the source code, it appears you should be able to do this by using the GetMetaData() method off of your _client object. This method returns a MetaData object.
Example:
//gets contents at requested path
var metaData = _client.GetMetaData("/Public/DropboxManagement/Logs");
//without knowing how this API works, Path may be a full path and therefore need to check for "/Public/DropboxManagement/Logs" + folder
if (metaData.Contents.Any(c => c.Is_Dir && c.Path == folder)
{
//folder exists
}

Categories