store voice file path android xamarin - xamarin

the following code is what I use to grab a voice file to send an email as an attachment. However, I am not able to find this file. no clue where it is stored. (this is what I see when I hover the path /storage/emulated/0/test.mp4). the storage folder is empty even when this run, for this reason, the attachment can't be sent. any ideas? Thank you! updated code
string path = "";
public Recorder_Droid()
{
var sqlliteFilname = "test.mp4";
string filePath = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
path = Path.Combine(filePath, sqlliteFilname);
_recorder = new MediaRecorder();
_player = new MediaPlayer();
_player.Completion += (sender, e) => {
_player.Reset();
};
}
MediaRecorder _recorder;
MediaPlayer _player;
public void PlayAudio()
{
if (File.Exists(path))
{
File.Delete(path);
}
if (_recorder == null)
{
_recorder = new MediaRecorder();
}
_recorder.Reset();
_recorder.SetAudioSource(AudioSource.Mic);
_recorder.SetOutputFormat(OutputFormat.Mpeg4);
_recorder.SetAudioEncoder(AudioEncoder.Aac);
_recorder.SetOutputFile(path);
_recorder.Prepare(); // Prepared state
_recorder.Start(); // Recording state.
return;

Related

Download and open picture from url/http [Android Xamarin App]

Hello, would any of you send a working code to download a photo from a given http address on android Xamarin c #?
First, I need to create a new folder for my application files.
My goal is to download the file from the internet to my Android folder (saving this file with its original name is best).
The next step is to display the image from that folder in "ImageView". It is also important that there are permissions in android and I do not fully understand it.
Could any of you send it to me or help me understand it and explain the topic?
*Actually i have this code:
string address = "https://i.stack.imgur.com/X3V3w.png";
using (WebClient webClient = new WebClient())
{
webClient.DownloadFileCompleted += WebClient_DownloadFileCompleted;
webClient.DownloadFile(address, Path.Combine(pathDire, "MyNewImage1.png"));
//System.Net.WebException: 'An exception occurred during a WebClient request.'
}
Loading image from url and display in imageview.
private void Btn1_Click(object sender, System.EventArgs e)
{
var imageBitmap = GetImageBitmapFromUrl("http://xamarin.com/resources/design/home/devices.png");
imagen.SetImageBitmap(imageBitmap);
}
private Bitmap GetImageBitmapFromUrl(string url)
{
Bitmap imageBitmap = null;
using (var webClient = new WebClient())
{
var imageBytes = webClient.DownloadData(url);
if (imageBytes != null && imageBytes.Length > 0)
{
SavePicture("ImageName.jpg", imageBytes, "imagesFolder");
imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
}
}
return imageBitmap;
}
download image and save it in local storage.
private void SavePicture(string name, byte[] data, string location = "temp")
{
var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
documentsPath = System.IO.Path.Combine(documentsPath, "Orders", location);
Directory.CreateDirectory(documentsPath);
string filePath = System.IO.Path.Combine(documentsPath, name);
using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))
{
int length = data.Length;
fs.Write(data, 0, length);
}
}
you need to add permission WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE in AndroidMainfeast.xml, then you also need to Runtime Permission Checks in Android 6.0.
private void checkpermission()
{
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) == (int)Permission.Granted)
{
// We have permission, go ahead and use the writeexternalstorage.
}
else
{
// writeexternalstorage permission is not granted. If necessary display rationale & request.
}
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) == (int)Permission.Granted)
{
// We have permission, go ahead and use the ReadExternalStorage.
}
else
{
// ReadExternalStorage permission is not granted. If necessary display rationale & request.
}
}

Xamarin: Saving files to external storage on Android with an API level >=29

