I'm attempting to configure AppCenter.Distribute for in-app updates within my Xamarin Android app. Here is the very basic setup code, which I have in my main launcher activity's OnCreate method (AFTER the base.OnCreate call):
AppCenter.Start (Resources.GetString (Resource.String.appcenter_app_secret), typeof (Analytics), typeof (Crashes), typeof (Distribute));
I was able to get the in-app updates to supposedly initialize. When I first install and open the app, it shows a browser window for one second that says "In-app updates enabled! Returning to app in 1...", then it redirects back to my app. Unfortunately, when I then bump the version name and code and distribute a new build, I don't get a dialog within the app prompting me to update to the new version.
I even tried handling the Distribute.ReleaseAvailable action and showing a custom dialog, and that action isn't invoked either:
Distribute.ReleaseAvailable = OnReleaseAvailable;// Called before AppCenter.Start
private bool OnReleaseAvailable(ReleaseDetails releaseDetails)
{
// Show custom dialog.
Droid.ApplicationContext.Activity.CustomDialogBuilder().Show(new NotificationArgs
{
Title = "New update available!",
Message = "A new version of RPR Mobile, {0} ({1}) is available. Release notes: {2}"
.WithFormat(releaseDetails.ShortVersion, releaseDetails.Version, releaseDetails.ReleaseNotes),
PositiveButtonText = "Update",
PositiveAction = () =>
{
// Notify SDK that user selected to update...
Distribute.NotifyUpdateAction(UpdateAction.Update);
},
HideNegativeButton = releaseDetails.MandatoryUpdate,
NegativeButtonText = "Postpone Update",
NegativeAction = () =>
{
// Notify SDK that user selected to postpone (for 1 day)...
// Note that this method call is ignored by the SDK if the update is mandatory.
Distribute.NotifyUpdateAction(UpdateAction.Postpone);
}
});
// Return true if you are using your own dialog, false otherwise.
return true;
}
I'm wondering what I'm missing. Some questions that may or may not be relevant...
Does it matter whether the AppCenter.Start code executes before or after the base.OnCreate call?
Does it matter whether the activity that AppCenter.Start is called from is running or finished? Because in our case, the main launcher is just a splash screen that closes after a couple seconds.
Is the App Center SDK supposed to poll every few seconds for an update? Or does it check only when opening and closing activities?
It turns out that you have to close and relaunch your app for it to check for new updates. The documentation could be more clear on this...
Im creating an Electron app. I save the user progress in a file. I want the app to show the usual 'Save changes before closing' when the user has not saved and tries to close the App.
I could show a custom dialog, however, I would want to do it the native way.
(Example: On macOS, when you edit a file, the red button changes, letting know the user that the app has unsaved content)
I know this has to be done probably inside the Electron's listener for a closing app:
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
... preventing quit() from being called. And instead handling the unsaved file state and dialog.
PD: I already handle the logic to know whether the user has saved its progress or not. I just want to know how to set the 'Unsaved' state to my electron app and correctly handle it.
(The example is Visual Studio Code, which is also an Electron App)
I usually use a global variable to indicate changes had occured and for example in the case of closing the app:
Code in the main:
mainWindow.on('close', function (event) {
if (global.savetoask== 'Yes') {
event.preventDefault();
//send a ipc message to request a confirm dialog
.............
} else {
app.exit();
}
});
Im using xamarin forms 2.3.4.247 shared project. In my login page im navigating my page to another. while this page is rendering im showing a Activity Indicator in Main Page. But unfortunately Activity Indicator Stucks And After A couple of seconds the second page loads.ive tried these codes below and i got nothing.All of these codes are running into an async command.im testing my app in actual device on android platform.
1
activityIndicator.IsRunnig=true;
new System.Threading.Thread(new System.Threading.ThreadStart(() =>
{
Navigation.PushAsync(new DeviceLoginView());
})).Start();
2
activityIndicator.IsRunnig=true;
Device.BeginInvokeOnMainThread(async () =>
{
await Navigation.PushAsync(new DeviceLoginView());
});
3
activityIndicator.IsRunnig=true;
await Navigation.PushAsync(new DeviceLoginView());
That issue is because your activity indicator is in the UI of the old page not on the new page, so when you do the Push the old page is not longer displaying.
For have the result you want, you can use this plugin for keep having the loading during the transition
https://github.com/aritchie/userdialogs
i Finally was able to make this issue right.
you can do all your asynchronous jobs in a Task.Run() method to run all of them in a new thread and NOT in the UI thread
Do you know what could be causing the permissions request dialog on iOS to show behind the app? It actually flashes quickly and then goes behind. I have to press the home button to bring it to the front. Until then the UI is blocked.
I am using Everlive and I am calling the register method in the app's launchEvent as such:
var pushSettings = {
//iOS - specific settings
iOS: {
badge: true,
sound: true,
alert: true,
clearBadge: true
},
notificationCallbackIOS: function (userInfo) {
...
},
//Android - specific settings
android: {
projectNumber: '944301213976'
},
notificationCallbackAndroid: function callback(data) {
...
}
}
el.push.register(pushSettings, function (data) {
...
}, function (error) {
});
Thank you.
EDIT: I should add that I am testing on iOS 9.3.4 and right before the dialog goes behind the app, I get the following warning in the console: enabledRemoteNotificationTypes is not supported in iOS 8.0 and later. Not sure if it matters, but I wanted to mention it, just in case.
So, it turns out that it was a timing issue. I was running the code when the app was initializing. The popup will get displayed, but shortly after, the first screen (login in my case) gets initialized, stealing the focus from the popup.
Once I moved the code in a button tap event (after the screen loading was completed) everything worked as expected.
I am not sure if this is the best way to handle this. I am open for suggestions.
Also, you can see https://github.com/NativeScript/push-plugin/issues/38 for more info. Thank you Anton Dobrev for pointing me to the right direction.
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".