using System; using AVFoundation; using com.hdl.on; using CoreLocation; using Foundation; using UIKit; namespace Shared { public class BaseApplicationDelegate : UIApplicationDelegate { public static Action<UIApplication, NSDictionary> FinishedLaunchingAction; public static Action<UIApplication> OnResignActivationAction; public static Action<UIApplication> DidEnterBackgroundAction; public static Action<UIApplication> WillEnterForegroundAction; public static Action<UIApplication> OnActivatedAction; public static Action<UIApplication> WillTerminateAction; public static Action<string> DeviceTokenAction; public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) { registerForRemoteNotification(application); //var musicInfo = new MusicInfo { }; //Volume.Init(); FinishedLaunchingAction?.Invoke(application, launchOptions); //GPS if (Shared.Application.IsGpsEnable) { if (MyCLLocationManager.Instance.IsLocationServicesEnabled) { switch (Shared.Application.CurrentGpsUseMode) { case Application.GpsUseMode.Always: MyCLLocationManager.Instance.RequestAlwaysAuthorization(); break; case Application.GpsUseMode.WhenInUse: MyCLLocationManager.Instance.RequestWhenInUseAuthorization(); break; } if (launchOptions != null && launchOptions.ObjectForKey(UIApplication.LaunchOptionsLocationKey) != null) { MyCLLocationManager.Instance.StartMonitoringSignificantLocationChanges(); } else { MyCLLocationManager.Instance.StartUpdatingLocation(); } } else { ///TODO å¯ä»¥æç¤ºç”¨æˆ·æ‰“å¼€å®šä½æƒé™ } } return true; } /// <summary> /// æ³¨å†Œè¿œç¨‹æ¶ˆæ¯æŽ¨é€ /// </summary> /// <param name="application">Application.</param> void registerForRemoteNotification(UIApplication application) { if (8 <= int.Parse(UIDevice.CurrentDevice.SystemVersion.Split('.')[0])) { // 1.注册UserNotification,ä»¥èŽ·å–æŽ¨é€é€šçŸ¥çš„æƒé™ var settings = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Sound | UIUserNotificationType.Alert | UIUserNotificationType.Badge, null); application.RegisterUserNotificationSettings(settings); // 2.æ³¨å†Œè¿œç¨‹æŽ¨é€ application.RegisterForRemoteNotifications(); } else { application.RegisterForRemoteNotificationTypes(UIRemoteNotificationType.NewsstandContentAvailability | UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound); } } class MyCLLocationManager : CLLocationManager { #region å®šä½ public static MyCLLocationManager Instance { get { if (locationManager == null) { locationManager = new MyCLLocationManager(); //设置是å¦å…许系统自动暂åœå®šä½ locationManager.PausesLocationUpdatesAutomatically = false; locationManager.AllowsBackgroundLocationUpdates = false; //设置定ä½ç²¾åº¦ locationManager.DesiredAccuracy = CLLocation.AccuracyKilometer; locationManager.init(); } return locationManager; } } //判æ–å®šä½æ“作是å¦è¢«å…许 static MyCLLocationManager locationManager; //最å°çš„移动速度 m/s float minSpeed = 3; //最å°çš„移动è·ç¦» m float minInteval = 100; /// <summary> /// 用户是å¦å…许定ä½åŠŸèƒ½ /// </summary> public bool IsLocationServicesEnabled => LocationServicesEnabled; void init() { if (LocationServicesEnabled) { //è®¾ç½®å®šä½æ›´æ–°çš„æœ€å°è·ç¦» locationManager.DistanceFilter = minInteval; locationManager.LocationsUpdated += (sender, e) => { var location = e.Locations[e.Locations.Length - 1]; adjustDistanceFilter(location); Shared.Application.LocationAction?.Invoke(location.Coordinate.Longitude, location.Coordinate.Latitude); //System.Console.WriteLine($"ä½ç½®ä¿¡æ¯å˜åŒ– ç»åº¦{location.Coordinate.Longitude} 纬度{location.Coordinate.Latitude}"); //uploadToServer(location); }; } } //* 规则: 如果速度å°äºŽminSpeed m/s 则把触å‘范围设定为100m //* å¦åˆ™å°†è§¦å‘范围设定为minSpeed*minInteval //* æ¤æ—¶è‹¥é€Ÿåº¦å˜åŒ–超过10% 则更新当å‰çš„触å‘范围(这里é™åˆ¶æ˜¯å› 为ä¸èƒ½ä¸åœçš„设置distanceFilter, //* å¦åˆ™uploadLocation会ä¸åœè¢«è§¦å‘) void adjustDistanceFilter(CLLocation location) { //NSLog(@"adjust:%f",location.speed); if (location.Speed < minSpeed) { if (Math.Abs(DistanceFilter - minInteval) > 0.1f) { DistanceFilter = minInteval; } } else { var lastSpeed = DistanceFilter / minInteval; if ((Math.Abs(lastSpeed - location.Speed) / lastSpeed > 0.1f) || (lastSpeed < 0)) { float newSpeed = (int)(location.Speed + 0.5f); float newFilter = newSpeed * minInteval; DistanceFilter = newFilter; } } } nint taskIdentifier = UIApplication.BackgroundTaskInvalid; void beingBackgroundUpdateTask() { taskIdentifier = UIApplication.SharedApplication.BeginBackgroundTask(() => { endBackgroundUpdateTask(); }); } void endBackgroundUpdateTask() { if (taskIdentifier != UIApplication.BackgroundTaskInvalid) { UIApplication.SharedApplication.EndBackgroundTask(taskIdentifier); taskIdentifier = UIApplication.BackgroundTaskInvalid; } } // void uploadToServer(CLLocation location) // { //#warning 如果有较长时间的æ“作 比如HTTPä¸Šä¼ è¯·ä½¿ç”¨beginBackgroundTaskWithExpirationHandler // if (UIApplication.SharedApplication.ApplicationState == UIApplicationState.Active) // { // //HTTP upload // Shared.Application.LocationAction?.Invoke(location.Coordinate.Longitude, location.Coordinate.Latitude); // endBackgroundUpdateTask(); // } // else//åŽå°å®šä½ // { // //å‡å¦‚ä¸Šä¸€æ¬¡çš„ä¸Šä¼ æ“ä½œå°šæœªç»“æŸ åˆ™ç›´æŽ¥return // if (taskIdentifier != UIApplication.BackgroundTaskInvalid) // { // return; // } // beingBackgroundUpdateTask(); // //HTTP upload // Shared.Application.LocationAction?.Invoke(location.Coordinate.Longitude, location.Coordinate.Latitude); // //ä¸Šä¼ å®Œæˆè®°å¾—调用 // endBackgroundUpdateTask(); // } // } #endregion } public override void OnResignActivation(UIApplication application) => OnResignActivationAction?.Invoke(application);// Invoked when the application is about to move from active to inactive state.// This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) // or when the user quits the application and it begins the transition to the background state.// Games should use this method to pause the game. public override void DidEnterBackground(UIApplication application) => DidEnterBackgroundAction?.Invoke(application);// Use this method to release shared resources, save user data, invalidate timers and store the application state.// If your application supports background exection this method is called instead of WillTerminate when the user quits. public override void WillEnterForeground(UIApplication application) => WillEnterForegroundAction?.Invoke(application);// Called as part of the transiton from background to active state.// Here you can undo many of the changes made on entering the background. public override void OnActivated(UIApplication application) { AVAudioSession.SharedInstance().SetActive(true); OnActivatedAction?.Invoke(application); // Restart any tasks that were paused (or not yet started) while the application was inactive. // If the application was previously in the background, optionally refresh the user interface. } public override void WillTerminate(UIApplication application) => WillTerminateAction?.Invoke(application);// Called when the application is about to terminate. Save data, if needed. See also DidEnterBackground. /// <summary> /// æ³¨å†Œè¿œç¨‹æ¶ˆæ¯æŽ¨é€å›žè°ƒæ–¹æ³• /// </summary> /// <param name="application">Application.</param> /// <param name="deviceToken">Device token.</param> public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) { var bytes = new byte[deviceToken.Length]; System.Runtime.InteropServices.Marshal.Copy(deviceToken.Bytes, bytes, 0, bytes.Length); var stringBuilder = new System.Text.StringBuilder(); for (int i = 0; i < bytes.Length; i++) { stringBuilder.AppendFormat("{0:x2}", bytes[i]); } var newDeviceToken = stringBuilder.ToString(); var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey("PushDeviceToken"); if (oldDeviceToken != newDeviceToken) { // Save new device token NSUserDefaults.StandardUserDefaults.SetString(newDeviceToken, "PushDeviceToken"); } DeviceTokenAction?.Invoke(newDeviceToken); } public virtual void setHDLRootViewController() { } } }