As we know, Android 13 is introducing runtime notification permission. Here's the Android developer documentation on this.
We already have a priming page where we show the notification permission prompt in iOS. We just need to do this for all users on Android 13.
After reading the documentation, i've added the following:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
However I can't seem to find a way to prompt Android users. Has anyone had any success with this/can point me in the right direction?
Also, we've noticed all of our users who have upgraded to Android 13 have notifications turned off by default. Is there a way we can add a link to the notifications permission in the settings?
I am currently using this to achieve that, in your MainActivity put this
protected override void OnStart()
{
base.OnStart();
const int requestLocationId = 0;
string[] notiPermission =
{
Manifest.Permission.PostNotifications
};
if ((int)Build.VERSION.SdkInt < 33) return;
if (this.CheckSelfPermission(Manifest.Permission.PostNotifications) != Permission.Granted)
{
this.RequestPermissions(notiPermission, requestLocationId);
}
}
From document Notification runtime permission, we know that:
To request the new notification permission from your app, update your
app to target Android 13 and complete a similar process compared to
requesting other runtime permissions.
And from document POST_NOTIFICATIONS, we also find that :
POST_NOTIFICATIONS Added in API level 33
public static final String POST_NOTIFICATIONS Allows an app to post
notifications
Protection level: dangerous
Constant Value: "android.permission.POST_NOTIFICATIONS"
That is the Protection level of POST_NOTIFICATIONS is dangerous, so we need to
add Requesting Runtime Permissions.
For more information, you can check : Requesting Runtime Permissions in Android Marshmallow.
You can also check Permissions In Xamarin.Android here.
And there is a sample here:https://github.com/xamarin/monodroid-samples/tree/main/android-m/RuntimePermissions.
I try to connect to BLE peripheral. First, I watch for advertisements:
watcher = new BluetoothLEAdvertisementWatcher { ScanningMode = BluetoothLEScanningMode.Active };
watcher.Received += WatcherOnReceived;
watcher.Start();
and in the WatcherOnReceived callback I try to create BluetoothLEDevice
public async void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs btAdv)
{
BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(btAdv.BluetoothAddress);
}
However, I always get bleDevice == null in WatcherOnReceived callback. Why and how to fix it? What is the proper way of creating BLE device in UWP application? I then need to connect to that device, discover its GATT services and characteristics, enable notifications on some of them and read/write some of them.
The answer to this question is simple - do not use BLE on Windows 10. The API doesn't work or behaves randomly and is totally undocumented. I like everyone talking about IoT being next industrial revolution and Microsoft not having working BLE API after 6 year BLE exists.
See example 8 and 9 in https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/DeviceEnumerationAndPairing if you want to be able to connect to previously non-paired BLE devices, i.e. use a DeviceWatcher with a Bluetooth LE selector.
Otherwise you need to first pair it in the system's bluetooth pairing settings before you will be able to retrieve a BluetoothLEDevice from FromBluetoothAddressAsync.
You can check device information in WatcherOnReceived() to ensure that the device is what you want to connect with. Do it like this:
public async void WatcherOnReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs btAdv)
{
if (btAdv.Advertisement.LocalName == "SensorTag")
{
BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(btAdv.BluetoothAddress);
}
}
Use your own BLE device name instead of "SensorTag".
Note: You need pair your BLE device beforehand(either programatically like DeviceEnumerationAndPairing sample or PC's setting app as shown in the following image.).
How to terminate a Xamarin application from any of the activities?
I have tried both System.Environment.Exit(0) and System.Environment.Exit(1) as well as Finish() and killing all the activities.
It still opens one blank page with default activity name and a black screen.
Is there any specific solution for this?
If you are using Xamarin.Forms create a Dependency Service.
Interface
public interface ICloseApplication
{
void closeApplication();
}
Android : Using FinishAffinity() won't restart your activity. It will simply close the application.
public class CloseApplication : ICloseApplication
{
public void closeApplication()
{
var activity = (Activity)Forms.Context;
activity.FinishAffinity();
}
}
IOS : As already suggested above.
public class CloseApplication : ICloseApplication
{
public void closeApplication()
{
Thread.CurrentThread.Abort();
}
}
UWP
public class CloseApplication : ICloseApplication
{
public void closeApplication()
{
Application.Current.Exit();
}
}
Usage in Xamarin Forms
var closer = DependencyService.Get<ICloseApplication>();
closer?.closeApplication();
A simple way to make it work cross platform is by this command:
System.Diagnostics.Process.GetCurrentProcess().CloseMainWindow();
Got it from this link.
EDIT: After using it for a while, I discovered that .CloseMainWindow() don't kill the application, only Closes it (well, thats obvious). If you want to terminate the app (kill), you shoud use the following:
System.Diagnostics.Process.GetCurrentProcess().Kill();
For Android, you can do
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
iOS explicitly does not provide any API for existing an App. Only the OS can close an App.
For iOS, you can use this code:
Thread.CurrentThread.Abort();
For Android, as #Jason mentioned here:
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
System.Environment.Exit(0);
Works for me.
In your activity, use this code
this.FinishAffinity();
I tried this code
protected override bool OnBackButtonPressed()
{
Device.BeginInvokeOnMainThread(async () =>
{
var result = await DisplayAlert("", "Would you like to exit from application?", "Yes", "No");
if (result)
{
if (Device.OS == TargetPlatform.Android)
{
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
}
else if (Device.OS == TargetPlatform.iOS)
{
Thread.CurrentThread.Abort();
}
}
});
return true;
}
In this, iOS and Android application close when a user chooses to terminate the application. Maybe it helps you.
A simple all-in-one combination of the previous answers, instead of the interface/dependency:
protected override bool OnBackButtonPressed()
{
Device.BeginInvokeOnMainThread(async () =>
{
var result = await this.DisplayAlert("Alert!", "want to exit?", "Yes", "No");
if (result)
{
#if __ANDROID__
var activity = (Android.App.Activity)Forms.Context;
activity.FinishAffinity();
#endif
#if __IOS__
Thread.CurrentThread.Abort();
#endif
}
});
return true;
}
System.Diagnostics.Process.GetCurrentProcess().CloseMainWindow();
System.Diagnostics.Process.GetCurrentProcess().Kill();
None of the methods above helped my Xamarin Android app to completely shut down. I tried to close it from Activity B, having Activity A also open under it.
A clever guy left a trick here.
First call FinishAffinity() in Activity B (closes both activities,
however, the app is still alive in the background)
Then call JavaSystem.Exit(0) to kill the background app (I think it can be replaced with Android.OS.Process.KillProcess(Android.OS.Process.MyPid()); or System.Diagnostics.Process.GetCurrentProcess().Kill();)
My method to close the app:
private void CloseBtn_Click(object sender, EventArgs e){
FinishAffinity();
JavaSystem.Exit(0);
}
As your original question mentions activities, your question is specifically for Android, you should probably update the question title with that in mind to avoid people looking for a cross-platform solution coming here.
For iOS and Android (say in Xamarin Forms) you can just throw an exception, which while being the "heavy handed" approach, will do the job:
throw new Exception();
As this isn't the best user experience and you may only want to use this for iOS because on Android, you are likely to get a system popup telling you the app crashed. However, unlike other iOS methods like calling exit(0) or calling private iOS methods like "terminateWithSuccess" via a selector, it shouldn't fail app store validation purely based on how you do it. They may still fail you because your app tries to terminate itself.
You may want to implement something different specifically for Android, in which case Jason's answer is sufficient, again if not a little on the nose i.e. using this approach may not allow your app to clean itself up:
Android.OS.Process.KillProcess(Android.OS.Process.MyPid());
Either way, you should really question why you need to provide this option. Unlike desktop applications where closing an application is needed because apps reside inside windows which by design allow multi-tasking and are not task orientated, mobile platforms are primarily designed for users to focus on one task at a time. Once the user is finished the task, they should decide to exit this task by clicking the home button, back button or change app (task) button. This really applies to all platforms.
None of these work with Android 8. They all left the app in the background.
I can prove this by pressing the close all button and the app is still there.
For my testing I used a brand new simple Android app and tried all of your answers.
Application.Quit();
I'm assuming you are using C#
Call
public void Quit ();
This will quit the application the correct way without it "crashing".
I am follow the window phone authentication tutorial with Add authentication to your Mobile Services app. And I choose using Azure Active Directory way to make authentication. But the question is: it always fails and shows The remote procedure call failed. (Exception from HRESULT: 0x800706BE) at the following code
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
await Authenticate();//here throws System.Exception in mscorlib.ni.dll
await RefreshMissionTable();
}
And I make sure there is nothing wrong in my Azure setting. The weird thing is that when I choose windows phone universal app sample, and do the same procedure again, it can work in the windows 8.1 emulator! But still can't work in the windows phone 8.1 emulator .
And the break point stays here
#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
#endif
}
}
}
this might be related to a known problem with the WebAuthenticationBroker on Windows Phone 8.1: it cannot be invoked until the full UX of the app has been loaded. Please take a look to this thread for a description of the issue and proposed workarounds: https://social.msdn.microsoft.com/Forums/vstudio/en-US/95c6569e-2fa2-43c8-af71-939e006a9b27/mobile-services-loginasync-remote-procedure-call-failed-hresult-0x800706be?forum=azuremobile
HTH
V.
I need to open a new application from my application. If it is not installed on the phone then I need to open the installation inside windows store.
Anybody have an idea how can I achieve this?
I read the below articles but I couldn't find anything helpful:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207014%28v=vs.105%29.aspx
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206987%28v=vs.105%29.aspx
Answer:
For the store i ended up using:
private async void test()
{
try
{
Uri uri = new Uri("zune://navigate/?appid=xxx-xxx-xxx-xxx");
await Launcher.LaunchUriAsync(uri);
}
catch (Exception exception)
{
//TODO
}
}
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662937(v=vs.105).aspx
describes how you can launch the store app and display a specific app
What you need will look something like this:
Windows.System.Launcher.LaunchUriAsync(new Uri("zune:navigate?appid=[app ID]"));
where '[app ID]' needs to be replaced by the unique app id of the application you want to install.