Xamarin.Androidで、定期的にGPS情報アップロードを行うアプリを開発しています。
通常はMainActivityのTimer処理でアップロードを行っていますが、
ホームボタン押下等でアプリ終了され、OnStop()に入った場合はServiceを立ち上げて上記処理を行い、
アプリ起動でOnCreate()に入った場合に、Serviceを完全にキルしたいと考えています。
C#
1var context = this.ApplicationContext; 2context.StopService(new Intent(context, typeof(BackgroundService)));
上記のコードをOnCreate()やTimer処理内で実行すると、
開発者向けオプション内の「実行中のアプリ」リストからはクリアされているのですが、
「実行中のアプリ→キャッシュしたプロセスを表示」リストには残存しており、おそらくそれが原因で、Serviceがリスタートしているようです。
いわゆるゾンビ状態となり、Serviceを終了できず困っています。
「キャッシュしたプロセスを表示」リストから、バックグラウンドプロセスを終了させる方法はございますでしょうか。
よろしくお願いいたします。
~開発環境等~
Visual Studio 2017
Xamarin.Android
Android 7.1 (APIレベル25 - Nougat)
MainActivity.cs
C#
1public class MainActivity : Activity 2{ 3 protected override void OnCreate(Bundle bundle) 4 { 5 base.OnCreate(bundle); 6 SetContentView(Resource.Layout.Main); 7 8 //サービスがあれば終了させる 9 var context = this.ApplicationContext; 10 context.StopService(new Intent(context, typeof(BackgroundService))); 11 } 12 13 protected async override void OnStop() 14 { 15 //サービスを起動 16 var context = this.ApplicationContext; 17 var serviceIntent = new Intent(context, typeof(BackgroundService)); 18 serviceIntent.AddFlags(ActivityFlags.NewTask); 19 context.StartService(serviceIntent); 20 21 base.OnStop(); 22 System.Diagnostics.Process.GetCurrentProcess().CloseMainWindow(); 23 } 24}
BackgroundService.cs
C#
1[Service(Name = "com.CompanyName.App.BackgroundService", Exported = true, Process = ":Process")] 2public class BackgroundService : Service 3{ 4 /// <summary> 5 /// 6 /// </summary> 7 Thread thread; 8 9 /// <summary> 10 /// 11 /// </summary> 12 /// <param name="intent"></param> 13 /// <returns></returns> 14 public override IBinder OnBind(Intent intent) 15 { 16 return null; 17 } 18 19 /// <summary> 20 /// 21 /// </summary> 22 /// <param name="intent"></param> 23 /// <param name="flags"></param> 24 /// <param name="startId"></param> 25 /// <returns></returns> 26 [return: GeneratedEnum] 27 public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId) 28 { 29 try 30 { 31 thread = new Thread(() => 32 { 33 //var bundle = new Bundle(); 34 //global::Xamarin.Forms.Forms.Init(this, bundle); 35 36 // 別スレッドでWhile処理を用いてアップロードを実行 37 BackgroundThread.Main(); 38 }); 39 thread.Start(); 40 41 return StartCommandResult.NotSticky; 42 } 43 catch(Exception ex) 44 { 45 return StartCommandResult.NotSticky; 46 } 47 } 48 49 /// <summary> 50 /// 51 /// </summary> 52 public override void OnDestroy() 53 { 54 try 55 { 56 base.OnDestroy(); 57 58 thread.Interrupt(); 59 thread = null; 60 61 StopSelf(); 62 } 63 catch (Exception ex) 64 { 65 66 } 67 } 68}
BackgroundThread.cs
C#
1public static class BackgroundThread 2{ 3 /// <summary> 4 /// GPS 5 /// </summary> 6 private static IGeolocator _GeoLocator; 7 8 /// <summary> 9 /// GPS取得データ 10 /// </summary> 11 private static Position _LastPos; 12 13 public static async void Main() 14 { 15 var mac = AppUtil.GetDeviceMacAddress(); 16 17 _GeoLocator = CrossGeolocator.Current; 18 _GeoLocator.DesiredAccuracy = 10; 19 _GeoLocator.AllowsBackgroundUpdates = true; 20 _GeoLocator.PositionChanged -= Geolocator_PositionChanged; 21 _GeoLocator.PositionChanged += Geolocator_PositionChanged; 22 await _GeoLocator.StartListeningAsync(1000, 0, true); 23 24 while (true) 25 { 26 try 27 { 28 // 位置情報をサーバーへPOST 29 using (var httpClient = new HttpClient()) 30 { 31 httpClient.Timeout = TimeSpan.FromMilliseconds(10000); 32 httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 33 34 // JSON形式に 35 var jArray = new JArray(); 36 37 var jObj = new JObject(); 38 jObj.Add("DeviceMacAddress", mac); 39 jObj.Add("GpsAccelerometerX", 0); 40 jObj.Add("GpsAccelerometerY", 0); 41 jObj.Add("GpsAccelerometerZ", 0); 42 jObj.Add("GpsDatetime", _LastPos.Timestamp); 43 jObj.Add("GpsLat", _LastPos.Latitude); 44 jObj.Add("GpsLon", _LastPos.Longitude); 45 jObj.Add("GpsSpeed", _LastPos.Speed); 46 jObj.Add("GpsDirection", _LastPos.Heading); 47 jObj.Add("GpsAccuracy", _LastPos.Accuracy); 48 jArray.Add(jObj); 49 50 var content = new StringContent(jArray.ToString(), System.Text.Encoding.UTF8, "application/json"); 51 //httpClient.PostAsync(GetString(Resource.String.DomainUrl) + GetString(Resource.String.ApiValues), content); 52 await httpClient.PostAsync(@"http://www.xxx.com/api/values/", content); 53 } 54 } 55 catch (Exception ex) 56 { 57 string message = ex.Message; 58 Console.WriteLine(ex.Message); 59 } 60 61 Thread.Sleep(10000); 62 } 63 } 64 65 /// <summary> 66 /// 位置情報更新 67 /// </summary> 68 /// <param name="sender"></param> 69 /// <param name="e"></param> 70 private static void Geolocator_PositionChanged(object sender, PositionEventArgs e) 71 { 72 if (e.Position.Accuracy <= 100) 73 { 74 _LastPos = new Position 75 { 76 Timestamp = e.Position.Timestamp.ToLocalTime(), 77 Latitude = e.Position.Latitude, 78 Longitude = AppUtil.ToRoundDown(e.Position.Longitude, 79 Speed = e.Position.Speed, 80 Heading = e.Position.Heading, 81 Accuracy = e.Position.Accuracy 82 }; 83 } 84 } 85 86}
回答1件
あなたの回答
tips
プレビュー