I've been trying to create a function where the user will download a file(PDF) when a button is clicked.
I stored the file in firebase storage and can be accessible via url/link. I found this solution How to download files in Xamarin.Forms? that helps you download from a url. However I got an error that say **System.UnauthorizedAccessException:** 'Access to the path '/data/user/0/com.companyname.pawadopt_v5/files' is denied.' I already made sure to check and request permission using Xamarin.Essentials but I keep getting this error even with Permission.Granted for StorageRead and StorageWrite.
Here is my code:
Download Function
public async Task<bool> DownloadFile(string fileURL)
{
var checkPermission = await PermissionServices.PermissionClientInstance.checkStorage();
if(checkPermission == true)
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
try
{
var client = new HttpClient();
var downloadStream = await client.GetStreamAsync(fileURL);
var fileStream = File.Create(path);
await downloadStream.CopyToAsync(fileStream);
return true;
}
catch (Exception ex)
{
return false;
}
}
else
{
return false;
}
}
Check and Request Permission
var Readpermission = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
var Writepermission = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
if (Readpermission != PermissionStatus.Granted || Writepermission != PermissionStatus.Granted)
{
Readpermission = await Permissions.RequestAsync<Permissions.StorageRead>();
Writepermission = await Permissions.RequestAsync<Permissions.StorageWrite>();
}
if (Readpermission != PermissionStatus.Granted && Writepermission != PermissionStatus.Granted)
return false;
else
return true;
What are your thoughts and solutions about this?
Any ideas and solution are greatly appreciated
UPDATE
When I changed the path into string localPath = Path.Combine(FileSystem.AppDataDirectory,"File.pdf");, No error shows and prompt the 'Download Successful'. However I cant find where this local path is.
Our c# application has been using an older version of Twilio for a while & now that Twilio version is scheduled to be deprecated next month. I updated our application to the latest version of Twilio.API and everything's working fine, with the exception of some code which returns the sms message response based on the message's sid.
Here's our old code. The line which reads: "var response = trc.GetFeedback(Sid);" is the problem.
This is deprecated & no longer viable in the updated version of twilio. Does anyone know of an updated approach to returning the sms message response based on the sid?:
public class SmsUtil
{
private readonly string twilioAuth = ConfigurationManager.AppSettings["Twilio_Auth"].ToString();
private readonly string twilioAuthToken = ConfigurationManager.AppSettings["Twilio_Auth_Token"].ToString();
private Twilio.TwilioRestClient trc;
public SmsUtil()
{
trc = new Twilio.TwilioRestClient(twilioAuth, twilioAuthToken);
}
public IAppResult GetStatus(String Sid)
{
IAppResult result = new AppResult();
try
{
var response = trc.GetFeedback(Sid);
result.Data = response;
result.Code = response.Issues.Count == 0 ? 0 : -1;
}
catch (Exception ex)
{
result.Code = -1;
result.Message = "Error - Sending Text";
result.Data = ex.Message;
}
return result;
}
}
My service is register with azzure notification hub. And using my .net server API it push notification to particular device within particular time frame.
Everything goes right except when I try to send multiple push in same code it stuck with "BadRequest" except first one.
Below is the code
public static async void SendAzzurePushNotification()
{
for (int i = 0; i < 10; i++)
{
HttpStatusCode pushNotificationStatus = await CreateAndPushAsync("user_37");
Console.WriteLine(pushNotificationStatus);
}
}
static async Task<HttpStatusCode> CreateAndPushAsync(string tag)
{
HttpStatusCode pushNotificationStatus = HttpStatusCode.NotImplemented;
try
{
HttpResponseMessage response = null;
string uri = "<HUBURI>";
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("SharedAccessSignature", <SASTOKEN>);
client.DefaultRequestHeaders.Add("ServiceBusNotification-Format", "gcm");
client.DefaultRequestHeaders.Add("ServiceBusNotification-Tags", tag);
client.DefaultRequestHeaders.Add("x-ms-version", "2015-01");
response = await client.PostAsync(uri,
new StringContent("{\"data\":{\"message\":\"Notification Hub test notification\"}}", Encoding.UTF8, "application/json"));
pushNotificationStatus = response.StatusCode;
}
catch (Exception ex)
{
throw;
}
return pushNotificationStatus;
}
Above code give me Created status for first time and then BadRequest after that. If same api I call from client like postman. It work fine.
I also tried nuget package from azure notification hub, regarding which code is as below. Which solve my above issue but it won't return me any status code which I can have in my above code for success.
NotificationHubClient hub = NotificationHubClient.CreateClientFromConnectionString("<CONNECTIONSTRING>", "<HUB>");
NotificationOutcome outcome = await hub.SendGcmNativeNotificationAsync("{\"data\":{\"message\":\"Notification Hub test notification\"}}", "user_37");
Call send method with your tags and your notification-data
private static readonly string Endpoint = #"Your End Point";
private static readonly string HubName = #"You Hub Name";
private static NotificationHubClient Hub { get { return NotificationHubClient.CreateClientFromConnectionString(Endpoint, HubName); } }
public static async Task Send(string[] tags, object data)
{
try
{
string payload = string.Empty;
string json_gcm = string.Empty;
if (data.GetType() != typeof(string))
{
//If your notification data is of type
payload = JsonConvert.SerializeObject(data);
json_gcm = "{ \"data\" : " + payload + "}";
}
else
{
//If your notification data is simply is in string
payload = Convert.ToString(data);
json_gcm = "{ \"data\" : {\"message\":\"" + payload + "\"}}";
}
// Android
NotificationOutcome gcmOutcome = null;
gcmOutcome = await Hub.SendGcmNativeNotificationAsync(json_gcm, tags);
if (gcmOutcome != null)
{
if (!((gcmOutcome.State == NotificationOutcomeState.Abandoned) || (gcmOutcome.State == NotificationOutcomeState.Unknown)))
{
//Do code when notification successfully send to Android
}
}
}
catch (Exception ex)
{
//Do code when any exception occurred while sending notification
}
}
NotificationOutcomeState: Gives you status code in the form of enum that represent your notification has been successfully sent or not.
You may ignore if-else block as your need.
Try once may it help you
I am trying to send e-mail from within a Xamarin Forms app, using Gmail.
I have created an Interface with only 1 method: SendEmail();
Then, in the Droid project, I added a class which implements said interface. Using the Dependency attribute and getting the implementation of the method in the main project, all is fine, except the following error:
Could not resolve host 'smtp.gmail.com'
This is the actual implementation of the method:
string subject = "subject here ";
string body= "body here ";
try
{
var mail = new MailMessage();
var smtpServer = new SmtpClient("smtp.gmail.com", 587);
mail.From = new MailAddress("myEmailAddress#gmail.com");
mail.To.Add("anotherAddress#yahoo.com");
mail.Subject = subject;
mail.Body = body;
smtpServer.Credentials = new NetworkCredential("username", "pass");
smtpServer.UseDefaultCredentials = false;
smtpServer.EnableSsl = true;
smtpServer.Send(mail);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
}
Searching around I could not find any details regarding it other that the actual smtp address.
Also, I have used the Less Secure apps procedure from Google, not receiving a credentials error I assume that it can connect to the account just fine.
Hello I have achieve this using the code below, also I have attached a file to the email, using the dependency service I use this methods:
Android:
public static string ICSPath
{
get
{
var path = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, StaticData.CalendarFolderName);
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
return Path.Combine(path, StaticData.CalendarFileName);
}
}
public async Task<bool> ShareCalendarEvent(List<ISegment> segmentList)
{
Intent choserIntent = new Intent(Intent.ActionSend);
//Create the calendar file to attach to the email
var str = await GlobalMethods.CreateCalendarStringFile(segmentList);
if (File.Exists(ICSPath))
{
File.Delete(ICSPath);
}
File.WriteAllText(ICSPath, str);
Java.IO.File filelocation = new Java.IO.File(ICSPath);
var path = Android.Net.Uri.FromFile(filelocation);
// set the type to 'email'
choserIntent.SetType("vnd.android.cursor.dir/email");
//String to[] = { "asd#gmail.com" };
//emailIntent.putExtra(Intent.EXTRA_EMAIL, to);
// the attachment
choserIntent.PutExtra(Intent.ExtraStream, path);
// the mail subject
choserIntent.PutExtra(Intent.ExtraSubject, "Calendar event");
Forms.Context.StartActivity(Intent.CreateChooser(choserIntent, "Send Email"));
return true;
}
iOS:
public static string ICSPath
{
get
{
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), StaticData.CalendarFolderName);
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
return Path.Combine(path, StaticData.CalendarFileName);
}
}
public async Task<bool> ShareCalendarEvent(List<ISegment> segmentList)
{
//Create the calendar file to attach to the email
var str = await GlobalMethods.CreateCalendarStringFile(segmentList);
if (File.Exists(ICSPath))
{
File.Delete(ICSPath);
}
File.WriteAllText(ICSPath, str);
MFMailComposeViewController mail;
if (MFMailComposeViewController.CanSendMail)
{
mail = new MFMailComposeViewController();
mail.SetSubject("Calendar Event");
//mail.SetMessageBody("this is a test", false);
NSData t_dat = NSData.FromFile(ICSPath);
string t_fname = Path.GetFileName(ICSPath);
mail.AddAttachmentData(t_dat, #"text/v-calendar", t_fname);
mail.Finished += (object s, MFComposeResultEventArgs args) =>
{
//Handle action once the email has been sent.
args.Controller.DismissViewController(true, null);
};
Device.BeginInvokeOnMainThread(() =>
{
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(mail, true, null);
});
}
else
{
//Handle not being able to send email
await App.BasePageReference.DisplayAlert("Mail not supported",
StaticData.ServiceUnavailble, StaticData.OK);
}
return true;
}
I hope this helps.
Figured it own finally!
First of all, I was using Android Player by Xamarin, which apparently does not support network connectivity.
So my fix was easy: used an Android Emulator ( any version of it for that matter ) built in Visual Studio Community 2015, and tested network connectivity using the plugin by James Montemagno ( Xam.Plugin.Connectivity on NuGet ).
I am developing a Windows store app, however I used this method to generate an user id when the app open by first time
private string host = "http://etc.com";
public async void RegisterUsuario() {
string displayName = await UserInformation.GetDisplayNameAsync();
string url = host + "/json/Register.php?code=" + displayName;
try
{
var http = new HttpClient();
var jsonText = await http.GetStringAsync(url);
var jsonValues = JsonArray.Parse(jsonText)[0];
var status = jsonValues.GetObject().GetNamedString("status");
if (status == "error")
{
var dialog = new MessageDialog("No se pudo registrar tu usuario", "¡Oops!");
await dialog.ShowAsync();
}
else
{
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
localSettings.Values["usuario"] = jsonValues.GetObject().GetNamedNumber("id");
}
}
catch {
alertCatch("No se pudo registrar tu usuario");
}
}
THE JSON RESPONSE:
[{"status":"success","id":32}]
The problem:
In my pc always works fine, but when I submit the app to the windows store I always get this:
http://imgur.com/lOT09l7
the same error that will show the app in the CATCH.
Can you help me, maybe something in the appxmanifest?
In capabilities I selected private and public networks