【问题标题】:One Service data Multiple Activity in androidAndroid中的一项服务数据多项活动
【发布时间】:2016-11-12 07:01:07
【问题描述】:

您好,我为 Xamarin 制作了 Android 应用程序。我在 Android Studio 中创建了一个简单的应用程序。所以任何答案都欢迎 Java 或 C# 我有一项服务(GPS 服务)和 2 项活动。 MainActivity - GPS 服务与广播连接良好。我希望 MainActivity -> 另一个活动实时 GPS 点。(从 GPS 服务发送到另一个活动也可以。)但它失败了......应用程序死了..

MainActivity 代码

    private void RegisterService()
    {
        _gpsServiceConnection = new GPSServiceConnection(_binder);
        _gpsServiceIntent = new Intent(Android.App.Application.Context, typeof(GPS.GPSService));
        BindService(_gpsServiceIntent, _gpsServiceConnection, Bind.AutoCreate);
    }

    private void RegisterBroadcastReceiver()
    {
        IntentFilter filter = new IntentFilter(GPSServiceReciever.LOCATION_UPDATED);
        filter.AddCategory(Intent.CategoryDefault);
        _receiver = new GPSServiceReciever();
        RegisterReceiver(_receiver, filter);
    }

    private void UnRegisterBroadcastReceiver()
    {
        UnregisterReceiver(_receiver);
    }

    public void UpdateUI(Intent intent)
    {
        LatLng_txt.Text = intent.GetStringExtra("Location");
        Lat = intent.GetDoubleExtra("Lat", 0.0);
        Lng = intent.GetDoubleExtra("Lng", 0.0);
    }

    protected override void OnResume()
    {
        base.OnResume();
        RegisterBroadcastReceiver();
    }

    protected override void OnPause()
    {
        base.OnPause();
        UnRegisterBroadcastReceiver();
    }

    [BroadcastReceiver]
    internal class GPSServiceReciever : BroadcastReceiver
    {
        public static readonly string LOCATION_UPDATED = "LOCATION_UPDATED";
        public override void OnReceive(Context context, Intent intent)
        {
            if (intent.Action.Equals(LOCATION_UPDATED))
            {
                Instance.UpdateUI(intent);

            }
        }
    }

GPS 服务代码

public void OnLocationChanged(Location location)
    {
        try
        {
            _currentLocation = location;

            if (_currentLocation == null)
            {
                _location = "Unable to determine your location.";
            }
            else
            {
                _location = String.Format("{0}, {1}", _currentLocation.Latitude, _currentLocation.Longitude);

                Geocoder geocoder = new Geocoder(this);

                IList<Address> addressList = geocoder.GetFromLocation(_currentLocation.Latitude,
                    _currentLocation.Longitude, 10);

                Address addressCurrent = addressList.FirstOrDefault();

                if (addressCurrent != null)
                {
                    StringBuilder deviceAddress = new StringBuilder();

                    for (int i = 0; i < addressCurrent.MaxAddressLineIndex; i++)
                    {
                        deviceAddress.Append(addressCurrent.GetAddressLine(i)).AppendLine(",");
                    }

                    _address = deviceAddress.ToString();
                }
                else
                {
                    _address = "Unable to determine the address.";
                }

                IList<Address> source = geocoder.GetFromLocationName(_sourceAddress, 1);
                Address addressOrigin = source.FirstOrDefault();

                var coord1 = new LatLng(addressOrigin.Latitude, addressOrigin.Longitude);
                var coord2 = new LatLng(addressCurrent.Latitude, addressCurrent.Longitude);

                var distanceInRadius = Utils.HaversineDistance(coord1, coord2, Utils.DistanceUnit.Miles);

                _remarks = string.Format("Your are {0} miles away from your original location.", distanceInRadius);

                Intent intent = new Intent(this, typeof(MainActivity.GPSServiceReciever));
                intent.SetAction(MainActivity.GPSServiceReciever.LOCATION_UPDATED);
                intent.AddCategory(Intent.CategoryDefault);
                intent.PutExtra("Location", _location);
                intent.PutExtra("Lat", _currentLocation.Latitude);
                intent.PutExtra("Lng", _currentLocation.Longitude);
                SendBroadcast(intent);

            }
        }
        catch
        {
            _address = "Unable to determine the address.";
        }

    }