I'm trying to export files to the public external storage of an Android phone in Xamarin, for a backup DB. However, in the last version of Android phones (11.0 - API30), one can't opt-out of scoped storage using the property android:requestLegacyExternalStorage="true" of the <application> tag in the manifest.xml.
I made sure that the permissions READ_EXTERNAL_STORAGE & WRITE_EXTERNAL_STORAGE are granted before trying to create the file. Still, when trying to create a file, a System.UnauthorizedAccessException exception is thrown.
/* file 1: */
// ....
private async void Export_Tapped (object sender, EventArgs e) {
// check if permission for writing in external storage is given
bool canWrite = await FileSystem.ExternalStoragePermission_IsGranted ();
if (!canWrite) {
// request permission
canWrite = await FileSystem.ExternalStoragePermission_Request ();
if (!canWrite) {
// alert user
return;
}
}
// find the directory to export the db to, based on the platform
string fileName = "backup-" + DateTime.Now.ToString ("yyMMddThh:mm:ss") + ".db3";
string directory = FileSystem.GetDirectoryForDatabaseExport (); // returns "/storage/emulated/0/Download"
string fullPath = Path.Combine (directory, fileName);
// copy db to the directory
bool copied = false;
if (directory != null)
copied = DBConnection.CopyDatabase (fullPath);
if (copied)
// alert user
else
// alert user
}
// ....
/* file 2: */
class DBConnection
{
private readonly string dbPath;
// ....
public bool CopyDatabase(string path)
{
byte[] dbFile = File.ReadAllBytes(dbPath);
File.WriteAllBytes(path, dbFile); // --> this is where the exception is thrown <--
return true;
}
// ....
}
So the question stands: how does one write a new file to the public external storage of an Android device with an API level of 29 or more?
All the resources I have found so far, maybe you can gather more information than I did:
https://forums.xamarin.com/discussion/179999/access-denied-to-external-storage
(regarding private external storage) https://forums.xamarin.com/discussion/171039/saving-files-to-external-storage
https://learn.microsoft.com/en-us/xamarin/android/platform/files/external-storage?tabs=windows
https://developer.android.com/about/versions/11/privacy/storage#permissions
Try This , I use a dependency service to call this method in Native Android and save files like docx and pdf from their by byte array.
public async Task<bool> CreateFile(string fileName, byte[] docBytes, string fileType)
{
try
{
Java.IO.File file = new Java.IO.File(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath, fileName + fileType);
OutputStream os = new FileOutputStream(file);
os.Write(docBytes);
os.Close();
}
catch
{
return false;
}
return true;
}
The path you use is incorrect, please try the following file path .
Context context = Android.App.Application.Context;
var filePath = context.GetExternalFilesDir(Android.OS.Environment.DirectoryDocuments);
Refer to https://forums.xamarin.com/discussion/comment/422501/#Comment_422501 .

Change DisplayImage while playing Mp3 file using CrossMediaManager in Xamarin forms IOS

I am trying to change the Display Image while playing mp3 file using CrossMediaManager, but It seems it doesn't change the image. It does change the title, id and so on, but I don't know why it can't change the display image.
async Task ExecutePlayChapterCommand()
{
if (IsBusy) return;
IsBusy = true;
try
{
await Task.Delay(TimeSpan.FromMilliseconds(10));
var reciter = Reciters.FirstOrDefault();
Device.BeginInvokeOnMainThread(async() => {
var mediaItem = await CrossMediaManager.Current.Play(reciter.DownloadURL);
CrossMediaManager.Current.Queue.Current.IsMetadataExtracted = false;
mediaItem.Title = reciter.Name;
var image = new Image() { Source = ImageSource.FromUri(new Uri(reciter.ImagePath)) };
CrossMediaManager.Current.Queue.Current.Title = string.Format("{0} - {1} ({2})", "1", "ChName", "English");
CrossMediaManager.Current.Queue.Current.Album = reciter.Name;
CrossMediaManager.Current.Queue.Current.Artist = reciter.Name;
CrossMediaManager.Current.Queue.Current.AlbumImage = image;
CrossMediaManager.Current.Queue.Current.AlbumImageUri = reciter.ImagePath;
CrossMediaManager.Current.Queue.Current.DisplayImage = image;
CrossMediaManager.Current.Queue.Current.DisplayImageUri = reciter.ImagePath;
CrossMediaManager.Current.Queue.Current.Image = image;
CrossMediaManager.Current.Queue.Current.ImageUri = reciter.ImagePath;
CrossMediaManager.Current.Notification.UpdateNotification();
});
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
finally { IsBusy = false; }
}
}
A sample project is uploaded in here
This answer might be a little bit late, but it worked for me perfectly.
First, the "Image, DisplayImage" properties of the media items are objects, that contain native representations of the cover image (UIImage and Bitmap) in the platform specific projects, so do not assign them any value.
Create your media item like this, without assigning the properties mentioned above.
new MediaItem(chapter.MediaUrl)
{
ImageUri = item.ImageUrl,
DisplayImageUri = item.ImageUrl,
AlbumImageUri = item.ImageUrl,
DisplayTitle = item.Title,
Title = item.Title,
Artist = item.Author,
Author = item.Author,
};
Then, on iOS, after setting the Queue items of the media items, in the platform specific project, create a method that takes the media item. This method will be called from the shared project.
Here is the method.
public void SetMediaImages(IMediaManager mediaManager)
{
if (mediaManager.Queue != null && mediaManager.Queue.Any())
{
foreach (var mediaItem in mediaManager.Queue)
{
if (!string.IsNullOrEmpty(mediaItem.ImageUri))
{
mediaItem.Image = UIImage.LoadFromData(NSData.FromUrl(new NSUrl(mediaItem.ImageUri)));
mediaItem.AlbumImage = mediaItem.Image;
}
}
}
}
Call this method in your shared project using Xamarin.Form's dependency service.

