Geolocation, Service und lokale Benachrichtigungen

Ich versuche, meine erste Systemanwendung für Android im Zusammenhang mit Geolocation und lokalen Benachrichtigungen zu machen. Ich stelle mir das vor … Es gibt grundlegende Aktivität MainActivity . Nach dem Start startet es einen Service TestService der bei einer Änderung der Koordinaten sie auf dem Server sendet und in der Antwort eine Nachricht erhält, die als lokale Benachrichtigung angezeigt wird. Und ich habe einige Probleme.

  1. Wenn ich die Anwendung schließe (mit Task-Manager), dann wird der Service zu stoppen, so nach Änderung der Koordinaten nichts passiert. Was brauche ich die ganze Zeit? Oder es ist unmöglich?

  2. Nach der Aktivierung der lokalen Benachrichtigung startet es NotifyActivity die detaillierte Informationen enthält. Dort buttonDelete ich auf buttonDelete – es schließt NotifyActivity und startet MainActivity . Aber wenn ich danach auf den OS-Bildschirm umschalte (mit der Back Taste) und zurück (mit Task-Manager), dann wird statt 'MainActivity' wieder 'NotifyActivity' angezeigt. Warum es auftritt und wie es zu vermeiden?

Hauptaktivität

 [Activity(Label = "LocationTest", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); var button = FindViewById<Button>(Resource.Id.myButton); button.Click += delegate { StartService(new Intent(this, typeof(TestService))); button.Text = "Started"; }; } } 

Geolokalisierungsservice

 [Service] public class TestService : Service, ILocationListener { // Start service public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId) { locManager = (LocationManager)GetSystemService(LocationService); locationCriteria = new Criteria(); locationCriteria.Accuracy = Accuracy.Coarse; locationCriteria.PowerRequirement = Power.Low; string locationProvider = locManager.GetBestProvider(locationCriteria, true); // Preferences.MinTime, for example, 60 (seconds) // Preferences.MinDist, for example, 100 (meters) locManager.RequestLocationUpdates(locationProvider, Preferences.MinTime * 1000, Preferences.MinDist, this); return StartCommandResult.Sticky; } public void OnLocationChanged(Location loc) { // Send coordinates to the server, receive a response, and show local notification var msg = new ReceivedMessage(counter++, "Test Title", loc.ToString()); ShowNotification(msg); } // show local notification void ShowNotification(ReceivedMessage msg) { var myContainer = new Bundle(); myContainer.PutLong("msg_id", Convert.ToInt64(msg.Id)); myContainer.PutStringArray("msg_data", new [] { msg.Title, msg.Text }); var resultIntent = new Intent(this, typeof(NotifyActivity)); resultIntent.PutExtras(myContainer); TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this); stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(NotifyActivity))); stackBuilder.AddNextIntent(resultIntent); PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(Convert.ToInt32(msg.Id), PendingIntentFlags.UpdateCurrent); Notification.Builder builder = new Notification.Builder(this) .SetDefaults(NotificationDefaults.Sound | NotificationDefaults.Vibrate) .SetAutoCancel(true) .SetContentIntent(resultPendingIntent) .SetContentTitle(msg.Title) .SetContentText(msg.Text) .SetSmallIcon(Resource.Drawable.Icon); var nm = (NotificationManager)GetSystemService(NotificationService); nm.Notify(Convert.ToInt32(msg.Id), builder.Build()); } } 

Lokale Benachrichtigungen

 [Activity(Label = "NotifyActivity")] public class NotifyActivity : Activity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.NotifyActivity); var msg_id = Intent.Extras.GetLong("msg_id"); var msg_data = Intent.Extras.GetStringArray("msg_data"); FindViewById<TextView>(Resource.Id.textTitle).Text = msg_data[0]; FindViewById<TextView>(Resource.Id.textDescription).Text = msg_data[1]; FindViewById<Button>(Resource.Id.buttonDelete).Click += delegate { StartActivity(typeof(MainActivity)); Finish(); }; } } 

