Can't copy file to the public storage - c#

I am trying to start an intent in order to open an image file, I download from the internet.
The image file I can download to the internal storage of the app, but I can't copy it to the public /Documents directory on my Android device, in order to start the intent.
This is how I copy the file
var bytes = System.IO.File.ReadAllBytes (privatePath);
Java.IO.File docFolder = new Java.IO.File (global::Android.OS.Environment.ExternalStorageDirectory + "/MyAppCache");
if (!docFolder.Exists ()) docFolder.Mkdir ();
Java.IO.File file = new Java.IO.File (docFolder.AbsolutePath, "cache.jpg");
file.CreateNewFile();
Java.IO.FileOutputStream fOut = new Java.IO.FileOutputStream (file);
fOut.Write (bytes);
fOut.Close ();
return file.AbsolutePath;
the returned path I use for
global::Android.Net.Uri uri = global::Android.Net.Uri.Parse(FilePublisher.CopyToPublic());
StartActivity (new Intent (Intent.ActionView, uri));
The result I get is
No Activity found to handle Intent { act=android.intent.action.VIEW dat=/storage/emulated/0/MyAppCache/cache.jpg }
I checked the /storage folder on my device and there isn't even the MyAppCache folder in it.
What is wrong here?

The URI you are passing in the Intent doesn't contain the scheme. You can see this from the error:
No Activity found to handle Intent { act=android.intent.action.VIEW dat=/storage/emulated/0/MyAppCache/cache.jpg }
The "dat=" needs to start with file:///.

Related

MediaSource.CreateFromUri(...) cannot retrieve the file for MediaSource.

Here is my code........
public MediaPlaybackItem GetMediaPlaybackItemFromPath(string path)
{
//StorageFile file = await StorageFile.GetFileFromPathAsync(path);
var source = MediaSource.CreateFromUri(new Uri(path));
return new MediaPlaybackItem(source);
}
If I use this method I cannot play music. But if I try this I can play music.
public async Task<MediaPlaybackItem> GetMediaPlaybackItemFromPathAsync(string path)
{
StorageFile file = await StorageFile.GetFileFromPathAsync(path);
var source = MediaSource.CreateFromStorageFile(file);
return new MediaPlaybackItem(source);
}
Whats the problem with this? I am using mediaplaybacklist for MediaPlayer.Source . How can I get proper MediaSource using my first method? Help me please.
You could not pass file path parameter to CreateFromUri directly. In general, the Uri parameter is http protocol address such as http://www.testvideo.com/forkvideo/test.mp4. But we could pass the file path with uwp file access uri scheme.
For example:
Media file stored in the installation folder.
ms-appx:///
Local folder.
ms-appdata:///local/
Temporary folder.
ms-appdata:///temp/
For more you could refer this document.

How to download a file in my app from a cloud with a content URI

