using System; using Acr.UserDialogs; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Bit.Android.Services; using Bit.App.Abstractions; using Bit.App.Repositories; using Bit.App.Services; using Plugin.Connectivity; using Plugin.CurrentActivity; using Plugin.Fingerprint; using Plugin.Settings; using PushNotification.Plugin; using PushNotification.Plugin.Abstractions; using XLabs.Ioc; using System.Threading.Tasks; using Plugin.Settings.Abstractions; using FFImageLoading.Forms.Droid; using XLabs.Ioc.SimpleInjectorContainer; using SimpleInjector; namespace Bit.Android { #if DEBUG [Application(Debuggable = true)] #else [Application(Debuggable = false)] #endif public class MainApplication : Application, Application.IActivityLifecycleCallbacks { private const string FirstLaunchKey = "firstLaunch"; private const string LastVersionCodeKey = "lastVersionCode"; public static Context AppContext; public MainApplication(IntPtr handle, JniHandleOwnership transer) : base(handle, transer) { // AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser; if(!Resolver.IsSet) { SetIoc(this); } } private void AndroidEnvironment_UnhandledExceptionRaiser(object sender, RaiseThrowableEventArgs e) { var message = AppendExceptionToMessage("", e.Exception); Utilities.SendCrashEmail(message, false); } private string AppendExceptionToMessage(string message, Exception ex) { message += ("\n\n" + ex.Message + "\n\n" + ex.StackTrace); if(ex.InnerException != null) { return AppendExceptionToMessage(message, ex.InnerException); } return message; } public override void OnCreate() { base.OnCreate(); // workaround for app compat bug // ref https://forums.xamarin.com/discussion/62414/app-resuming-results-in-crash-with-formsappcompatactivity Task.Delay(10).Wait(); RegisterActivityLifecycleCallbacks(this); AppContext = ApplicationContext; StartPushService(); HandlePushReregistration(); } private void HandlePushReregistration() { var pushNotification = Resolver.Resolve(); var settings = Resolver.Resolve(); // Reregister for push token based on certain conditions // ref https://github.com/rdelrosario/xamarin-plugins/issues/65 var reregister = false; // 1. First time starting the app after a new install if(settings.GetValueOrDefault(FirstLaunchKey, true)) { settings.AddOrUpdateValue(FirstLaunchKey, false); reregister = true; } // 2. App version changed (installed update) var versionCode = Context.ApplicationContext.PackageManager.GetPackageInfo(Context.PackageName, 0).VersionCode; if(settings.GetValueOrDefault(LastVersionCodeKey, -1) != versionCode) { settings.AddOrUpdateValue(LastVersionCodeKey, versionCode); reregister = true; } // 3. In debug mode if(InDebugMode()) { reregister = true; } // 4. Doesn't have a push token currently if(string.IsNullOrWhiteSpace(pushNotification.Token)) { reregister = true; } if(reregister) { pushNotification.Unregister(); if(Resolver.Resolve().IsAuthenticated) { pushNotification.Register(); } } } private bool InDebugMode() { #if DEBUG return true; #else return false; #endif } public override void OnTerminate() { base.OnTerminate(); UnregisterActivityLifecycleCallbacks(this); } public void OnActivityCreated(Activity activity, Bundle savedInstanceState) { CrossCurrentActivity.Current.Activity = activity; } public void OnActivityDestroyed(Activity activity) { } public void OnActivityPaused(Activity activity) { } public void OnActivityResumed(Activity activity) { CrossCurrentActivity.Current.Activity = activity; } public void OnActivitySaveInstanceState(Activity activity, Bundle outState) { } public void OnActivityStarted(Activity activity) { CrossCurrentActivity.Current.Activity = activity; } public void OnActivityStopped(Activity activity) { } public static void StartPushService() { AppContext.StartService(new Intent(AppContext, typeof(PushNotificationService))); if(Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat) { PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext, typeof(PushNotificationService)), 0); AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(AlarmService); alarm.Cancel(pintent); } } public static void StopPushService() { AppContext.StopService(new Intent(AppContext, typeof(PushNotificationService))); if(Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat) { PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext, typeof(PushNotificationService)), 0); AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(AlarmService); alarm.Cancel(pintent); } } public static void SetIoc(Application application) { UserDialogs.Init(application); CachedImageRenderer.Init(); CrossFingerprint.SetCurrentActivityResolver(() => CrossCurrentActivity.Current.Activity); //var container = new UnityContainer(); var container = new Container(); // Android Stuff container.RegisterSingleton(application.ApplicationContext); container.RegisterSingleton(application); // Secure Storage ISecureStorageService secureStorage; try { secureStorage = new KeyStoreBackedStorageService(CrossSettings.Current); } catch { // Some isolated devices are having a hard time generating RSA keys for the key store. // Continue using the "old" keystore implementation for now. secureStorage = new KeyStoreStorageService(new char[] { }); } // Services container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(secureStorage); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); // Repositories container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); container.RegisterSingleton(); // Other container.RegisterSingleton(CrossSettings.Current); container.RegisterSingleton(CrossConnectivity.Current); container.RegisterSingleton(UserDialogs.Instance); container.RegisterSingleton(CrossFingerprint.Current); // Push var pushListener = new PushNotificationListener(); container.RegisterSingleton(pushListener); CrossPushNotification.Initialize(pushListener, "962181367620"); container.RegisterSingleton(CrossPushNotification.Current); container.Verify(); Resolver.SetResolver(new SimpleInjectorResolver(container)); } } }