zoukankan      html  css  js  c++  java
  • 17.Android开发笔记:广播(一)

    1.广播的分类

    • 标准广播
      所有广播接收器可同时收到

    • 有序广播
      一个时刻只能有一个广播接收器收到广播,且可决定可否截断

    2.接收系统广播

    Android内置了很多系统级的广播,比如:开机,电量变化,时间或时区

    3.广播接收器

    要想接收到广播,需要注册广播接收器,注册方式有两种:

    • 动态注册:代码注册

      • 主要是使用方法:registerReceiver(广播接收器,intentFilter)
    • 静态注册:AndroidMannifest.xml中注册

      • 主要代码
        <application>
           ....
           <receiver android:name=".MyBrodcastReceiver"
              android:enabled="true"
              android:exported="false">
              <intent-filter>
                  <action android:name="com.example.mybroadcastDemo.MY_BROADCAST"/>
              </intent-filter>
          </receiver>
        
        

    如何创建广播接收器

    • 创建继承BroadcastReciever
    • 重写方法onRecieve

    3.1 动态注册

    示例:动态监听网络变化

    
    public class MainActivity extends AppCompatActivity {
    
     private NetWorkChangeReciever netWorkChangeReciever;
     
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
    
         IntentFilter intentFilter = new IntentFilter();
         //当网络变化时系统发送该广播
         intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
         //注册广播接收器
         netWorkChangeReciever = new NetWorkChangeReciever();
         registerReceiver(netWorkChangeReciever, intentFilter);
    
     }
    
     @Override
     protected void onDestroy() {
         super.onDestroy();
    
         //注销广播接收器
         unregisterReceiver(netWorkChangeReciever);
     }
    
     class NetWorkChangeReciever extends BroadcastReceiver {
    
         @Override
         public void onReceive(Context context, Intent intent) {
             Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
             Log.d("network", "network changes");
            
    
         }
     }
    }
    
    
    

    关闭模拟器网络:

    显示更详细的网络状态信息:

        class NetWorkChangeReciever extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                //Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
                Log.d("network", "network changes");
    
                ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    
                if (networkInfo != null && networkInfo.isAvailable()){
                    Toast.makeText(context, "网络已连接", Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(context, "网络不可用", Toast.LENGTH_SHORT).show();
                }
            }
        }
    
    

    访问网络状态需要申请权限,在AndroidMannifest.xml文件中添加(Android Studio 有智能提示):

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    

    3.2 静态注册

    静态注册广播被禁用:

    解决安卓Android 8.0以上的静态广播无法注册

    • 1.创建接收器:右键本程序包节点->New Other->Broadcast Reciever, 命名为BootCompleteReciever

      • 勾选【Export】:表示广播接收器接收本程序以为的广播
      • 勾选【Enable】: 表示广播接收器可用
    • 2.BroadcastReceiver 修改 onReceive

    public class BootCompleteReciever extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO: This method is called when the BroadcastReceiver is receiving
            // an Intent broadcast.
            Log.d("reciever", "this is boot complete reciever");
            Toast.makeText(context, "系统启动了", Toast.LENGTH_LONG).show();
        }
    }  
    
    • 3.添加权限
      申请监听系统开机系统广播的权限,在AndroidMannifest.xml文件中添加
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.broadcastdemo">
       ...
       <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
        ...
    
    • 4.在AndroidMannifest.xml文件中
      receiver(BootCompleteReciever)的节点添加intent-filter标签: android.intent.action.BOOT_COMPLETED
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            ...
           
            <receiver
                android:name=".BootCompleteReciever"
                android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED"/>
                </intent-filter>
            </receiver>
            
             ...
    

    注意:
    不要在onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的,
    当onReceive()方法运行了较长时间而没有结束时,程序就会报错。
    因此广播接收器更多的是扮演一种打开程序其他组件的角色,比如
    创建一条状态栏通知,或者启动一个服务等,

    4.发送自定义广播

    4.1 发送标准广播

    使用方法`sendBroadcast(intent)`;
    
    • 定义广播接收器MyBrodcastReceiver:
    public class MyBrodcastReceiver extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
         Toast.makeText(context, "收到自定义广播 ", Toast.LENGTH_LONG).show();
     }
    }
    
    
    • AndroidMannifest.xml文件中注册广播接收器MyBrodcastReceiver
            <receiver android:name=".MyBrodcastReceiver"
                android:enabled="true"
                android:exported="false">
                <intent-filter>
                    <action android:name="com.example.mybroadcastDemo.MY_BROADCAST"/>
                </intent-filter>
            </receiver>
    
    
    • 发起自定义消息

      在MainActivity中的创建一个按钮,点击它发送指定义广播

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/btn_send_my_broadcast"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            android:text="发送自定义广播 MY_BROADCAST"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Button btn_send_my_broadcast = findViewById(R.id.btn_send_my_broadcast);
            btn_send_my_broadcast.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent("com.example.mybroadcastDemo.MY_BROADCAST");
                    sendBroadcast(intent); //发送自定义标准广播
                }
            });
        }
    }
    
    

    点击按钮,接收程序内部自定义广播

    • 其它程序接收自定义广播com.example.mybroadcastDemo.MY_BROADCAST:
      创建一个新的工程:【MybroadcastReciever2】

      (1)创建广播接收器RecieveAntherAppBroadcast

    
    public class RecieveAntherAppBroadcast extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context,"mybroadcastreciever2:收到其它程序的广播(com.example.mybroadcastDemo.MY_BROADCAST)", Toast.LENGTH_SHORT).show();
        }
    }
    
    

    (2) 在AndroidMannifest.xml文件中注册广播接收器RecieveAntherAppBroadcast

    
            <receiver android:name=".RecieveAntherAppBroadcast"
                android:exported="true"
                android:enabled="true" >
                <intent-filter>
                    <action android:name="com.example.mybroadcastDemo.MY_BROADCAST"/>
                </intent-filter>
            </receiver>
    
    
    • 在程序【MyBrodcastReceiver】中点击按钮【发送自定义广播 MY_BROADCAST】,

      程序【MyBrodcastReceiver2】会受到广播:

    4.2 发送有序广播

    在项目【MyBrodcastReceiver】中

    • AndroidMannifest.xml文件中注册广播接收器MyBrodcastReceiver 的优先级:
      <intent-filter android:priority="100"
      数字越大,优先级越高
    
    ...
    
            <receiver android:name=".MyBrodcastReceiver"
                android:enabled="true"
                android:exported="false">
                <intent-filter android:priority="100">
                    <action android:name="com.example.mybroadcastDemo.MY_BROADCAST"/>
                </intent-filter>
            </receiver>
    
    ...
    
    
    • 点击按钮时,使用有序广播
      sendOrderedBroadcast(intent, null);
    
           Button btn_send_my_broadcast = findViewById(R.id.btn_send_my_broadcast);
           btn_send_my_broadcast.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   Intent intent = new Intent("com.example.mybroadcastDemo.MY_BROADCAST");
                   //发起标准广播
                   //sendBroadcast(intent);
    
                   //发起有序广播,sendOrderedBroadcast()方法接收两个参数,
                   // 第一个参数仍然是Intent,
                   // 第二个参数是一个与权限相关的字符串,这里传入null就行
                   sendOrderedBroadcast(intent, null);
               }
           });
    
    
    • 截断广播:

      广播接收器MyBrodcastReceiver使用 abortBroadcast(); 截断广播;

    
    public class MyBrodcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "收到自定义广播 ", Toast.LENGTH_LONG).show();
            abortBroadcast(); //截断广播,优先级的广播器将无法收到广播
        }
    }
    
    

    这样项目【MyBrodcastReceiver2】的App将无法收到广播(com.example.mybroadcastDemo.MY_BROADCAST)。

    5.本地广播

    程序为了避免:
    (1)广播被其它程序截获,
    (2)其它程序不断地给程序发送垃圾广播
    Android引入本地广播机制

    本地广播主要就是使用了一个LocalBroadcastManager来对广播进行管理,并提供了发送广播和注册广播接收器的方法
    另外还有一点需要说明,本地广播是无法通过静态注册的方式来接收的。其实这也完全可以理解,因为静态注册主要就是为了让程序在未启动的情况下也能收到广播,
    而发送本地广播时,我们的程序肯定是已经启动了,因此也完全不需要使用静态注册的功能。

    创建一个新的项目【LocalBroadcastDemo】

    • 1.创建广播接收器LocalReceiver
    
    public class LocalReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "本地广播", Toast.LENGTH_SHORT).show();
        }
    }
    
    
    • 2.注册广播接收器
      localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    
    public class MainActivity extends AppCompatActivity {
    
        private LocalBroadcastManager localBroadcastManager;
        private LocalReceiver localReceiver;
        private final String localBrodcastName = "com.example.localbroadcastdemo.LOCAL_BROADCAST";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            localBroadcastManager = LocalBroadcastManager.getInstance(this);
    
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(localBrodcastName);
            localReceiver = new LocalReceiver();
            //注册本地广播接收器
            localBroadcastManager.registerReceiver(localReceiver, intentFilter);
         
           ...
        }
    }
    
    
    • 3.发送本地广播

    发送本地广播 localBroadcastManager.sendBroadcast(intent);

    
            Button btn_send_loacl_broadcast = findViewById(R.id.btn_send_loacl_broadcast);
            btn_send_loacl_broadcast.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(localBrodcastName);
                    //发送本地广播
                    localBroadcastManager.sendBroadcast(intent);
                }
            });
    
    
  • 相关阅读:
    Centos7安装dockercompose
    windows环境下python2和python3版本的切换
    移动硬盘无法读取分区表修复RAW格式修复
    网络与信息安全初探
    MyBatis下在插入数据时获得MySQL自增长序列的值
    CentOS7下mongodb忘记密码后重置密码
    url中有空格等特殊字符及中文字符处理
    通过linux mail实现网站存活监控告警通知
    如何通过SecureCRT转发功能实现外网访问内网服务
    java转JSON串的几种方式
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/12535169.html
Copyright © 2011-2022 走看看