Android系统中的广播机制比较灵活,因为Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来自于其他应用程序的。Android提供了一套完整的API,允许应用程序自由地发送和接收广播。
广播的类型主要可以分为以下两种:
1.标准广播(无序广播) 特点:无序、异步,几乎同时接收到
2:.有序广播 特点:有序、同步,根据优先级高低执行,可以被截断
标准广播(无序广播)Normal broadcast是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条消息,因为它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着无法被截断。
有序广播Ordered broadcast则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收器是有一个先后顺序的,优先级高的广播接收器就可以收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接收器就无法收到广播消息了。
Android内置了很多系统级别的广播,我们可以在应用程序中通过监听这些广播来得到各种系统的状态信息。比如手机开机完成后会发出一条广播,电池的电量发生变化发出一条广播,时间或时区发生改变也会发出一条广播,等待。如果想要接收到这些广播,那么我们就需要了解广播接收器,并学会使用它。
广播接收器可以自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广播接收器就能够收到该广播,并在内部处理相应的逻辑。
注册广播的方式有两种:
第一种是静态注册,直接在AndroidManifest.xml中注册
第二种是动态注册,直接在代码中注册
那么该如何创建一个广播接收器呢?其实只需要新建一个类,让它继承自BroadcastReceiver,并重写父类的onReceive()方法就行了。这样当有广播到来时,onReceive()方法就会得到执行。
我们这里通过动态注册的方式编写一个能够监听网路变化的程序。
MainActivity.java代码:
package com.example.administrator.broadcasttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private NetworkChangeReceiver receiver;
private IntentFilter intentFilter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
receiver = new NetworkChangeReceiver();
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(receiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(MainActivity.this, "network changes", Toast.LENGTH_SHORT).show();
}
}
}
效果图:
Toast提示有点麻烦,下面我们换做TextView来显示文字,同时判断网络是否可用。
activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">
<TextView
android:id="@+id/tv_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textColor="@android:color/holo_orange_light"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
MainActivity.java代码:
package com.example.administrator.broadcasttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.ExifInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.Text;
public class MainActivity extends AppCompatActivity {
private NetworkChangeReceiver receiver;
private IntentFilter intentFilter;
private TextView tv_show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
receiver = new NetworkChangeReceiver();
intentFilter = new IntentFilter();
//添加监听网络发生变化的Action,这是动态注册广播的常用方式,静态注册一般在AndroidManifest中添加<action/>标签
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(receiver, intentFilter);
tv_show = (TextView) findViewById(R.id.tv_show);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isAvailable()) {
updateUI("network is available");
} else {
updateUI("network is unavailable");
}
}
}
private void updateUI(final String msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_show.setText(msg);
}
});
}
}
因为要判断网络是否可用,所以需要在AndroidManifest中需要加上监听网络是否可用的权限:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.administrator.broadcasttest">
<!--监听网络状态的权限-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
注意、注意,现在的Android手机对于权限方面的控制很严格了,可能你在程序中已经加上了,然而手机真机中没有允许给予权限,网络状态的监听还是无法使用。
最后运行程序,实现效果图如下:
点击数据流量: