将数据从服务发送到其他活动的BroadcastReceiver(Xamarin Android)

Pac*_*aco 5 c# service android broadcastreceiver xamarin

Location从服务发送到自定义BroadcastReceiver时遇到问题.

这是我的BroadcastReceiver.cs

[BroadcastReceiver]
class MyBroadcastReceiver : BroadcastReceiver
{
    public static readonly string GRID_STARTED = "GRID_STARTED";
    public event EventHandler<OnLocationChangedEventArgs> mOnLocationChanged;
    private Location location;
    public override void OnReceive(Context context, Intent intent)
    {
        if (intent.Action == GRID_STARTED)
        {
            Toast.MakeText(context, "Grid Started", ToastLength.Short).Show();
            //location = JsonConvert.DeserializeObject<Location>(intent.GetStringExtra("location"));
            //mOnLocationChanged.Invoke(this, new OnLocationChangedEventArgs(location));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我在上面的代码中取消两行,我的应用程序突然停止.我无法告诉你错误是什么,因为在开发Xamarin应用程序时,调试是由内部错误停止的(我在Xamarin论坛上读过它但是没时间处理它).

这就是我在服务中所做的:

private void BroadcastStarted(Location location)
{
        Intent BroadcastIntent = new Intent(this, typeof(MyBroadcastReceiver));
        BroadcastIntent.PutExtra("location",JsonConvert.SerializeObject(location));
        BroadcastIntent.SetAction(MyBroadcastReceiver.GRID_STARTED);
        BroadcastIntent.AddCategory(Intent.CategoryDefault);
        SendBroadcast(BroadcastIntent);
}
Run Code Online (Sandbox Code Playgroud)

我正在使用Newtonsoft.Json发送一个对象.任何帮助,将不胜感激.

更新:

好吧,不知怎的,我设法揭示错误:

无法找到用于Android.Location.Location类型的构造函数.一个类应该有一个默认的构造函数,一个带参数的构造函数或一个用JsonConstructor属性标记的构造函数.

更新:

整个服务代码:

using Newtonsoft.Json;

namespace GoogleMaps
{
    public class OnLocationChangedEventArgs
    {
    Location location;

    public Location Location
    {
        get { return location; }
        set { location = value; }
    }

    public OnLocationChangedEventArgs(Location location)
    {
        this.location = location;
    }
}

[Service]
class MyService : Service
{
    private LocationManager locationManager = null;

    public MyService()
    {

    }

    private class MyLocationListener : Java.Lang.Object,ILocationListener
    {
        Location mLastLocation;
        public event EventHandler<OnLocationChangedEventArgs> onLoc;

        public MyLocationListener(String provider)
        {
            mLastLocation = new Location(provider);
        }

        public void OnLocationChanged(Location location)
        {
            try
            {
                mLastLocation.Set(location);
                onLoc.Invoke(this, new OnLocationChangedEventArgs(mLastLocation));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public void OnProviderDisabled(string provider)
        {

        }

        public void OnProviderEnabled(string provider)
        {

        }

        public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras)
        {

        }
    }

    private MyLocationListener locationListener = new MyLocationListener("network");

    public override IBinder OnBind(Intent intent)
    {
        return null;
    }
    private void BroadcastStarted(Location location)
    {
        Intent BroadcastIntent = new Intent(this, typeof(MyBroadcastReceiver));
        BroadcastIntent.PutExtra("location",JsonConvert.SerializeObject(location));
        BroadcastIntent.SetAction(MyBroadcastReceiver.GRID_STARTED);
        BroadcastIntent.AddCategory(Intent.CategoryDefault);
        SendBroadcast(BroadcastIntent);
    }

    [return: GeneratedEnum]
    public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
    {
        return StartCommandResult.Sticky;
    }

    public override void OnCreate()
    {
        try
        {
            base.OnCreate();
            InitializeLocationManager();

            locationManager.RequestLocationUpdates(LocationManager.NetworkProvider, 0, 0, locationListener);

            locationListener.onLoc += MyService_onLoc;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    private void MyService_onLoc(object sender, OnLocationChangedEventArgs e)
    {
        BroadcastStarted(e.Location);
    }

    public override void OnDestroy()
    {
        base.OnDestroy();
        locationManager.RemoveUpdates(locationListener);
    }

    private void InitializeLocationManager()
    {
        if (locationManager == null)
        {
            locationManager = (LocationManager)GetSystemService(LocationService);
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)

更新:

这就是我在第6条评论中所说的:

 public override void OnReceive(Context context, Intent intent)
 {
        if (intent.Action == GRID_STARTED)
        {
            try
            {
                Toast.MakeText(context, "Grid Started", ToastLength.Short).Show();

                a = new LatLng(intent.GetDoubleExtra("latitude",0),intent.GetDoubleExtra("longitude",0));
                mOnLocationChanged.Invoke(this, new OnLatLngChangedEventArgs(a)); // NULL EXCEPTION LINE
            }
            catch (Exception ex)
            {
                Toast.MakeText(context, ex.Message, ToastLength.Short).Show();
            }
        }
 }
Run Code Online (Sandbox Code Playgroud)

为什么事件处理程序mOnLocationChanged等于null?服务的一部分:

private void BroadcastStarted(Location location)
{
        Intent BroadcastIntent = new Intent(this, typeof(MyBroadcastReceiver));
        BroadcastIntent.PutExtra("latitude",location.Latitude);
        BroadcastIntent.PutExtra("longitude", location.Longitude);
        BroadcastIntent.SetAction(MyBroadcastReceiver.GRID_STARTED);
        BroadcastIntent.AddCategory(Intent.CategoryDefault);
        SendBroadcast(BroadcastIntent);
}
Run Code Online (Sandbox Code Playgroud)

Tal*_*lha 4

将数据(不是对象)从Service(使用 SendBroadcast)发送到BroadcastReceiver(在 MainActivity 中):

Android-java 要点在这里。(100% 工作且经过测试的代码)。

C# 等效服务类代码:

(有关所需的命名空间/类,请参阅要点中的导入语句)

[Service]
public class BackgroundService : Service
{
        private static LocationReceiver mTickReceiver;
    
        public BackgroundService()
        {
    
        }
    
        public override IBinder OnBind(Intent arg0)
        {
            return null;
        }
    
        public override StartCommandResult OnStartCommand (Android.Content.Intent intent, StartCommandFlags flags, int startId)
        {
            return StartCommandResult.Sticky;
        }
    
        public override void OnCreate()
        {
            registerReceiver();
        }
    
        public override void OnDestroy()
        {
            UnregisterReceiver(mTickReceiver);
            mTickReceiver = null;
        }
    
        private void registerReceiver()
        {
            mTickReceiver = new LocationReceiver();
    
            IntentFilter filter = new IntentFilter(Android.Content.Intent.ActionTimeTick); // this will broadcast Intent every minute
            RegisterReceiver(mTickReceiver, filter);
        }
    
        // you can write this class in separate cs file
        
        [BroadcastReceiver(Enabled = true)]
        
        [IntentFilter(new[] { Android.Content.Intent.ActionTimeTick })]
        
        public class LocationReceiver : BroadcastReceiver
        {
            public override void OnReceive(Context context, Intent intent)
            {
                // sample data, you should get your location here,
                // one way is to implement location logic in this class
                double SampleLatitude=52.01566;
                double SampleLongitude=65.00487;

                // assuming above coordinates are from some location manager code
                Intent I = new Intent();
                i.SetAction("LocationData");
                i.PutExtra("Latitude", SampleLatitude);
                i.PutExtra("Longitude", SampleLongitude);
                // PREPARE BROADCAST FOR MAINACTIVITY
                SendBroadcast(i); // this broadcast will be received by mainactivity
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

C# 等效 MainActivity 类代码:

(有关所需的命名空间/类,请参阅要点中的导入语句)

public class MainActivity : AppCompatActivity
{
        protected override Void OnCreate(Bundle savedInstanceState) 
        {
            base.OnCreate(savedInstanceState);
            SetContentView(R.layout.activity_main);
    
            Intent i = new Intent(this, typeof(BackgroundService));
            StartService(i);
            IntentFilter filter = new IntentFilter("LocationData");
            RegisterReceiver(new MyBroadcastReceiver(), filter);
        }
    
        // public static variables of MainActivty can be accessed and manipulated in this class
        [BroadcastReceiver(Enabled = true)]        
        [IntentFilter(new[] { "LocationData" })]
        class MyBroadcastReceiver : BroadcastReceiver
        {
            public override Void OnReceive(Context context, Intent intent)
            {
                // GET BROADCAST FROM RECEIVER IN THE BACKGROUND SERVICE CLASS
                if (intent.GetAction() == "LocationData")
                {
                    double lat=intent.GetDoubleExtra("Latitude", 0);
                    double lng=intent.GetDoubleExtra("Longitude", 1);
        
                    String LocationDataFromService=lat+","+lng;
                    // REPLACE this with console.writeline
                    Log.d("LocationDataFromService",LocationDataFromService);
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

AndroidManifest.xml服务声明为:

<service android:name=".BackgroundService">
</service>
Run Code Online (Sandbox Code Playgroud)

它可能仍然会抛出一些错误。希望这可以帮助。