地理位置,服务和本地通知

Dmi*_*7ry 8 c# android xamarin

我正在尝试制作我的第一个与地理位置和本地通知相关的Android系统应用程序.我想像这样......有基本的活动MainActivity.启动后,它会启动一项服务TestService,在更改坐标的情况下,将它们发送到服务器上,并作为回复接收一些将显示为本地通知的消息.我有一些问题.

  1. 如果我关闭应用程序(使用任务管理器),那么服务将停止,因此在更改坐标后没有任何反应.我需要做什么一直服务工作?或者这不可能?

  2. 激活本地通知后,它会启动NotifyActivity,显示详细信息.我点击buttonDelete它 - 它将关闭NotifyActivity并开始MainActivity.但是如果之后我切换到操作系统屏幕(使用Back按钮)并返回(使用任务管理器),那么"MainActivity"将再次显示为"NotifyActivity".为什么会发生以及如何避免它?

主要活动

[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";
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

地理位置服务

[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());
    }

}
Run Code Online (Sandbox Code Playgroud)

本地通知

[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();
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的示例项目

Art*_*nov 1

在 MainActivity 中添加此代码。此方法将解决您的第二个问题(总线仍然不知道如何解决最近应用程序列表中应用程序标题的问题)。

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

Android 中的 Beeing 磨练活动有很多陷阱。因此,我的建议是从服务启动 MainActivity,然后启动 NotifyAcitivity。然后您可以再次启动 MainActivity(在这种情况下,您需要为 MainActivity 设置 LaunchMode = LaunchMode.SingleTop)。

对于第一个问题 - 您是否尝试过定义[Service (Process = ":remote")]而不是[Service]