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);
                }
            });
    
    
  • 相关阅读:
    hdu acm 2844 Coins 解题报告
    hdu 1963 Investment 解题报告
    codeforces 454B. Little Pony and Sort by Shift 解题报告
    广大暑假训练1 E题 Paid Roads(poj 3411) 解题报告
    hdu acm 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
    hdu acm 1114 Piggy-Bank 解题报告
    poj 2531 Network Saboteur 解题报告
    数据库范式
    ngnix 配置CI框架 与 CI的简单使用
    Vundle的安装
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/12535169.html
Copyright © 2011-2022 走看看