码迷,mamicode.com
首页 > 移动开发 > 详细

《第一行代码:Android》读书笔记——第5章 Broadcast

时间:2016-03-28 23:27:28      阅读:388      评论:0      收藏:0      [点我收藏+]

标签:

  (一)广播机制简介

  1、Android广播的分类:

  如图所示:

  技术分享

  2、发送广播:使用Intent;接收广播:Broadcast Receiver。

 

  (二)接收系统广播

  1、动态注册监听网络变化

  示例程序:

  (1)MainActivity(注:以下代码中的ToastUtil是自己简单封装的Toast显示功能的类):

 1 package com.example.broadcasttest;
 2 
 3 import android.app.Activity;
 4 import android.content.BroadcastReceiver;
 5 import android.content.Context;
 6 import android.content.Intent;
 7 import android.content.IntentFilter;
 8 import android.net.ConnectivityManager;
 9 import android.net.NetworkInfo;
10 import android.os.Bundle;
11 import android.view.Menu;
12 import android.view.MenuItem;
13 
14 public class MainActivity extends Activity {
15 
16     private IntentFilter intentFilter;
17     private NetworkChangeReceiver networkChangeReceiver;
18 
19     @Override
20     protected void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.activity_main);
23 
24         // 1.创建IntentFilter实例
25         intentFilter = new IntentFilter();
26         // 2.用addAction方法添加action
27         intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
28 
29         // 3.创建内部类NetworkChangeReceiver实例
30         networkChangeReceiver = new NetworkChangeReceiver();
31         // 4.注册
32         registerReceiver(networkChangeReceiver, intentFilter);
33     }
34 
35     class NetworkChangeReceiver extends BroadcastReceiver {
36 
37         @Override
38         public void onReceive(Context context, Intent intent) {
39             // 创建ConnectivityManager实例
40             ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
41             // 创建NetworkInfo对象(需要申请权限ACCESS_NETWORK_STATE)
42             NetworkInfo networkInfo = connectivityManager
43                     .getActiveNetworkInfo();
44 
45             // 判断NetworkInfo的状态,即网络是否可用
46             if (networkInfo != null && networkInfo.isAvailable()) {
47                 ToastUtil.showShort(MainActivity.this, "网络可用!");
48             } else {
49                 ToastUtil.showShort(MainActivity.this, "网络不可用!");
50             }
51 
52         }
53     }
54 
55     @Override
56     protected void onDestroy() {
57         super.onDestroy();
58         unregisterReceiver(networkChangeReceiver);
59     }
60 
61 }

  (2)申请权限

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

  (3)xml文件:不需要添加什么内容。

  2、静态注册实现开机启动

  动态注册的一个缺点就是,必须要在程序启动之后才能接收到广播,而静态注册就可以在程序还未启动时就能接收到广播,利用这一点就可以实现诸如开机启动程序的功能。

  示例程序:

  (1)新建类BootCompleteReceiver继承自BroadcastReceiver(注:onReceive方法中红不能放过于耗时的逻辑,因为其中不允许使用线程):

 1 package com.example.broadcasttest;
 2 
 3 import android.content.BroadcastReceiver;
 4 import android.content.Context;
 5 import android.content.Intent;
 6 
 7 public class BootCompleteReceiver extends BroadcastReceiver {
 8 
 9     @Override
10     public void onReceive(Context context, Intent intent) {
11         ToastUtil.showShort(context, "BroadcastTest开机启动");
12     }
13 
14 }

  (2)在AndroidManifest.xml静态注册广播:

 1 <application
 2         android:allowBackup="true"
 3         android:icon="@drawable/ic_launcher"
 4         android:label="@string/app_name"
 5         android:theme="@style/AppTheme" >
 6         ...
 7         <receiver android:name=".BootCompleteReceiver" >
 8             <intent-filter>
 9                 <action android:name="android.intent.action.BOOT_COMPLETED" />
10             </intent-filter>
11         </receiver>
12     </application>

  (3)申请权限:

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

 

  (三)发送自定义广播

  1、发送标准广播

  (1)在BroadcastTest项目中:

  ①创建MyBroadcastReceiver:

1 public class MyBroadcastReceiver extends BroadcastReceiver {
2 
3     @Override
4     public void onReceive(Context context, Intent intent) {
5         ToastUtil.showShort(context, "在MyBroadcastReceiver中接收到了自定义广播!");
6     }
7 
8 }

  ②在AndroidManifest.xml中注册广播接收器:

1      <receiver android:name=".MyBroadcastReceiver" >
2             <intent-filter>
3                 <action android:name="com.example.broadcasttest.MY_BROADCAST" />
4             </intent-filter>
5         </receiver>

  ③activity_main.xml:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical" >
 5 
 6     <Button
 7         android:id="@+id/send_broadcast_btn"
 8         android:layout_width="match_parent"
 9         android:layout_height="wrap_content"
10         android:text="发送自定义广播" />
11 
12 </LinearLayout>

  ④MainActivity:

 1 package com.example.broadcasttest;
 2 
 3 import android.app.Activity;
 4 import android.content.BroadcastReceiver;
 5 import android.content.Context;
 6 import android.content.Intent;
 7 import android.content.IntentFilter;
 8 import android.net.ConnectivityManager;
 9 import android.net.NetworkInfo;
10 import android.os.Bundle;
11 import android.view.Menu;
12 import android.view.MenuItem;
13 import android.view.View;
14 import android.view.View.OnClickListener;
15 import android.widget.Button;
16 
17 public class MainActivity extends Activity implements OnClickListener {
18 
19     private Button sendBroadcast;
20 
21     @Override
22     protected void onCreate(Bundle savedInstanceState) {
23         super.onCreate(savedInstanceState);
24         setContentView(R.layout.activity_main);
25 
26         sendBroadcast = (Button) findViewById(R.id.send_broadcast_btn);
27         sendBroadcast.setOnClickListener(this);
28     }
29 
30     @Override
31     public void onClick(View v) {
32         switch (v.getId()) {
33         case R.id.send_broadcast_btn:
34             Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
35             sendBroadcast(intent);
36             break;
37         default:
38             break;
39         }
40     }
41 }

  (2)创建BroadcastTest2项目,在其中:

  ①创建AnotherBroadcastReceiver:

1 public class AnotherBroadcastReceiver extends BroadcastReceiver {
2 
3     @Override
4     public void onReceive(Context context, Intent intent) {
5         ToastUtil.showShort(context, "在AnotherBroadcastReceiver中接收到了自定义广播!");
6     }
7 
8 }

  ②在AndroidManifest.xml中注册广播接收器:

1      <receiver android:name=".AnotherBroadcastReceiver" >
2             <intent-filter>
3                 <action android:name="com.example.broadcasttest.MY_BROADCAST" />
4             </intent-filter>
5         </receiver>

  (3)同时运行BroadcastTest和BroadcastTest2程序,然后在BroadcastTest中点击“发送自定义广播”按钮,然后就会发现弹出两次Toast显示接收到了广播。

  2、发送有序广播

  在1中BroadcastTest项目的基础上,做以下修改即可(红色加下划线的代码为新增或修改的代码):

  (1)MainActivity中:

 1   @Override
 2     public void onClick(View v) {
 3         switch (v.getId()) {
 4         case R.id.send_broadcast_btn:
 5             Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
 6             sendOrderedBroadcast(intent, null);
 7             break;
 8         default:
 9             break;
10         }
11     }

  (2)AndroidManifest.xml中:

1      <receiver android:name=".MyBroadcastReceiver" >
2             <intent-filter android:priority="100" >
3                 <action android:name="com.example.broadcasttest.MY_BROADCAST" />
4             </intent-filter>
5         </receiver>

  (3)MyBroadcastReceiver类中:

1 public class MyBroadcastReceiver extends BroadcastReceiver {
2 
3     @Override
4     public void onReceive(Context context, Intent intent) {
5         ToastUtil.showShort(context, "在MyBroadcastReceiver中接收到了自定义广播!");
6  abortBroadcast();
7     }
8 
9 }

  (4)再运行两个程序,点击发送广播按钮后,发现只看到了一个Toast提示,因为另一个广播接收被截断了。 

 

  (四)使用本地广播

  以上的广播都是全局广播,也就是任何应用程序都能接收到。而这会引发安全性问题,如果只希望在当前应用程序内部传递广播,就要使用本地广播了。

  本地广播的关键是使用LocalBroadcastManager来发送广播。示例程序:

  1、xml文件:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical" >
 5 
 6     <Button
 7         android:id="@+id/send_broadcast_btn"
 8         android:layout_width="match_parent"
 9         android:layout_height="wrap_content"