Beispielprojekt hier

  • Warum ist die gleiche Schnittstelle auf einem Emulator und einem Gerät unterschiedlich gemacht?
  • Die Anwendung konnte nicht gestartet werden
  • Xamarin Android Resource Datei nicht gefunden
  • Visual Studio 2017 - Xamarin - Die Datei "obj \ Debug \ android \ bin \ packaged_resources" existiert nicht
  • Genymotion Android Emulator für Xamarin
  • Wie benutzt man setOnTouchListener in C # (Xamarin)
  • Fabric TwitterKit auf Xamarin
  • Visual Studio 2015 Xamarin-Bereitstellung fehlgeschlagen ohne Fehlermeldung
  • 2 Solutions collect form web for “Geolocation, Service und lokale Benachrichtigungen”

    In MainActivity füge diesen Code hinzu. Diese Methode wird Ihr zweites Problem lösen (Bus immer noch Ich weiß nicht, wie man Problem mit Anwendungs-Titel in der Liste der letzten Apps zu lösen).

     public override bool OnKeyDown (Keycode keyCode, KeyEvent e) { if (keyCode == Keycode.Back) { MoveTaskToBack(true); return true; } return base.OnKeyDown (keyCode, e); } 

    Beeing hones Aktivitäten in Android haben viele Fallstricke. Daher ist mein Vorschlag, MainActivity aus dem Dienst zu starten und dann NotifyAcitivity zu starten. Dann kannst du MainActivity wieder starten (in diesem Fall müssen Sie LaunchMode = LaunchMode.SingleTop für MainActivity setzen).

    Für das erste Problem – hast du versucht, [Service (Process = ":remote")] anstelle von [Service] ?

    Ich habe keine Erfahrung mit xamarin, aber ich kann versuchen, die Fragen zu beantworten, wie sie im Allgemeinen auf Android beziehen.

    Frage 1

    Wenn du deine App durch den Task-Manager schliefst, machst du mehr als einfach die App zu schließen – du tödst den ganzen Prozess. Obwohl Sie das Verhalten Ihrer Benutzer nicht kontrollieren können, ist dies nicht die Art und Weise, wie ein Android-Benutzer eine App stoppen soll. Der "richtige" Weg, um eine App zu schließen, ist, einfach wieder raus zu kommen, was den Prozess nicht zerstört und hält den Service im Hintergrund.

    Also, um Ihre Frage zu beantworten, ich glaube nicht, dass es irgendetwas gibt, was Sie tun können, um diese Situation zu umgehen, in der ein Benutzer den Prozess Ihrer Bewerbung mit Nachdruck tötet. Allerdings denke ich nicht, dass du dich über diesen Randfall Gedanken machen musst, denn unter normalen Umständen wird dein App-Prozess nicht getötet, bis das System es für richtig hält oder absolut braucht. So sollte der Service weiterlaufen, wenn die App auf normale Weise geschlossen ist. Die docs sagen:

    Das System wird den Dienst so lange beibehalten, wie es entweder gestartet wird, oder es gibt eine oder mehrere Verbindungen zu ihm mit dem Context.BIND_AUTO_CREATE-Flag. Sobald keine dieser Situationen vorliegt, wird die onDestroy () – Methode des Dienstes aufgerufen und der Service wird effektiv beendet.

    Also ist dein Service in Ordnung. Im Allgemeinen wird Ihre App nicht erwartet, um Fälle zu behandeln, in denen ihr Prozess stark getötet wird.

    Weitere Informationen über Prozesse

    Weitere Informationen zum Service-Lebenszyklus

    Frage 2

    Ich bin nicht ganz sicher, was hier los ist. Allerdings betrachte ich dein verknüpftes Projekt, ich merke, dass deine AndroidManifest.xml Datei kaum ausgefüllt ist. Mein Verdacht ist, dass ohne diese Datei, das Android-System nicht wissen, wie Sie Ihren Backstack zu initialisieren, und es weiß nicht, welche Ihrer Aktivitäten ist die MAIN und LAUNCHER Aktivität.

    Sie sollten Ihre Aktivitäten in AndroidManifest.xml , und in diesem sollten Sie angeben, dass MainActivity Ihre MAIN- und LAUNCHER-Aktivität ist und dass es sich um ein Elternteil von NotifyActivity . Auf diese Weise wird das System wissen, um MainActivity zu öffnen, wenn die App gestartet wird, und es wird wissen, um es zurückzukehren, wenn Sie "zurück" von NotifyActivity . Etwas wie das:

     <application android:label="LocationTest" android:icon="@drawable/icon"> <activity android:name="MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="NotifyActivity" android:parentActivityName="MainActivity"/> </application> 

    Weitere Informationen zur Verwendung Ihres Android Manifest

    Hoffentlich hilft Ihnen das Problem zu lösen!

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.