有没有什么好办法?

【问题讨论】:

  • 据我了解您的问题,您希望通过Service 将数据从一个Activity 发送到另一个。我说的对吗?
  • MainActivity 和另一个活动需要实时 GPS 点数据。所以我尝试直接发送,也尝试从服务发送两个意图,但失败了......

标签: java c# android xamarin


【解决方案1】:

我了解您的问题。但对 GPS 等不了解更多。我在创建音乐应用程序时遇到了同样的问题。 有两个活动和一个服务。并且成功地从两个活动中获得了实时的歌曲位置和歌曲数据。

我的 MainActivity 有

ServiceConnection sc=null;
public static PlayerService ps;

并在 MainActivity 的 onCreate 中获取其值

   sc=new ServiceConnection(){

        @Override
        public void onServiceConnected(ComponentName p1, IBinder p2)
        {
            PlayerService.Getters getters=(PlayerService.Getters) p2;
            ps=getters.getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName p1)
        {
            // TODO: Implement this method
        }

    };

那么PlayerService.Getters类就是

public  class Getters extends Binder
{
    public PlayerService getService()
    {
        return PlayerService.this;
    }
}

PlayerService 有

@Override
public IBinder onBind(Intent p1)
{
    return new Getters();
}

Getters 的 getService 将 PlayerService 的对象提供给我的 MainActivity。 现在我可以使用来自多个活动的静态 ps 获取服务变量和方法的实时值。

【讨论】:

  • 嗯....我认为习惯于观察者模式。但缺乏设计模式的概念,不适用。
  • 我认为与来自多个活动的服务进行通信很容易。因为我用过,感觉很简单。
【解决方案2】:

为了将数据或信息从Service 发送到Activity,您需要使用Messenger API。此 API 将允许您创建进程间通信 (IPC),即两个或多个进程之间的通信链接。在 Android 中,ActivityService 是两个独立的进程,因此您可以使用 IPC 技术在它们之间建立通信链接。

在IPC技术中,有两个端,Server端和Client端。 Service 充当服务器,Activity 充当客户端。

注意:服务一次只能与一个Activity 通信。

Messenger 允许在处理程序的帮助下实现跨进程的基于消息的通信。

Handler 允许您发送和处理这些消息。

实现 Messenger 的步骤:

步骤 1.Service 实现一个 Handler,它接收来自 Activity 的回调

第 2 步。处理程序然后创建一个 Messenger 对象,该对象进一步创建一个 IBinder,服务返回给 Activity。

第 3 步。Activity 然后使用 IBinder 实例化 Messenger,Activity 使用该 Messenger 向 Service 发送消息。

第四步,Service在第一步创建的Handler中接收消息。

现在让我们通过一个例子来理解它:

像这样在 Service 中创建一个 Handler:

class ServiceHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            default:
                super.handleMessage(msg);
        }
    }
}

现在,将 Messenger 对象与 onBind() 方法一起添加到上面第二步中提到的服务中:

final Messenger messenger = new Messenger(new ServiceHandler());

@Override
public IBinder onBind(Intent intent) {
    return messenger.getBinder();
}

在 Activity 中,我们将创建一个 ServiceConnection 来从 Service 中获取 iBinder 以实例化上面第 3 步中提到的 Messenger 对象。

Messenger messenger;
private ServiceConnection serviceConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder iBinder) {
        messenger = new Messenger(iBinder);
    }

    public void onServiceDisconnected(ComponentName className) {
    }
};

借助上面创建的 ServiceConnection 将 Service 绑定到 Activity:

bindService(new Intent(this, MessengerService.class), serviceConnection,
    Context.BIND_AUTO_CREATE);

要从 Activity 向 Service 发送消息,请使用 Messenger 对象的 send() 方法。

如果你想在Activity中接收来自Service的消息,你需要在Activity中创建一个Messenger和一个Handler,并使用Messenger的replyTo参数来接收消息给各自的Handler。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-08
    • 1970-01-01
    相关资源
    最近更新 更多