jjzjj

c# - 将数据从服务发送到其他 Activity 的 BroadcastReceiver (Xamarin Android)

coder 2023-12-12 原文

我在将 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));
        }
    }
}

如果我取消注释上面代码中的两行,我的应用程序会突然停止。我无法告诉您错误是什么,因为在开发 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);
}

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

更新:

好吧,不知何故我设法揭示了错误:

Unable to find a constructor to use for type Android.Location.Location. A class should either have a default constructor,one constructor with arguments or a constructor marked with JsonConstructor attribute.

更新:

整个服务代码:

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

更新:

这是我在第 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();
            }
        }
 }

为什么事件处理程序 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);
}

最佳答案

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

Android-java Gist here. (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
        }
    }

    }

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);  


           }
        }
    }
}

AndroidManifest.xml 中声明服务为:

<service android:name=".BackgroundService">
    </service>

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

关于c# - 将数据从服务发送到其他 Activity 的 BroadcastReceiver (Xamarin Android),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37694560/

有关c# - 将数据从服务发送到其他 Activity 的 BroadcastReceiver (Xamarin Android)的更多相关文章

  1. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  2. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  4. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  7. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  8. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  9. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  10. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

随机推荐