10         android:text="发送自定义广播" />
11 
12 </LinearLayout>

  2、MainActivity:

 1 package com.example.broadcasttest;
 2 
 3 import android.app.Activity;
 4 import android.content.BroadcastReceiver;
 5 import android.content.Context;
 6 import android.content.Intent;
 7 import android.content.IntentFilter;
 8 import android.net.ConnectivityManager;
 9 import android.net.NetworkInfo;
10 import android.os.Bundle;
11 import android.support.v4.content.LocalBroadcastManager;
12 import android.view.Menu;
13 import android.view.MenuItem;
14 import android.view.View;
15 import android.view.View.OnClickListener;
16 import android.widget.Button;
17 
18 public class MainActivity extends Activity implements OnClickListener {
19 
20     private Button sendBroadcast;
21 
22     private IntentFilter intentFilter;
23 
24     private LocalReceiver localReceiver;
25     private LocalBroadcastManager localBroadcastManager;
26 
27     @Override
28     protected void onCreate(Bundle savedInstanceState) {
29         super.onCreate(savedInstanceState);
30         setContentView(R.layout.activity_main);
31 
32         // 1.获取localBroadcastManager实例
33         localBroadcastManager = LocalBroadcastManager.getInstance(this);
34 
35         sendBroadcast = (Button) findViewById(R.id.send_broadcast_btn);
36 
37         // 2.在点击事件中用LocalBroadcastManager的sendBroadcast方法发送广播
38         sendBroadcast.setOnClickListener(this);
39 
40         // 3.注册IntentFilter
41         intentFilter = new IntentFilter();
42         intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
43         localReceiver = new LocalReceiver();
44         localBroadcastManager.registerReceiver(localReceiver, intentFilter);
45     }
46 
47     @Override
48     public void onClick(View v) {
49         switch (v.getId()) {
50         case R.id.send_broadcast_btn:
51             Intent intent = new Intent(
52                     "com.example.broadcasttest.LOCAL_BROADCAST");
53             localBroadcastManager.sendBroadcast(intent);
54             break;
55         default:
56             break;
57         }
58     }
59 
60     @Override
61     protected void onDestroy() {
62         super.onDestroy();
63         localBroadcastManager.unregisterReceiver(localReceiver);
64     }
65 }

  3、注册广播接收器:

1      <receiver android:name=".LocalReceiver" >
2             <intent-filter>
3                 <action android:name="com.example.broadcasttest.LOCAL_BROADCAST" />
4             </intent-filter>
5         </receiver>

  4、这时如果也让另一个程序接收LOCAL_BROADCAST这个广播,会发现是接收不到的。

  5、本地广播的优点:

  (1)不用担心机密数据泄露。

  (2)其他程序无法将广播发送到我们程序的内容,不用担心安全漏洞的问题。

  (3)比全局广播更高效。

 

  (五)最佳实践——实现强制下线功能

  在登录页面输入账号密码进入主界面后,点击强制下线按钮会弹出强制下线Dialog,并且该Dialog不能被取消,当用户点击确定后会发出强制下线广播,再次跳转到登录界面。

  1、login.xml文件:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:stretchColumns="1" >
 6 
 7     <TableRow>
 8 
 9         <TextView
