一、 接收广播
动态注册广播
通过Toast提醒网络发生变化
public class MainActivity extends Activity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver,intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes",Toast.LENGTH_LONG).show();
}
}
}
对程序进行改进准确告知用户网络的状态
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()){
Toast.makeText(context,"network is available",Toast.LENGTH_SHORT)
.show();
}else{
Toast.makeText(context,"network is unavailable",Toast.LENGTH_SHORT)
.show();
}
// Toast.makeText(context, "network changes",Toast.LENGTH_LONG).show();
}
}
添加权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
静态注册实现开机启动
动态注册的广播接收器可以自由地控制注册与注销,在灵活性方面有很大的优势,但是它也存在着一个缺点,即必须要在程序启动之后才能接收到广播,因为注册的逻辑是写在onCreate()方法中的。
新建一个BootCompleteReceiver继承BroadReceiver,代码如下所示
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete",Toast.LENGTH_SHORT).show();
}
}
修改AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
二、发送广播
发送标准广播
先定义一个MyBroadcastReceiver来接收广播
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "receiver in MyBroadcastReceiver",
Toast.LENGTH_SHORT).show();
}
}
注册广播
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="droidroid.com.sendbroadcast.MY_BROADCAST"/>
</intent-filter>
</receiver>
为button添加点击事件以发送广播
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("droidroid.com.sendbroadcast.MY_BROADCAST");
sendBroadcast(intent);
}
});
}
}
发送有序广播
在发送标准广播的基础上,新建一个新的类AnotherBroadcastReceiver
public class AnotherBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received in AnotherBroadcastReceiver",Toast.LENGTH_SHORT).show();
}
}
注册广播接收器
<receiver android:name=".AnotherBroadcastReceiver">
<intent-filter>
<action android:name="droidroid.com.sendbroadcast.MY_BROADCAST"/>
</intent-filter>
</receiver>
修改MainActivity
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("droidroid.com.sendbroadcast.MY_BROADCAST");
//发送有序广播
sendOrderedBroadcast(intent,null);
}
});
}
}
对MyBroadcastReceiver设置优先级
<receiver android:name=".MyBroadcastReceiver">
<intent-filter android:priority="100">
<action android:name="droidroid.com.sendbroadcast.MY_BROADCAST"/>
</intent-filter>
</receiver>
最后在设置在MyBroadcastReceiver拦截广播
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "receiver in MyBroadcastReceiver", Toast.LENGTH_SHORT).show();
abortBroadcast();
}
发送本地广播
上面所介绍的是系统全局广播,即发出的广播可以被其他任何应用程序接收到,并且我们也可以接收来自其他应用的广播。因此容易引发安全性的问题
引入广播正是为了解决这个问题
本地广播用法并不复杂,主要使用一个LocalBroadcastManager来对广播进行管理,并提供了发送广播和注册广播接收器的方法。
public class MainActivity extends Activity {
private IntentFilter intentFilter;
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取实例
localBroadcastManager = LocalBroadcastManager.getInstance(this);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("droidroid.com.localbroadcast.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent);
}
});
intentFilter = new IntentFilter();
intentFilter.addAction("droidroid.com.localbroadcast.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver,intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
}
class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received local broacast",Toast.LENGTH_SHORT).show();
}
}
}
实践——实现强制下线功能
login.xml
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:stretchColumns="1">
<TableRow>
<TextView android:layout_height="wrap_content"
android:text="Account:"/>
<EditText android:id="@+id/account"
android:layout_height="wrap_content"
android:hint="Input your account"/>
</TableRow>
<TableRow>
<TextView
android:layout_height="wrap_content"
android:text="Password:"/>
<EditText
android:id="@+id/password"
android:layout_height="wrap_content"
android:inputType="textPassword"/>
</TableRow>
<TableRow>
<Button
android:id="@+id/login"
android:layout_height="wrap_content"
android:layout_span="2"
android:text="Login"/>
</TableRow>
</TableLayout>
activity_main.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/force_offline"
android:text="Send force offline broadcast"/>
</LinearLayout>
LoginActivity.java
public class LoginActivity extends BaseActivity {
private EditText accountEdit;
private EditText passwordEdit;
private Button login;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
accountEdit = (EditText) findViewById(R.id.account);
passwordEdit = (EditText) findViewById(R.id.password);
login = (Button) findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String account = accountEdit.getText().toString();
String password = passwordEdit.getText().toString();
if (account.equals("admin") && password.equals("123456")) {
Intent intent = new Intent(LoginActivity.this,
MainActivity.class);
startActivity(intent);
finish();
} else {
Toast.makeText(LoginActivity.this, "account or password is invalid",
Toast.LENGTH_SHORT).show();
}
}
});
}
}
MainActivity.java
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button forceOffline = (Button) findViewById(R.id.force_offline);
forceOffline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("droidroid.com.broadcastbestpractice.FORCE_OFFLINE");
sendBroadcast(intent);
}
});
}
}
ForceOfflineReceiver.java
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button forceOffline = (Button) findViewById(R.id.force_offline);
forceOffline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("droidroid.com.broadcastbestpractice.FORCE_OFFLINE");
sendBroadcast(intent);
}
});
}
}
BaseActivity.java
public class BaseActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
}
ActivityCollector.java
public class ActivityCollector {
public static List<Activity> activities = new ArrayList<Activity>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for(Activity activity : activities){
if(!activity.isFinishing()){
activity.finish();
}
}
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="droidroid.com.broadcastbestpractice" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name=".LoginActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
>
</activity>
<receiver android:name=".ForceOfflineReceiver">
<intent-filter>
<action android:name="droidroid.com.broadcastbestpractice.FORCE_OFFLINE"/>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
</manifest>