`
uule
  • 浏览: 6352652 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

《第一行代码》广播

 
阅读更多

 

10、广播接收器(Broadcast Receiver)

 

  Android 中的广播主要可以分为两种类型,标准广播和有序广播

 

  标准广播(Normal broadcasts):

  是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言

 

  有序广播(Ordered broadcasts):

  是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播

 

  注册广播的方式一般有两种,在代码中注册和在 AndroidManifest.xml 中注册,其中前者也被称为动态注册,后者也被称为静态注册

 

创建一个广播接收器:

  新建一个类,让它继承自 BroadcastReceiver,并重写父类的 onReceive()方法就行了。这样当有广播到来时,onReceive()方法就会得到执行

 

  动态注册:

    因为逻辑都是写在onCreate()中,所以必须要在程序启动之后才能接收到广播

    动态注册的广播接收器一定都要取消注册才行,这里我们是在 onDestroy()方法中通过调用 unregisterReceiver()方法来实现的

 

class NetworkChangeReceiver extends BroadcastReceiver {

			@Override
			public void onReceive(Context context, Intent intent) {
				Toast.makeText(context, "network changes",Toast.LENGTH_SHORT).show();
			}
		}

 

//MainActivity:

		protected void onCreate(Bundle savedInstanceState) {
			...
			//当网络状态发生变化时,系统发出的正是一条值为 android.net.conn.CONNECTIVITY_CHANGE 的广播

			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 {

		}

 打 开AndroidManifest.xml 文件,在里面加入如下权限

  

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

  

静态注册:

  可以让程序在未启动的情况下就能接收到广播

 

    新建一个 BootCompleteReceiver 继承自BroadcastReceiver:

 

public class BootCompleteReceiver extends BroadcastReceiver {

			public void onReceive(Context context, Intent intent) {
				Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
			}
		}

 在 AndroidManifest.xml中添加:

  

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

		<application
			……			

			<receiver android:name=".BootCompleteReceiver" >
				<intent-filter>
					<action android:name="android.intent.action.BOOT_COMPLETED" />
				</intent-filter>
			</receiver>
		</application>

 

 

发送自定义广播

 

发送标准广播:

  1、新建一个广播接收器

  新建一个 MyBroadcastReceiver继承自 BroadcastReceiver

 

  2、在 AndroidManifest.xml 中对这个广播接收器进行注册

 

<receiver android:name=".MyBroadcastReceiver">

		<intent-filter>
			<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
		</intent-filter>
	</receiver>

  

  3、定义按钮发送广播

 

public void onClick(View v) {
		Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
		sendBroadcast(intent);
	}

 

 

发送有序广播:

  1~2跟标准广播一样

  4、

Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent, null);

 

  sendOrderedBroadcast()方法接收两个参数,第一个参数仍然是Intent,第二个参数是一个与权限相关的字符串,这里传入 null 就行了

 

  android:priority 属性给广播接收器设置了优先级,优先级比较高的广播接收器就可以先收到广播

<receiver android:name=".MyBroadcastReceiver">

		<intent-filter android:priority="100" >
			<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
		</intent-filter>
	</receiver>

  abortBroadcast()方法,就表示将这条广播截断,在广播接收器中使用

 

使用本地广播:

  前面我们发送和接收的广播全部都是属于系统全局广播,

  即发出的广播可以被其他任何的任何应用程序接收到,并且我们也可以接收来自于其他任何应用程序的广播

 

  本地广播的用法并不复杂,主要就是使用了一个 LocalBroadcastManager 来对广播进行管理

 

1、接收器

class LocalReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			Toast.makeText(context, "received local broadcast",Toast.LENGTH_SHORT).show();
		}
	}

 

2、

public class MainActivity extends Activity {

		private IntentFilter intentFilter;
		private LocalReceiver localReceiver;
		private LocalBroadcastManager localBroadcastManager;
		

		@Override
		protected void onCreate(Bundle savedInstanceState) {
			。。。
			//获取localBroadcastManager
			localBroadcastManager = LocalBroadcastManager.getInstance(this);
			Button button = (Button) findViewById(R.id.button);
			button.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				 // 发送本地广播
				Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
				localBroadcastManager.sendBroadcast(intent);
				}
			});
	

			intentFilter = new IntentFilter();
			intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
			localReceiver = new LocalReceiver();
			localBroadcastManager.registerReceiver(localReceiver, intentFilter);

		}			

		@Override
		protected void onDestroy() {
			super.onDestroy();
			localBroadcastManager.unregisterReceiver(localReceiver);
		}

 

广播的最佳实践——实现强制下线功能

原理:

点击强制下线按钮,发送一条”强制下线“的广播,在广播接收器里弹出一个不可取消的对话框,点击对话框确定按钮,调用 ActivityCollector 的 finishAll()方法来销毁掉所有活动,并重新启动 LoginActivity 这个活动

 

强制用户下线的逻辑并不是写在 MainActivity 里的,而是应该写在接收这条广播的广播接收器里面这样强制下线的功能就不会依附于任何的界面,不管是在程序的任何地方,只需要发出这样一条广播,就可以完成强制下线的操作了。

 

注意:

由于我们是在广播接收器里启动活动的,因此一定要给Intent 加入 FLAG_ACTIVITY_NEW_TASK 这个标志。

还需要把对话框的类型设为 TYPE_SYSTEM_ALERT,不然它将无法在广播接收器里弹出

 

1、发送广播:

public void onClick(View v) {
      Intent intent = new Intent("com.example.broadcastbestpractice.FORCE_OFFLINE ");
      sendBroadcast(intent);
}

  

2、接收广播:

public class ForceOfflineReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(final Context context, Intent intent) {
        Toast.makeText(context, "received in ForceOfflineReceiver", Toast.LENGTH_SHORT).show();


        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
        dialogBuilder.setTitle("Warning");
        dialogBuilder.setMessage("You are forced to be offline. Please try to login again.");
        dialogBuilder.setCancelable(false);

        //点击对话框OK
        dialogBuilder.setPositiveButton("OK",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityCollector.finishAll(); // 销毁所有活动
                        Intent intent = new Intent(context,MainActivity.class);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        context.startActivity(intent); // 重新启动LoginActivity
                    }
                });

        AlertDialog alertDialog = dialogBuilder.create();
        // 需要设置AlertDialog的类型,保证在广播接收器中可以正常弹出
        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
        alertDialog.show();

       // context.unregisterReceiver(this);
    }
}

 

3、注册广播接收器,声明权限 android.permission.SYSTEM_ALERT_WINDOW 

 

问题:

1、Broadcast的onReceive方法中弹出AlertDialog

 

使用静态注册广播,只能弹出System Alert类型的Dialog。但google在 6.0加入了运行时权限的概念,需要在java代码中进行动态申请。为了防止旧的应用程序崩溃,只对targetSDK为23及以上的程序使用新的权限机制。 

相应的解决方法有如下几种。 

第一种方式是:targetSDK设为23以下就可以规避问题。 

第二种方式是:设置里面给了这个调试应用【允许悬浮窗】 但是得手动的打开(我是没有找到这个悬浮窗到底在哪里)。 

第三种方式是:使用无需权限显示悬浮窗。

 

a 修改广播接收类中的import包 将

import android.support.v7.app.AlertDialog;

修改为:

import android.app.AlertDialog;

 

b 修改AlertDialog的弹窗类型为:TYPE_TOAST 将

alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

修改为:

alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);

这样编译运行就可以正常弹出AlertDialog了。

 

2、在广播中弹出对话框与在Activiity中弹出对话框有所不同,在Activiity中弹出对话框,我们需要用到当前Activiity的Context,而在广播中并没有,如果一定要在广播中弹出一个对话框,我需要定义这个对话框是一个系统级别的。

首先需要有弹出系统对话框的权限

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

在show()之前,要先设置Dialog的类型为TYPE_SYSTEM_ALERT。

alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

最后,最最重要的,AlertDialog要使用android.app.AlertDialog,不要用v7包下的Dialog,会报错。

 

分享到:
评论

相关推荐

    第一行代码Android学习练习代码9

    【标题】"第一行代码Android学习练习代码9" 涉及的是Android开发中的实践环节,这通常是基于郭文静的畅销书《第一行代码——Android》中的第九个练习项目。这本书是Android初学者入门的经典教材,通过实际的编程练习...

    第一行Android代码(第二版)源码

    《第一行Android代码(第二版)》是一本深入浅出的Android编程入门书籍,它旨在帮助初学者快速理解和掌握Android应用开发的基本技能。书中通过丰富的实例和详细的解释,引导读者从零开始,逐步构建自己的第一个...

    第一行代码-Android 源代码

    《第一行代码-Android 源代码》是郭霖撰写的一本面向初学者的Android编程书籍,这本书通过实例引导读者逐步了解和掌握Android应用开发。源代码压缩包提供了书中所有示例程序的完整代码,方便读者实践和学习。以下是...

    Android第二行代码(郭霖全书源代码)

    1. **Android Studio入门**:Android Studio是Android开发的官方集成开发环境(IDE),书中会介绍如何下载、安装和配置Android Studio,以及创建第一个"Hello, World!"应用。 2. **AndroidManifest.xml**:每个...

    android第一行代码笔记

    《Android第一行代码笔记》是针对初学者的Android开发指南,涵盖了从基础知识到实际应用的全方位内容。在学习Android开发的过程中,"第一行代码"往往代表着编程旅程的起点,这本笔记将帮助读者逐步理解并掌握这个...

    第一行代码Android学习练习代码

    《第一行代码Android学习练习代码》是针对初学者的一个实践项目,主要涵盖了Android应用开发的基础知识。这个压缩包中的"DYHDM_02_00ActivityTest"很可能是一个示例程序,用于演示和练习Android中的Activity管理。...

    第一行代码笔记

    ### 第一行代码笔记知识点梳理 #### 一、打印与日志输出 1. **`System.out.print()`**:这是Java中的标准输出方法,用于在控制台打印文本信息。 2. **`Log`类的使用**: - `v`:表示最详细的日志输出等级,通常...

    第一行代码——Android 阅读计划-信仰.pdf

    本书《第一行代码——Android(第2版)》是一本适合Android初学者的教材,它详细介绍了Android开发的基础知识和技能。为了帮助读者更好地学习和掌握Android开发,书中特别为读者制定了一个四周的阅读计划,旨在通过...

    《第二行代码》全书源代码

    《第二行代码》是一本专注于Android开发的书籍,旨在帮助开发者深入理解并掌握Android应用程序的构建技巧。书中通过丰富的实例和详细的解释,让读者能够从基础到进阶逐步提升自己的编程技能。源代码是学习过程中的...

    第一行代码——Android(第3版)-思维导图.pdf

    《第一行代码——Android(第3版)》是一本专门为初学者准备的Android开发教程书籍,由郭霖编写。它以通俗易懂的语言和丰富的实例,带领初学者入门Android开发,并且循序渐进地深入到Android平台的各个方面。思维...

    《第一行Android代码》课件:第五章 全局大喇叭-详解广播机制.pptx

    《第一行Android代码》课件:第五章 全局大喇叭-详解广播机制.pptx

    Android第二行代码(全书源代码)

    《Android第二行代码》是一本深受开发者欢迎的Android编程入门书籍,其全书源代码包含了大量的实例和练习,旨在帮助读者深入理解Android应用开发的基本概念和技术。这些源代码覆盖了从基础到进阶的各种主题,涵盖了...

    第一行代码Java源代码第12章课程代码Java网络编

    【标题】"第一行代码Java源代码第12章课程代码Java网络编"涉及的是Java编程语言在网络编程方面的知识,这是Java开发中的一个重要领域。在这一章节中,开发者通常会学习如何利用Java API来实现网络通信,包括客户端与...

    第一行代码 第三版 第6章 6.3发送自定义广播

    发送自定义广播的逻辑: 1.构建一个Intent对象,并将要发送的广播的值传入,2.调用Intent的setPackage()方法,并传入当前应用程序的包名。3.最后调用sendBroadcast 发送广播。 //首先构造了一个Intent对象,将要...

    Android第二行代码源码

    《Android第二行代码》是Android开发领域的一本经典著作,主要面向初级到中级的开发者,旨在帮助他们深入理解Android应用开发。源码Demo是书中的重要组成部分,通过实践这些示例,读者可以更好地掌握Android编程的...

    第一行代码多章相关代码

    《第一行代码》是郭霖撰写的一本针对Android开发的入门书籍,深受初学者和有一定经验的开发者喜爱。书中的代码实例涵盖了Android开发的多个重要方面,包括UI设计、数据存储、网络通信、多媒体处理等。这个压缩包文件...

    Android第一行代码源码 BroadcastBestPractice.rar

    "Android第一行代码源码 BroadcastBestPractice.rar"是一个关于Android广播最佳实践的压缩包,它可能包含了详细的示例代码和讲解,旨在帮助开发者理解并掌握如何有效地使用Android广播。在这里,我们将深入探讨...

    包含五百多广播电台的网站代码!

    ”表明这是一个与构建网络电台相关的代码资源包,里面包含了大量广播电台的数据和对应的网页实现代码。这可能是用于创建一个聚合了众多广播频道的在线平台,使得用户可以通过网站收听来自全球各地的广播节目。 描述...

    第一行代码(2)的基本实现

    在Android开发领域,"第一行代码"是一本非常受欢迎的入门书籍,由郭霖老师撰写。这本书通过实际的示例代码帮助初学者快速理解和掌握Android编程的基础知识。在这个"第一行代码(2)"的基本实现中,我们可以看到作者...

Global site tag (gtag.js) - Google Analytics