Xamarin Forms, Android 11+, Access music folder in root - xamarin.forms

Hi i searched and searched.
How do i access the music folder in android? Not the music folder of the app.
Android.OS is not available.
I even tried System.IO.Directory.GetFiles("/"); no permissions.
I checked every permission in the manifest that states storage or read.
I need the filepath to each audio file to be able to play it. I don't need a file dialog where the user chooses a file.
I need a string[] of all audio files in the root music dir not the app dir.
There has to be a way, cause audio players exist that access my root music folder.
NOT sdCard Storage

May be you can try to grant your app the permission about accessing all the files.
At first, add the permission into the AndroidManifest.xml:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
And then add the following code into the OnCreate method of the main activity to request the permission.
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
if (!Android.OS.Environment.IsExternalStorageManager)
{
Intent intent = new Intent();
intent.SetAction(Android.Provider.Settings.ActionManageAppAllFilesAccessPermission);
Android.Net.Uri uri = Android.Net.Uri.FromParts("package", this.PackageName, null);
intent.SetData(uri);
StartActivity(intent);
}
}

Related

Background Service in Xamarin.Forms, iOS, Android

I have a background service in android.
My code is as follows:
[Service]
public class PeriodicService : Service
{
public override IBinder OnBind(Intent intent)
{
return null;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Device.StartTimer(TimeSpan.FromSeconds(5), () =>
{
// code
});
return StartCommandResult.Sticky;
}
}
The MainActivity class:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
StartService(new Intent(this, typeof(PeriodicService)));
}
Permission AndroidManifest.xml:
<uses-permission android:name="android.permission.PeriodicService" />
The problem is that my service only works in the background when the app is active or in the foreground but when I close the app it doesn't run in the background.
A possible solution is to follow along with what Fabio has written in his post about how to create The Never Ending Background Task.
The idea behind this is to create a BroadcastReceiver and Android Service in the manifest. The BroadcastReceiver will then activate the service with foreground priority as the application is being closed. If you are dealing with post Android 7 then he created an update to his blog showing The Fix.
Just to get a better understanding of how basic Android services operate, I'd recommend taking a look at this Android Services Tutorial
I also saw this other StackOverflow post that seems to be pretty similar so maybe there will be some useful info over there too.
I'm not too acclimated in this stuff, but I was able to follow along with the blog posts pretty easily so I hope this ends up helping :). If anyone finds a better solution I'd love to hear about it so tag be (if you would be so kind) so I can stay updated!

Delete file from firebase storage using sketchware

I managed to get files to upload to my firebase storage bucked but how can I delete the file within sketchwere.
I enter the URL of the storage bucket where the file is located but my application keeps crashing with error "The storage URI cannot be parsed."
Any ideas?
I think I am entering the wrong URL.
According to the documentation, here's an example on how to delete file in your firebase storage using the Android SDK : Delete.
// Create a storage reference from our app
StorageReference storageRef = storage.getReference();
// Create a reference to the file to delete
StorageReference desertRef = storageRef.child("images/desert.jpg");
// Delete the file
desertRef.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// File deleted successfully
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Uh-oh, an error occurred!
}
});
If you are displaying the image from a listmap, use "get value at position of listmap" block to get the URL of the image. You must add a firebase storage component to that activity matching the path of the image.
I'd you are using a firebase reference code to display image, use the reference code to get the value of the image url to a string variable.
You must also make sure you have a firebase auth component added to that activity, and make sure your rules allow writing to that path in storage and database.
Also, make sure you are using the firebase storage "delete file from url" block.

Cannot accomplish to add a xamarin.froms.android app to firebase

I don't know what to do anymore, I am trying to connect my Xamarin.Forms App to Firebase.
I cannot find any suitable tutorials. I have downloaded the Google-Service.json and added it to my Android root Directory, I also set the build Option for the file on GoogleServicesJson. I made sure the file has the Name from my packagename & I also added the Android App on firebase and installed the Nugget Package xamarin.firebase.Auth.
When I start the App, Firebase tells me that the app doesn't communicate with the firebase Server. Any suggestions where the Problem could be?
That's the changes in Code:
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
FirebaseApp.InitializeApp(Application.Context);
LoadApplication(new App());
}
FirebaseApp.InitializeApp(Application.Context); was added by me.

Geolocation GetLastKnownLocationAsync() permission exception from Xamarin Forms - call fails and no permission prompt