How to share contact data of my app with whtsapp in .vcf /vcard format using xamarin forms

I have an application that creates a .vcf file after you input data. it stores storage provided by the phone, I want to click on a list view item and get the vcf file and share it via Email, SMS, WhatsApp, Skype etc how do I implement this in IOS and Android.
Thank you
I have got the answer of creating .vcf file which is given below. and for share that file follow this link : https://github.com/adamped/ShareDialog
private void Share_Clicked(object sender, EventArgs e)
{
try
{
var _btn = sender as Button;
var record = _btn.BindingContext as Contact;
int tempcontactID = record.ContactID;
if (record.CardFrontImage == null)
{
record.CardImage = record.CardBackImage;
}
else
{
record.CardImage = record.CardFrontImage;
}
string baseimage = Convert.ToBase64String(record.CardImage);
var vcf = new StringBuilder(); //vcf code start
vcf.AppendLine("BEGIN:VCARD");
vcf.AppendLine("VERSION:3.0");
vcf.AppendLine($"N:{record.ContactName};{string.Empty}; ;;");
vcf.AppendLine($"FN:{record.ContactName}");
vcf.AppendLine($"ORG:{record.CompanyName}");
vcf.AppendLine($"TITLE:{record.Designation}");
vcf.AppendLine($"PHOTO;ENCODING=BASE64;TYPE=PNG:{baseimage}");
vcf.AppendLine($"TEL;TYPE=work,voice;VALUE=uri:tel:{record.PhoneNumber}");
vcf.AppendLine("END:VCARD");
string fileName = Path.Combine("/storage/emulated/0/Android/data/com.Gamma.GammaNetworkingApp/files/", record.ContactID + record.ContactName + ".vcf");
using (var writer = new StreamWriter(fileName))
{
writer.Write(vcf.ToString());
}
string text = File.ReadAllText(fileName);
bool doesExist = File.Exists(fileName);
if (doesExist == true)
{
var share = DependencyService.Get<IShare>();
share.Show("Contact share", record.ContactName, fileName);
}
}
catch (Exception ex)
{
string test = ex.ToString();
Navigation.PushAsync(new HomePage());
}
}

Sending an email with attachment in Xamarin.Forms for Android and iOS

