• 【Android】15.2 广播


    分类:C#、Android、VS2015;

    创建日期:2016-02-29

    一、简介

    Android系统和你自己编写的应用程序都可以通过Indent发送和接收广播信息。广播的内容既可以是自定义的信息,也可以是Android的系统信息。例如,网络连接变化、电池电量变化、系统设置变化、接收到新的短信、微信、……等。

    1、发送广播消息

    一般都是通过后台服务中向前台发送广播消息。当然,也可以在某个Activity中向其他的Activity发送广播,不过,这种情况很少见。

    要通过服务发送广播,可先定义一个继承自Service的子类,例如:

    [Service]

    public class MyService : Service

    {

    ……

    }

    在该服务子类中,重写StartCommandResult()方法,然后在该方法中创建一个Intent实例,同时还可以调用这个Intent实例的PutExtra()方法包含要发送的附加消息(可选),最后调用SendBroadcast()方法,即可将该消息广播出去。例如:

    intent = new Intent(action);

    intent.PutExtra("message", "这是来自广播的消息");

    SendBroadcast(intent);

    注意:

    (a)用Intent发送广播时,必须在参数中使用“全局唯一的标识符”指定该Intent要执行的动作,总之,你只要确保这个Action名称在整个项目中是唯一的就行了。

    在实际应用中,动作字符串一般用“解决方案名+项目名+动作名”来表示,例如:

    public static readonly string action = "MyBroadcastDemo.action1";

    也可以用“自定义的命名空间+动作名”来表示。例如:

    public static readonly string action = "www.cnblogs.com.rainmj.MyBroadcastDemo";

    但是,这些都是一些约定的大家觉得比较好的做法,并不是必须这样做。换言之,唯一的要求就是不要在同一个项目中有相同的Action名称就行,这就是“全局唯一的标识符”的含义。

    (b)由于发送广播一般都是通过后台服务来实现的,为了不让后台服务影响前台的界面操作,可以通过Task或者Thread来发送(见示例)。当然,如果服务用时很短,比如仅发送一个简单的字符串,那就没有必要用Task或者Thread来实现了。

    发送广播的完整代码见示例中的ch1501Service.cs文件。

    2、接收广播消息

    对于广播接收端来说,凡是注册了BroadcastReceiver的应用程序类,都可以从继承自BroadcastReceiver的类中接收到广播消息,这个实现接收广播的BroadcastReceiver子类就叫广播接收器。

    广播接收器(Broadcast Receivers)接收的广播内容一般来自Android内置的标准服务,另外,还可以来自你自己定义的服务。

    例如:

    public class MyBroadcastReceiver : BroadcastReceiver

    {

    ……

    }

    广播接收器一旦启动,就会自动监听你注册的广播,并在OnReceive()方法中接收广播消息。因此,要正常接收广播,必须在该子类中重写OnReceive()方法,例如:

    public override void OnReceive(Context context, Intent intent)

    {

    ……

    }

    默认情况下,Android要求OnReceive方法必须在5秒内执行完毕,否则Android会认为该组件失去响应,并提示用户强行关闭该组件。

    接收广播的完整代码见示例中的ch1501BroadcastReceiver.cs文件。

    3、注册接收的广播地址

    一般在Activity中注册要用哪个广播接收器来接收广播。

    有两种注册接收广播地址的方式,一种是通过C#代码实现(常用),另一种是在配置文件AndroidManifest.xml中实现(不常用)。

    通过C#代码实现的办法示例如下:

    var receiver = new MyBroadcastReceiver();

    RegisterReceiver(receiver, new IntentFilter(MyService.action));

    StartService(new Intent(this, typeof(MyService)));

    这段代码注册一个BroadcastReceiver,并通过IntentFilter(Intent过滤器)指定要执行的动作,然后就可以调用StartService()方法启动广播服务。

    调用RegisterReceiver()后,系统就会自动在配置文件(AndroidManifest.xml)中配置Intent过滤器,不需要我们自己在这个文件中去手动配置。

    二、示例1运行截图

    本示例演示如何定时发送多种类型的广播。通过这个例子,相信你应该能真正理解“要发送的动作(Action)”的含义,同时也应该能明白如何在一个接收器中通过Intent过滤器注册多个动作。

    该例子提前使用了下一章将要介绍的Android Service的功能。

    image

    三、主要设计步骤

    1、添加ch1501_Main.axml文件

    在Resource/layout文件夹下添加该文件。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <Button
            android:id="@+id/ch1501_btnStart"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="启动服务(发送广播)" />
        <Button
            android:id="@+id/ch1501_btnStop"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="停止服务(停止广播)" />
        <TextView
            android:text=""
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/textView1"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="50dp" />
    </LinearLayout>

    2、添加ch1501Service文件

    在SrcDemos文件夹下添加该文件,模板选择【Class】。

    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Runtime;
    using System;
    using System.Threading.Tasks;
    
    namespace MyDemos.SrcDemos
    {
        [Service]
        public class ch1501Service : Service
        {
            public const string action1 = "www.cnblogs.com.rainmj.ch1501Service";
            public const string action2 = "MyDemos.ch1501Service.Info1";
            public const string action3 = "MyDemos.ch1501Service.Info2";
            public const string action4 = "MyDemos.ch1501Service.Info3";
            public static bool IsCancel;
    
            [return: GeneratedEnum]
            public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
            {
                //一般应根据不同的情况通过action发送不同的广播信息,
                //如果仅发送一条广播,像下面这样直接发送即可,不需要用Task.Run实现
                //intent = new Intent(action1);
                //SendBroadcast(intent);
    
                //如果是长时间运行的后台服务,为了不影响界面操作,最好用
                //线程来实现,比如发送后台处理的进度等。
                //下面以每隔1秒随机选取一个action为例,来演示长时间运行
                //的服务以及定时向前台发送不同类型广播的办法
                Task.Run(async () =>
                {
                    Random r = new Random();
                    string[] actions = { action1, action2, action3, action4 };
                    string action = actions[0];
                    while (true)
                    {
                        if (IsCancel == true)
                        {
                            break;
                        }
                        intent = new Intent(action);
                        SendBroadcast(intent);
                        action = actions[r.Next(actions.Length)];
                        await Task.Delay(1000);
                    }
                });
                return StartCommandResult.Sticky;
            }
    
            public override IBinder OnBind(Intent intent)
            {
                return null;
            }
        }
    }

    3、添加ch1501BroadcastReceiver.cs文件

    在SrcDemos文件夹下添加该文件,模板选择【Class】。

    using Android.Content;
    using Android.Widget;
    
    namespace MyDemos.SrcDemos
    {
        public class ch1501BroadcastReceiver : BroadcastReceiver
        {
            private TextView txt;
            public ch1501BroadcastReceiver(ch1501MainActivity activity)
            {
                txt = activity.FindViewById<TextView>(Resource.Id.textView1);
            }
    
            public override void OnReceive(Context context, Intent intent)
            {
                //此处应该对接收到的intent.Action分别进行处理
                //为简单起见,例子仅将这个字符串在界面上显示出来了
                txt.Text += "
    收到:" + intent.Action;
            }
        }
    }

    4、添加ch1501MainActivity.cs文件

    在SrcDemos文件夹下添加该文件,模板选择【Activity】。

    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Widget;
    
    namespace MyDemos.SrcDemos
    {
        [Activity(Label = "【例15-1】广播基本用法")]
        public class ch1501MainActivity : Activity
        {
            private ch1501BroadcastReceiver receiver;
            private Intent intent;
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                SetContentView(Resource.Layout.ch1501_Main);
                var txt = FindViewById<TextView>(Resource.Id.textView1);
    
                IntentFilter intentFilter = new IntentFilter();
                intentFilter.AddAction(ch1501Service.action1);
                intentFilter.AddAction(ch1501Service.action2);
                intentFilter.AddAction(ch1501Service.action3);
                intentFilter.AddAction(ch1501Service.action4);
                receiver = new ch1501BroadcastReceiver(this);
                RegisterReceiver(receiver, intentFilter);
    
                intent = new Intent(this, typeof(ch1501Service));
                var btnStart = FindViewById<Button>(Resource.Id.ch1501_btnStart);
                btnStart.Click += delegate
                {
                    txt.Text = "";
                    ch1501Service.IsCancel = false;
                    StartService(intent);
                };
                var btnStop = FindViewById<Button>(Resource.Id.ch1501_btnStop);
                btnStop.Click += delegate
                {
                    ch1501Service.IsCancel = true;
                    StopService(intent);
                };
            }
    
            protected override void OnDestroy()
            {
                UnregisterReceiver(receiver);
                ch1501Service.IsCancel = true;
                StopService(intent);
                base.OnDestroy();
            }
        }
    }
  • 相关阅读:
    关于深拷贝和浅拷贝的理解
    Oracle数据库入门
    单例模式入门
    oracle存储过程 (还没动手实践、剩余内容找时间在处理、游标还没接触)
    Oracle用户名及默认密码
    oracle数据库怎么创建数据库实例
    Java 强、弱、软、虚,你属于哪一种?
    内存溢出和内存泄漏的区别
    aop中execution 表达式
    JPA 中@Enumerated
  • 原文地址:https://www.cnblogs.com/rainmj/p/5226229.html
Copyright © 2020-2023  润新知