做网站有没有免费空间,wordpress多商户商城插件,三河网站seo,网站建设php教程视频在网络通信中#xff0c;一个IP网络范围中最大的IP 地址是被保留作为广播地址来使用的。比如某个网络的IP 范围是192.168.0.XXX#xff0c;子网掩码是255.255.255.0#xff0c;那么这个网络的广播地址就是192.168.0.255。广播数据包会被发送到同一网络上的所有端口#xff… 在网络通信中一个IP网络范围中最大的IP 地址是被保留作为广播地址来使用的。比如某个网络的IP 范围是192.168.0.XXX子网掩码是255.255.255.0那么这个网络的广播地址就是192.168.0.255。广播数据包会被发送到同一网络上的所有端口这样在该网络中的每台主机都将会收到这条广播。 为了方便于进行系统级别的消息通知Android 也引入了一套类似的广播消息机制。相比于我前面举出的两个例子Android 中的广播机制会显得更加的灵活本章就将对这一机制的方方面面进行详细的讲解。 一、 广播机制简介 为什么说Android 中的广播机制更加灵活呢这是因为Android 中的每个应用程序都可以对自己感兴趣的广播进行注册这样该程序就只会接收到自己所关心的广播内容这些广播可能是来自于系统的也可能是来自于其他应用程序的。Android 提供了一套完整的API允许应用程序自由地发送和接收广播。发送广播的方法其实之前稍微有提到过一下如果你记性好的话可能还会有印象就是借助我们学过的Intent。而接收广播的方法则需要引入一个新的概念广播接收器Broadcast Receiver。 广播接收器的具体用法将会在下一节中做介绍这里我们先来了解一下广播的类型。Android 中的广播主要可以分为两种类型标准广播和有序广播。 标准广播Normal broadcasts是一种完全异步执行的广播在广播发出之后所有的广播接收器几乎都会在同一时刻接收到这条广播消息因此它们之间没有任何先后顺序可言。这种广播的效率会比较高但同时也意味着它是无法被截断的。标准广播的工作流程如下图 有序广播Ordered broadcasts则是一种同步执行的广播在广播发出之后同一时刻只会有一个广播接收器能够收到这条广播消息当这个广播接收器中的逻辑执行完毕后广播才会继续传递。所以此时的广播接收器是有先后顺序的优先级高的广播接收器就可以先收到广播消息并且前面的广播接收器还可以截断正在传递的广播这样后面的广播接收器就无法收到广播消息了。有序广播的工作流程如图 二、接收系统广播 Android 内置了很多系统级别的广播我们可以在应用程序中通过监听这些广播来得到各种系统的状态信息。比如手机开机完成后会发出一条广播电池的电量发生变化会发出一条广播时间或时区发生改变也会发出一条广播等等。如果想要接收到这些广播就需要使用广播接收器下面我们就来看一下它的具体用法。 1、 动态注册监听网络变化 广播接收器可以自由地对自己感兴趣的广播进行注册这样当有相应的广播发出时广播接收器就能够收到该广播并在内部处理相应的逻辑。注册广播的方式一般有两种在代码中注册和在AndroidManifest.xml 中注册其中前者也被称为动态注册后者也被称为静态注册。 那么该如何创建一个广播接收器呢其实只需要新建一个类让它继承自BroadcastReceiver并重写父类的onReceive()方法就行了。这样当有广播到来时onReceive()方法就会得到执行具体的逻辑就可以在这个方法中处理。 那我们就先通过动态注册的方式编写一个能够监听网络变化的程序借此学习一下广播接收器的基本用法吧。新建一个BroadcastTest 项目然后修改MainActivity 中的代码其中重要的代码如下所示该部分在onCreate 方法中实现 [java] view plaincopy IntentFilter myintentfilter new IntentFilter(); myintentfilter.addAction(time); MyBroadCast mybroadcast new MyBroadCast(); registerReceiver(mybroadcast,myintentfilter); 第一步这里先创建一个IntentFilter 实例并在其addAction 中添加我们要监听的广播这里是time”静态注册则把这一步在AndroidManifest.xml 中完成 第二步创建了一个MyBroadCast 实例然后调用registerReceiver 方法进行注册将MyBroadCast 实例和IntentFilter 实例都传播出去 这样mybroadcast 就会收到所有值为time 的广播实现监听功能。 当然这里我们新建一个类继承自BroadcastReceiver 并重写 onReceive() 方法 [java] view plaincopy class MyBroadCast extends BroadcastReceiver{ Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub int s intent.getIntExtra(key,0); TextView text1 (TextView) findViewById(R.id.text1); text1.setText(计时: s秒); } } 通过这个广播我们也可以利用Intent 的方法实现传送数据的功能并对其进行处理。 2、静态注册实现开机启动 动态注册的广播接收器可以自由地控制注册与注销在灵活性方面有很大的优势但是它也存在着一个缺点即必须要在程序启动之后才能接收到广播因为注册的逻辑是写在onCreate()方法中的。那么有没有什么办法可以让程序在未启动的情况下就能接收到广播呢这就需要使用静态注册的方式了。 我们准备让程序接收一条开机广播当收到这条广播时就可以在onReceive()方法里执行相应的逻辑从而实现开机启动的功能。新建一个MyReceiver继承自 BroadcastReceiver代码如下所示 [java] view plaincopy public class MyReceive extends BroadcastReceiver { Override ublic void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Log.v(MainActivity, 我是广播我来了); Toast.makeText(context, 我是广播我出来了, 0).show(); } } 可以看到这里不再使用内部类的方式来定义广播接收器因为稍后我们需要在AndroidManifest.xml 中将这个广播接收器的类名注册进去。在onReceive()方法中还是简单地使用Toast 弹出一段提示信息。 然后修改AndroidManifest.xml 文件代码如下所示 [java] view plaincopy receiver android:namecn.com.qiang.sendbroadcast.MyReceive intent-filter action android:nameBroadCast/ /intent-filter /receiver 终于application标签内出现了一个新的标签receiver所有静态注册的广播接收器都是在这里进行注册的。它的用法其实和activity标签非常相似首先通过android:name来指定具体注册哪一个广播接收器然后在intent-filter标签里加入想要接收的广播就行了由于Android 系统启动完成后会发出一条值为BroadCast的广播因此我们在这里添加了相应的action。 另外监听系统开机广播也是需要声明权限的可以看到我们使用uses-permission标签又加入了一条android.permission.RECEIVE_BOOT_COMPLETED 权限。 三、发送自定义广播 广播主要分为两种类型标准广播和有序广播在本节中我们就将通过实践的方式来看下这两种广播具体的区别 1、发送标准广播 我们来修改来修改activity_main.xml 中的代码通过按钮来发送广播 [java] view plaincopy Button android:idid/button1 android:layout_widthmatch_parent android:layout_heightwrap_content android:text发送广播/ 这里在布局文件中定义了一个按钮用于作为发送广播的触发点。然后修改MainActivity中的代码如下所示 [java] view plaincopy Button button1 (Button)findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { Override public void onClick(View v) { / TODO Auto-generated method stub Intent intent new Intent(); intent.setAction(BroadCast); sendBroadcast(intent); } }); 可以看到我们在按钮的点击事件里面加入了发送自定义广播的逻辑。首先构建出了一个Intent 对象并把要发送的广播的值传入然后调用了Context 的sendBroadcast()方法将广播发送出去这样所有监听BroadCast 条广播的广播接收器就会收到消息。此时发出去的广播就是一条标准广播。 注意由于广播是使用Intent 进行传递的因此你还可以在Intent 中携带一些数据传递给广播接收器。 2、发送有序广播 广播是一种可以跨进程的通信方式这一点从前面接收系统广播的时候就可以看出来了。因此在我们应用程序内发出的广播其他的应用程序应该也是可以收到的。 有序广播和标准广播的区别之一是我们发送广播时调用的是sendOrderedBroadcast 方法 [java] view plaincopy sendOrderedBroadcast(intent, null); 其中sendOrderedBroadcast()方法接收两个参数第一个参数仍然是Intent第二个参数是一个与权限相关的字符串这里传入null 就行了。 广播接收器是有先后顺序的而且前面的广播接收器还可以将广播截断以阻止其继续传播。那么该如何设定广播接收器的先后顺序呢当然是在注册的时候进行设定的了修改AndroidManifest.xml 中的代码如下所示 [java] view plaincopy receiver android:name.MyBroadcastReceiver intent-filter android:priority100 action android:namecom.example.broadcasttest.MY_BROADCAST/ /intent-filter /receiver 我们通过android:priority 属性给广播接收器设置了优先级优先级比较高的广播接收器就可以先收到广播。这里将MyBroadcastReceiver 的优先级设成了100以保证它一定会在AnotherBroadcastReceiver 之前收到广播。 既然已经获得了接收广播的优先权那么MyBroadcastReceiver 就可以选择是否允许广播继续传递了。修改MyBroadcastReceiver 中的代码如下所示 [java] view plaincopy public class MyBroadcastReceiver extends BroadcastReceiver { Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, received in MyBroadcastReceive, Toast.LENGTH_SHORT).show(); abortBroadcast(); } } 如果在onReceive()方法中调用了abortBroadcast()方法就表示将这条广播截断后面的广播接收器将无法再接收到这条广播。现在重新运行程序并点击一下Send Broadcast 按钮你会发现 只有MyBroadcastReceiver 中的Toast 信息能够弹出 说明这条广播经过MyBroadcastReceiver 之后确实是终止传递了。 下面我们用一个实例——计时器将前面学到的活动、服务、广播综合在一起进行学习整合程序实现的功能很简单就是在前台实现计时的功能并能暂停计时且继续计时时数字会接上暂停前数据继续跳转实例图如下 具体代码如下 1、MainActivty 端 主要实现广播的动态注册广播的发送与接收开启服务与停止服务的功能具体代码如下 [java] view plaincopy package cn.com.qiang.timeservice; import android.os.Bundle; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IntentFilter myintentfilter new IntentFilter(); myintentfilter.addAction(time); MyBroadCast mybroadcast new MyBroadCast(); registerReceiver(mybroadcast,myintentfilter); Button button1 (Button)findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { Override public void onClick(View v) { // TODO Auto-generated method stub Intent startintent new Intent(MainActivity.this,MyService.class); startService(startintent); } }); Button button2 (Button)findViewById(R.id.button2); button2.setOnClickListener(new OnClickListener() { Override public void onClick(View v) { // TODO Auto-generated method stub Intent stopintent new Intent(MainActivity.this,MyService.class); stopService(stopintent); TextView text1 (TextView) findViewById(R.id.text1); text1.setText(计时: 0秒); } }); Button button3 (Button)findViewById(R.id.button3); button3.setOnClickListener(new OnClickListener() { Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent new Intent(); intent.setAction(pause); sendBroadcast(intent); } }); } class MyBroadCast extends BroadcastReceiver{ Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub int s intent.getIntExtra(key,0); TextView text1 (TextView) findViewById(R.id.text1); text1.setText(计时: s秒); } } } 2、MySevice 端 具体实现计时服务与广播的接受与发送具体代码如下 [java] view plaincopy package cn.com.qiang.timeservice; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; public class MyService extends Service { Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } boolean flag; private Thread mythread; private int count; Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); IntentFilter myfilter new IntentFilter(); myfilter.addAction(pause); Pause pause new Pause(); registerReceiver(pause,myfilter); } Override public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub super.onStart(intent, startId); mythread new MyThread(); mythread.start(); } Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); ((MyThread) mythread).setflag(); } class Pause extends BroadcastReceiver{ Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub flag true; } } class MyThread extends Thread{ Override public void run() { // TODO Auto-generated method stub super.run(); flag false; while(!flag){ try { Thread.sleep(1000); } catch (Exception e) { // TODO: handle exception } // Log.v(MainActivity, 计时(count)秒); Intent intent new Intent(); intent.setAction(time); intent.putExtra(key, count); sendBroadcast(intent); } } public void setflag(){ flag true; } } } 3、AndroidManiTest 端就不写了该注册的注册就可以了 附在活动中使用Toast Toast 是Android 系统提供的一种非常好的提醒方式在程序中可以使用它将一些短小的信息通知给用户这些信息会在一段时间后自动消失并且不会占用任何屏幕空间我们现在就尝试一下如何在活动中使用Toast。 首先需要定义一个弹出Toast 的触发点正好界面上有个按钮那我们就让点击这个按钮的时候弹出一个Toast 吧。在onCreate()方法中添加代码 [java] view plaincopy protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.first_layout); Button button1 (Button) findViewById(R.id.button_1); button1.setOnClickListener(new OnClickListener() { Override public void onClick(View v) { Toast.makeText(FirstActivity.this, You clicked Button 1, Toast.LENGTH_SHORT).show(); } }); } 在活动中可以通过findViewById()方法获取到在布局文件中定义的元素这里我们传入R.id.button_1来得到按钮的实例这个值是刚才在first_layout.xml 中通过android:id 属性指定的。findViewById()方法返回的是一个View 对象我们需要向下转型将它转成Button对象。得到了按钮的实例之后我们通过调用setOnClickListener()方法为按钮注册一个监听器点击按钮时就会执行监听器中的onClick()方法。因此弹出Toast 的功能当然是要在onClick()方法中编写了。 Toast 的用法非常简单通过静态方法makeText()创建出一个Toast 对象然后调用show()将Toast 显示出来就可以了。这里需要注意的是makeText()方法需要传入三个参数。第一个参数是Context也就是Toast 要求的上下文由于活动本身就是一个Context 对象因此这里直接传入FirstActivity.this即可。第二个参数是Toast显示的文本内容第三个参数是Toast显示的时长有两个内置常量可以选择Toast.LENGTH_SHORT 和Toast.LENGTH_LONG。