I am creating an app to send an email with an attachment. I have tried using mailTo to do it but it is not working. Are there any other ways to send an email with attachment?
This is the code that I have tried so far
private void Button_Clicked_1(object sender, EventArgs e)
{
string toEmail = "toemail#nyp.edu.sg";
string emailSubject = "Test Email";
string emailBody = "Email Body";
string attachment = "C:/Users/L30901/Desktop/download.jpg";
Device.OpenUri(new Uri(String.Format("mailto:{0}?subject={1}&body={2}&attachment=file:///{3}", toEmail, emailSubject, emailBody, attachment)));
}
This is what I did for iOS
MainPage.xaml.cs
private void Button_Clicked_1(object sender, EventArgs e)
{
DependencyService.Get<IDependency>().SendEmail();
}
IDependency.cs
public interface IDependency
{
void SendEmail();
}
IOSEmail.cs
[assembly: Dependency(typeof(IOSEmail))]
namespace Notification.iOS
{
public class IOSEmail : IDependency
{
MFMailComposeViewController mailController;
public void SendEmail()
{
if (MFMailComposeViewController.CanSendMail)
{
mailController = new MFMailComposeViewController();
mailController.SetToRecipients(new string[] { "some.person#somewhere.com" });
mailController.SetSubject("Testing");
mailController.SetMessageBody("See attached file", false);
NSData data = NSData.FromFile(pdffilename);
mailController.AddAttachmentData(data, "application/jpeg", "xxxxx.jpg");// For JPEG
mailController.Finished += HandleMailFinished;
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(mailController, true, null);
}
}
private void HandleMailFinished(object sender, MFComposeResultEventArgs e)
{
e.Controller.DismissViewController(true, null);
}
What you need to do can only be done using Xamarin.Forms DependencyService:
For Android you need to do something like this:
Get the Directory of your attachment using Java.IO:
Java.IO.File dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads);
Note: I have used the downloads directory you can change it as per your need at any point in time.
Once you are done with picking that directory using Android OS environment then pick the file something like this;
Java.IO.File file = new Java.IO.File(dir, "yourFile.pdf"); //This could be any other type of file aswell
Get the URI of that Android file something like this:
Android.Net.Uri path = Android.Net.Uri.FromFile(file);
Create the Intent to send the data from to your Emailing app something like this:
var email = new Intent(Android.Content.Intent.ActionSend);
email.PutExtra(Android.Content.Intent.ExtraEmail,
new string[] { "some.person#somewhere.com" }); // to whom you want to send the email
email.PutExtra(Android.Content.Intent.ExtraCc,
new string[] { "some.person#somewhereelse.com" }); // to whom you want to Copy in the email (CC)
email.PutExtra(Android.Content.Intent.ExtraSubject, "Awesome File");
email.PutExtra(Android.Content.Intent.ExtraText,
"See attached file");
email.PutExtra(Intent.ExtraStream, path);
email.SetType("message/rfc822");
StartActivity(email);
For IOS you need to do something like this:
Create an instance of MFMailComposeViewController and add a subject and message body to it;
var mailer= new MFMailComposeViewController();
mailer.SetSubject("xxxx");
mailer.SetMessageBody("", true);
mailer.Finished += HandleMailFinished; //This controllers finished event in case you need it
Now it is mandatory that you have your file in the document directory for it to be available to the application for more information check Working with the File System
Assuming that you read that and you have added the file to the document directory of your application get the NSData for your attachment:
NSData data = NSData.FromFile(pdfFileName);
mailer.AddAttachmentData(data, "application/pdf", "xxxxx.pdf");// For PDF
mail.AddAttachmentData(csvdata, "application/csv", "csv.txt"); // For CSV/TXT
Get the currently displayed Viewcontroller something like this:
public UIViewController GetCurrentUIController()
{
UIViewController viewController;
var window = UIApplication.SharedApplication.KeyWindow;
if (window == null)
{
return null;
}
if (window.RootViewController.PresentedViewController == null)
{
window = UIApplication.SharedApplication.Windows
.First(i => i.RootViewController != null &&
i.RootViewController.GetType().FullName
.Contains(typeof(Xamarin.Forms.Platform.iOS.Platform).FullName));
}
viewController = window.RootViewController;
while (viewController.PresentedViewController != null)
{
viewController = viewController.PresentedViewController;
}
return viewController;
}
Then Present the Viewcontroller something like this:
var _CurrentViewComtroller= GetCurrentUIController();
_CurrentViewComtroller?.PresentViewController(mailer, true, null);
The Handled Finish method would be something like this:
private void HandleMailFinished(object sender, MFComposeResultEventArgs args)
{
DismissViewController (true, null);
}

Resources