10             android:layout_height="wrap_content"
11             android:text="用户名:" />
12 
13         <EditText
14             android:id="@+id/user_name_et"
15             android:layout_height="wrap_content"
16             android:hint="请输入用户名" />
17     </TableRow>
18 
19     <TableRow>
20 
21         <TextView
22             android:layout_height="wrap_content"
23             android:text="密码:" />
24 
25         <EditText
26             android:id="@+id/password_et"
27             android:layout_height="wrap_content" >
28         </EditText>
29     </TableRow>
30 
31     <TableRow>
32 
33         <Button
34             android:id="@+id/login_bt"
35             android:layout_height="wrap_content"
36             android:layout_span="2"
37             android:text="登录" />
38     </TableRow>
39 
40 </TableLayout>

  2、ActivityCollector类:

 1 public class ActivityCollector {
 2     public static List<Activity> activities = new ArrayList<Activity>();
 3 
 4     public static void addActivity(Activity activity) {
 5         activities.add(activity);
 6     }
 7 
 8     public static void removeActivity(Activity activity) {
 9         activities.remove(activity);
10     }
11 
12     public static void finishAll() {
13         for (Activity activity : activities) {
14             if (!activity.isFinishing()) {
15                 activity.finish();
16             }
17         }
18     }
19 }

  3、BaseActivity类:

 1 public class BaseActivity extends Activity {
 2     @Override
 3     protected void onCreate(Bundle savedInstanceState) {
 4         super.onCreate(savedInstanceState);
 5 
 6         ActivityCollector.addActivity(this);
 7     }
 8 
 9     @Override
10     protected void onDestroy() {
11         super.onDestroy();
12         ActivityCollector.removeActivity(this);
13     }
14 }

  4、LoginActivity类:

 1 public class LoginActivity extends BaseActivity {
 2 
 3     private EditText userNameEt;
 4     private EditText passwordEt;
 5     private Button loginBt;
 6 
 7     @Override
 8     protected void onCreate(Bundle savedInstanceState) {
 9         super.onCreate(savedInstanceState);
10         setContentView(R.layout.login);
11 
12         userNameEt = (EditText) findViewById(R.id.user_name_et);
13         passwordEt = (EditText) findViewById(R.id.password_et);
14         loginBt = (Button) findViewById(R.id.login_bt);
15 
16         loginBt.setOnClickListener(new OnClickListener() {
17 
18             @Override
19             public void onClick(View v) {
20                 String userName = userNameEt.getText().toString();
21                 String password = passwordEt.getText().toString();
22 
23                 // 如果用户名是admin且密码是123456,就认为登录成功
24                 if (userName.equals("110") && password.equals("123456")) {
25                     Intent intent = new Intent(LoginActivity.this,
26                             MainActivity.class);
27                     startActivity(intent);
28                     finish();
29                 } else {
30                     Toast.makeText(LoginActivity.this, "用户名或密码错误!",
31                             Toast.LENGTH_SHORT).show();
32                 }
33             }
34         });
35     }
36 }

  5、activity_main.xml:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context="com.example.broadcastbestpractice.MainActivity" >
10 
11     <TextView
12         android:layout_width="wrap_content"
13         android:layout_height="wrap_content"
14         android:text="这里是主界面" />
15 
16     <Button
17         android:id="@+id/force_offline_bt"
18         android:layout_width="match_parent"
19         android:layout_height="wrap_content"
20         android:layout_margin="40dp"
21         android:text="发送一个强制下线广播" />
22 
23 </RelativeLayout>

  6、MainActivity类:

 1 public class MainActivity extends Activity {
 2 
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7 
 8         Button forceOfflineBt = (Button) findViewById(R.id.force_offline_bt);
 9         forceOfflineBt.setOnClickListener(new OnClickListener() {
10 
11             @Override
12             public void onClick(View v) {
13                 Intent intent = new Intent(
14                         "com.example.broadcastbestpractice.FORCE_OFFLINE");
15                 sendBroadcast(intent);
16             }
17         });
18     }
19 
20 }

  7、ForceOfflineReceiver:

 1 public class ForceOfflineReceiver extends BroadcastReceiver {
 2 
 3     @Override
 4     public void onReceive(final Context context, Intent intent) {
 5         AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
 6         dialogBuilder.setTitle("警告");
 7         dialogBuilder.setMessage("你将要被强制下线!请重新登录!");
 8         dialogBuilder.setCancelable(false);
 9         dialogBuilder.setPositiveButton("确定",
10                 new DialogInterface.OnClickListener() {
11 
12                     @Override
13                     public void onClick(DialogInterface dialog, int which) {
14                         ActivityCollector.finishAll();
15                         Intent intent = new Intent(context, LoginActivity.class);
16                         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
17                         context.startActivity(intent);
18                     }
19                 });
20 
21         AlertDialog alertDialog = dialogBuilder.create();
22         alertDialog.getWindow().setType(
23                 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
24         alertDialog.show();
25     }
26 }

  8、AndroidManifest.xml:

 1 ...
 2      <activity
 3             android:name=".LoginActivity"
 4             android:label="@string/app_name" >
 5             <intent-filter>
 6                 <action android:name="android.intent.action.MAIN" />
 7 
 8                 <category android:name="android.intent.category.LAUNCHER" />
 9             </intent-filter>
10         </activity>
11         <activity android:name=".MainActivity" >
12         </activity>
13 
14         <receiver
15             android:name=".ForceOfflineReceiver"
16             android:exported="false" >
17             <intent-filter>
18                 <action android:name="com.example.broadcastbestpractice.FORCE_OFFLINE" />
19             </intent-filter>
20         </receiver>
21 ...

 

 

 

 

 

 

 

 

 

《第一行代码:Android》读书笔记——第5章 Broadcast

标签:

原文地址:http://www.cnblogs.com/jiayongji/p/5329265.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!