GetLocationAsync fails on my Xamarin.Forms app.
I've got the latest Xamarin.Essentials nuget package.
I've set the necessary permissions in the info.plist.
I am calling this from my ViewModel.
The call is super simple:
var location = await Geolocation.GetLastKnownLocationAsync();
but it's both failing AND failing to prompt a user permission dialog even though my info.plist has been setup correctly with:
NSLocationWhenInUseUsageDescription
Insert reason
I'm asking and answering this question because it was a head scratcher, and I wasn't exactly sure what to be searching for or what the issue was.
My various searches pointed to many related issues but nothing that actually gets to the main problem.
The closest I got was actually this issue on the Essentials github page:
https://github.com/xamarin/Essentials/issues/634
This answer is inspired by Xamarin/Azure evangelist, Brandon Minnick --> take a look at his project where he handles a similar situation with the following code:
So what can we take away from the above? If you look at the context, he has connected his Views with his ViewModels in MVVM style. However, various libraries require that certain methods be called from the Main thread. This is the essence of the issue, and this is what this code can solve.
So to adopt the above code for the geolocation issue addressed in the question, I did the following:
Task<Xamarin.Essentials.Location> GetLocationFromPhone()
{
var locationTaskCompletionSource = new TaskCompletionSource<Xamarin.Essentials.Location>();
Device.BeginInvokeOnMainThread(async () =>
{
locationTaskCompletionSource.SetResult(await Geolocation.GetLastKnownLocationAsync());
});
return locationTaskCompletionSource.Task;
}
I'm using the above from my ViewModel from within a Task. Something like the following.
async Task ExecuteGetGeoLocationCommand()
{
try
{
var locationFromPhone = await GetLocationFromPhone().ConfigureAwait(false);
if (locationFromPhone is null)
return;
_location = locationFromPhone;
if (_location != null)
{
Console.WriteLine($"Latitude: {_location.Latitude}, Longitude {_location.Longitude}, Altitude: {_location.Altitude}");
}
else
{
Console.WriteLine($"Exiting geolocation");
}
catch (FeatureNotSupportedException fnsEx)
{
}
catch (Exception ex)
{
}
}
}
I hope it's helpful to someone else!
If you're using Xamarin.Essentials and aren't being prompted for permission on Android, make sure you've added all the necessary code to the Android Main Activity.
See https://learn.microsoft.com/en-us/xamarin/essentials/get-started?tabs=windows%2Candroid for details.
From the docs:
protected override void OnCreate(Bundle savedInstanceState) {
//...
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code, it may also be called: bundle
//...
and
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

Xamarin Forms - SMS BroadcastReceiver in Android failing to work

This seems to be a simple task, but I`m failing to do it. Saw a bunch of tutorials and stuff. Maybe someone can help me.
I'm starting from a Xamarin Forms App, that will have a task specific for Android (Targeting Android 8.0 - Oreo).
So to test I've made as follow (XF 3.2.0.839982). Told this mainly because it don't have a OnResume, OnPause, On....methods...(or I don't know about them).
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, Application.IActivityLifecycleCallbacks
{
SMSBroadcastReceiver myreceiver;
IntentFilter intentFilter;
protected override async void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var buttonbtnsendmessage = (Button)FindViewById(Resource.Id.sendBroadcast);
myreceiver = new SMSBroadcastReceiver();
intentFilter = new IntentFilter(SMSBroadcastReceiver.IntentAction);
intentFilter.Priority = 1000;
RegisterReceiver(myreceiver, intentFilter);
}
}
public class SMSBroadcastReceiver : BroadcastReceiver
{
public static string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent i)
{
if (i.Action != IntentAction)
{
return;
}
Toast.MakeText(context, "Received broadcast in MyBroadcastReceiver, " +
" value received: " + i.GetStringExtra("key"),
ToastLength.Long).Show();
}
}
and Manifest
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="26" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.BROADCAST_SMS" />
But it do not fall in my receiver when I get a SMS.
Just to check if it would work at all, I changed the IntentAction to "MY_TEST", and sent the broadcast from another app, and it was able to Toast.
Any Ideas?
Xamarin Forms - SMS BroadcastReceiver in Android failing to work
You are missing a lot is in your code.
Requesting Runtime Permissions in Android Marshmallow +
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. You should request permissions at runtime.
System permissions are divided into two categories, normal and dangerous:
Normal permissions do not directly risk the user's privacy. If your app lists a normal permission in its manifest, the system grants the permission automatically.
Dangerous permissions can give the app access to the user's confidential data. If you list a dangerous permission, the user has to explicitly give approval to your app during the runtime of the app.
READ_SMS is categorized as Dangerous permissions, so you should check this permissions manually for API level 23 and above.
Adorn BroadcastReceiver with the BroadcastReceiverAttribute
For more detail information, please refer to the official document: Broadcast Receivers in Xamarin.Android
Here is an example:
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" })]
class SMSBroadcastReceiver: BroadcastReceiver
{
public static string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent i)
{
if (i.Action != IntentAction)
{
return;
}
Toast.MakeText(context, "Received broadcast in MyBroadcastReceiver, " +
" value received: " + i.GetStringExtra("key"),
ToastLength.Long).Show();
}
}

Resources