I want to download a (zip) file from my cloud storage to my app using an intent. I succeeded to access to my cloud with :
var activity = (Activity)Xamarin.Forms.Forms.Context;
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file
// browser.
Intent intent = new Intent(Intent.ActionGetContent);
// Filter to only show results that can be "opened", such as a
// file (as opposed to a list of contacts or timezones)
intent.AddCategory(Intent.CategoryOpenable);
// Filter to show only images, using the image MIME data type.
// If one wanted to search for ogg vorbis files, the type would be "audio/ogg".
// To search for all documents available via installed storage providers,
// it would be "*/*".
intent.SetType("*/*");
activity.StartActivityForResult(intent, 0);
and I have my OnActivityResult like this in my Mainactivity.cs :
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 0)
{
System.Uri uri = new System.Uri(data.Data.ToString());
WebClient myWebClient = new WebClient();
myWebClient.DownloadFile(uri, "/root"));
}
}
But I think that my uri adress is not good because it's a content uri but not a file uri. So how I could have a valid file uri from my content uri please ?
Solved by using :
System.Uri uri = new System.Uri(data.Data.ToString());
ContentResolver rc = ContentResolver;
var stream = rc.OpenInputStream(data.Data);
try
{
using (var fileStream = System.IO.File.Create(filepath))
{
stream.CopyTo(fileStream);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("exception :" + ex.Message);
}

Retrieving recorded media (videos/photos)

I'm having trouble retrieving videos that I have recorded from my app on my iPhone.
The purpose of this is to upload this recorded video to Amazon Web Service's cloud (store it in a bucket).
However I seem to only be have directory access capabilities instead of the actual files. I don't know if this is a permissions issue or if there's a specific class that allows me to retrieve recorded videos.
This snippet of code saves the video:
var options = new PHAssetResourceCreationOptions {};
var changeRequest = PHAssetCreationRequest.CreationRequestForAsset ();
changeRequest.AddResource (PHAssetResourceType.Video, outputFileUrl, options);
The path from the outputFileUrl, which saves to the iPhone's temp folder, is how I was going about trying to retrieve the file to upload but to no success.
Can someone help me with this?
I have an toggle Record Event that gets the file like this:
// Start recording to a temporary file.
MovieFileOutput.StartRecordingToOutputFile (new NSUrl(GetTmpFilePath ("mov"), false), this);
This is the definition for GetTmpFilePath():
static string GetTmpFilePath (string extension)
{
// Start recording to a temporary file.
string outputFileName = NSProcessInfo.ProcessInfo.GloballyUniqueString;
string tmpDir = Path.GetTempPath();
string outputFilePath = Path.Combine (tmpDir, outputFileName);
return Path.ChangeExtension (outputFilePath, extension);
}
outputFileUrl is a NSUrl and is the result of this, it is a parameter to the method that uses this in the "AddResource" above.

xamarin.forms save file/image

coding xamarin form project and also using pcl storage. have problem with saving image or file on device all examples i found show how to save stream of byte array into file but non of them show how to turn convert image into usable format for saving.
var webImage = new Image();
webImage.Source = new UriImageSource
{
CachingEnabled = false,
Uri = new Uri("http://server.com/image.jpg"),
};
byte[] image = ????(what i need)????(webImage.Source);
// get hold of the file system
IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
// create a file, overwriting any existing file
IFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
// populate the file with image data
using (System.IO.Stream stream = await file.OpenAsync(FileAccess.ReadAndWrite))
{
stream.Write(image, 0, image.Length);
}
In other words looking for code to save image/file on device from url.
Tried ffimageloading since it contain converter to byte[], but always get error:"Object reference not set to an instance of an object." for GetImageAsJpgAsync and GetImageAsPngAsync method. problem might be that image isn't fully loaded. but finish event and finish command never get called even trough image is fully loaded on screen and bound to cachedImage.
var cachedImage = new CachedImage()
{
Source = "https://something.jpg",
FinishCommand = new Command(async () => await TEST()),
};
cachedImage.Finish += CachedImage_Finish;
var image = await cachedImage.GetImageAsJpgAsync();
With FFImageLoading (I noticed you use it):
await ImageService.Instance.LoadUrl("https://something.jpg").AsJpegStream();
If you want to get original file location, use this:
await ImageService.Instance.LoadUrl("https://something.jpg").Success((imageInfo) => { //TODO imageInfo.FilePath } ).DownloadOnly();

Downloading mp3 files directly

I've been using xamarin for a while and the current project I'm working on will require some mp3 files to be downloaded.
I saw tutorials for downloading a file and downloading an image, but they didn't lead me anywhere and are for iOS.
Given a url www.xyz.com/music.mp3, how do I download the mp3 file and save it?
Simplest way is to use WebClient and if on the UI thread then call method DownloadFileTaskAsync:
button.Click += async delegate
{
var destination = Path.Combine(
System.Environment.GetFolderPath(
System.Environment.SpecialFolder.ApplicationData),
"music.mp3");
await new WebClient().DownloadFileTaskAsync(
new Uri("http://www.xyz.com/music.mp3"),
destination);
};
Xamarin.iOS Docs converted to download bytes
The Xamarin.iOS docs WebClient sample for downloading a file should work just fine after you tweak from downloading a string to downloading bytes (note DownloadDataAsync and DownloadDataCompleted vs String sibling functions).
var webClient = new WebClient();
webClient.DownloadDataCompleted += (s, e) => {
var text = e.Result; // get the downloaded text
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string localFilename = "downloaded.mp3";
string localPath = Path.Combine (documentsPath, localFilename);
File.WriteAllText (localpath, text); // writes to local storage
};
var url = new Uri("http://url.to.some/file.mp3"); // give this an actual URI to an MP3
webClient.DownloadDataAsync(url);
Using HttpClient
If you want to use the newer HttpClient library. Add a reference to System.Net.Http to your Xamarin.Android project and give something like this a shot.
var url = new Uri("http://url.to.some/file.mp3");
var httpClient = new HttpClient ();
httpClient.GetByteArrayAsync(url).ContinueWith(data => {
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string localFilename = "downloaded.mp3";
string localPath = Path.Combine (documentsPath, localFilename);
File.WriteAllBytes (localPath, data.Result);
});

Categories