android学习九(android的广播)

在这里 篇文章里面我将总结广播接收器(Broadcast Receiver)方面的知识。首先我们来了解下andorid中广播的类型,android中的广播可以分为2种,标准广播和有序广播。

标准广播:是一种完全异步执行的广播,在广播发出后,所有广播接收器几乎都会同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率比较高,但同时也意味着它无法被截断的。

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

接收系统广播

广播接收器可以自由的对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广播接收器就能够收到该广播,并在内部处理相应的逻辑。注册广播的方式一般有2种,在代码中和在AndroidManifest.xml中注册,其中前者也被称为动态注册,后者也被称为静态注册。

那么该如何创建一个广播接收器?其实只要新建一个类,让它继承自BroadcastReceiver,并重写父类的onReceiver方法就行了。这样当有广播到来时,onReceiver方法就会得到执行,具体的逻辑处理就可以在这个方法中处理。

下面我们就先通过动态注册的方式来编写一个能够监听网络变化的程序。新建一个项目,项目为BroadcastTest。修改MainActivity中的代码,如下所示:

package com.wj.broadcasttest;

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.Menu;
import android.widget.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() {
		// TODO Auto-generated method stub
		super.onDestroy();
		unregisterReceiver(networkChangeReceiver);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	//继承BroadcastReceiver,重写onReceiver方法,进行广播接收处理。
	class NetworkChangeReceiver extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			Toast.makeText(context, "network changes",
					Toast.LENGTH_SHORT).show();
		}

	}

}

可以看到,MainActivity中定义了一个内部类NetworkChangeReceiver,这个类是继承自BroadcastReceiver的,并重写了父类的onReceiver方法,这样每当网络状态发送变化时,onReceiver方法就会得到执行,这里只是简单的使用Toast提示了一段文本信息。

在onCreate方法中,首先我们创建了一个IntentFilter的实例,并给它添加了一个值为android.net.conn.CONNECTIVITY_CHANGE的action,为什么要添加这个值呢?因为当网络状态发送变化时,系统发出的正是一条值为android.net.conn.CONNECTIVITY_CHANGE的广播,也就是说我们的广播接收器想要监听的广播,就在这里添加相应的action就行了。接着创建了一个NetworkChangeReceiver实例,然后调用registerReceiver(networkChangeReceiver,
intentFilter);方法进行注册,将NetworkChangeReceiver实例和IntentFilter实例都传了进去,这样NetworkChangeReceiver就会收到所有值为android.net.conn.CONNECTIVITY_CHANGE的广播,也就实现了监听网络变化的功能。

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

首先你会在注册完成的时候收到一条广播,然后按下home键回到主界面(注意不能按back键,否则onDestroy方法会执行),接着按下menu键--》System settings---》Data usage进入到数据使用详情界面,然后尝试着打开Mobile
Data来启动和禁用网络,你就会看到有Toast提醒你网络发生了变化。

上面只是提醒网络变化了还不够人性化,最好是能够准确的告诉用户当前是有网络还是没有网络,所以我们对onReceiver的代码进行修改,代码如下:

//继承BroadcastReceiver,重写onReceiver方法,进行广播接收处理。
	class NetworkChangeReceiver extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			ConnectivityManager connectivityManager=(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
			if(networkInfo!=null&&networkInfo.isAvailable()){
				Toast.makeText(context, "network is Available",
						Toast.LENGTH_LONG).show();
			}else{
				Toast.makeText(context, "network is unAvailable",
						Toast.LENGTH_LONG).show();
			}

		}

	}

在onReceiver中首先通过getSystemService方法得到ConnectivityManager的实例,这是一个系统服务类,专门用于管理网络连接。让回调用它的getActiveNetworkInfo方法可以得到NetworkInfo的实例,接着调用NetworkInfo的isAvailable方法,就可以判断出当前是否有网络了,最后我们通过Toast的方式对用户进行提示。

android系统为了保证应用程序的安全性能做了规定,如果程序需要访问一些系统的关键信息,必须在配置文件中声明权限才可以,否则程序将会崩溃,比如这里查询网络状态就是需要生命权限的。给程序添加权限,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wj.broadcasttest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="13"
        android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.wj.broadcasttest.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>
    </application>

</manifest>

重写运行程序,然后按下home键---》按下menu键---》System settings  --》Data usage(没的Data usage,你就找到手机的网络设置也一样),运行程序结果如下:

静态注册实现开机启动

动态注册的广播可以自由地控制注册与注销,在灵活性方面有很大的优势,但是存在的缺点是,必须要在程序启动之后才能接收到广播,因为注册的逻辑是写在onCreate方法中的。如果要程序在未启动的情况下就能接收到广播,这就需要使用静态注册的方式了。

下面准备让程序接收一条开机广播,当收到这条广播时就可以在onReciver方法里执行相应的逻辑,从而实现开机启动的功能。新建BootCompleteReceiver,继承BroadcastReceiver,代码如下:

package com.wj.broadcasttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class BootCompleteReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub

		Toast.makeText(context,
				"Boot Complete", Toast.LENGTH_LONG).show();
	}

}

在AndroidMainifest.xml中将上面的广播进行注册,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wj.broadcasttest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="13"
        android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<span style="color:#ff0000;"><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/></span>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.wj.broadcasttest.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="com.wj.broadcasttest.BootCompleteReceiver">
            <intent-filter >
               <span style="color:#ff0000;"> <action android:name="android.intent.action.BOOT_COMPLETED"/></span>
            </intent-filter>
        </receiver>

    </application>

</manifest>

application标签内出现了一个新的标签receiver,所有静态注册的广播接收器都是在这里进行注册的。由于android系统启动完成后会发出一条值为android.intent.action.BOOT_COMPLETED的广播,依次在这里添加了相应的action。

另外监听系统开机广播需要声明权限,所以使用了<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

把监听网络变化的Toast显示注释掉,然后关闭模拟器,并重写启动,运行程序,将看到Boot Complete弹出来了。

注意:不要在onReceiver方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的,当onReceiver方法运行了较长时间,而没有结束时,程序就会报错。因此广播接收器更多的是扮演一种打开程序其他组件的角色,比如创建一条状态通知,或者启动一个服务等。

发送自定义广播

发送标准广播

新建一个MyBroadcastReceiver类继承BroadcastReceiver,代码如下所示:

package com.wj.broadcasttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyBroadcastReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub

		Toast.makeText(context, "received in MyBroadcastReceiver",
				Toast.LENGTH_SHORT).show();
	}

}

当MyBroadcastReceiver收到自定义的广播时,就会弹出received in MyBroadcastReceiver的提示,然后在AndroidManifest.xml中对广播接收器进行注册:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wj.broadcasttest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="13"
        android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.wj.broadcasttest.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="com.wj.broadcasttest.BootCompleteReceiver">
            <intent-filter >
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

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

    </application>

</manifest>

MyBroadcastReceiver接收值为com.wj.broadcasttest.MY_BROADCAST的广播。

修改稿activity_main.xml中的代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="send broadcast"/>

</LinearLayout>

修改MainActivity里面的代码,代码如下:

package com.wj.broadcasttest;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
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.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.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);

		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("com.wj.broadcasttest.MY_BROADCAST");
				sendBroadcast(intent);
			}
		});

		intentFilter=new IntentFilter();
		intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
		networkChangeReceiver=new NetworkChangeReceiver();
		registerReceiver(networkChangeReceiver, intentFilter);
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		unregisterReceiver(networkChangeReceiver);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	//继承BroadcastReceiver,重写onReceiver方法,进行广播接收处理。
	class NetworkChangeReceiver extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			ConnectivityManager connectivityManager=(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
			if(networkInfo!=null&&networkInfo.isAvailable()){
				/*Toast.makeText(context, "network is Available",
						Toast.LENGTH_LONG).show();*/
			}else{
				Toast.makeText(context, "network is unAvailable",
						Toast.LENGTH_LONG).show();
			}

		}

	}

}

在按钮的点击事件里面加入了发送自定义广播的逻辑。首先构建出了一个Intent对象,并把要发送的广播值传入,然后调用了Context的sendBroadcast方法将广播发送出去。这样所有监听com.wj.broadcasttest.MY_BROADCAST这条广播的广播接收器就会收到消息。此时发送出去的广播就是一条标准广播。运行程序,并点击send
broadcast按钮,运行结果如下:

当然广播发送的时候也可以携带一些数据在Intent中进行传送。

发送有序广播

广播是一种跨进程的通信方式,这一点从前面接收系统广播的时候就可以看出来。因此在我们应用程序内发出的广播,其他的应用程序也是可以接收到的。为了验证这一点,我们在建立一个BroadcastTest2项目。将项目创建好之后,还需要在这个项目下定义一个广播接收器,用于接收上面的自定义广播。

在上面的项目BroadcastTest2中新建AnotherBroadcastReceiver类继承,BroadcastReceiver。代码如下:

<pre name="code" class="java">package com.wj.broadcasttest2;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class AnotherBroadcastReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub

		Toast.makeText(context, "received in AnotherBroadcastReceiver",
				Toast.LENGTH_SHORT).show();
	}

}

上面的代码,只为了在收到广播的时候,弹出一段文本信息。然后在AndroidManifest.xml文件中对上面的广播进行注册,代码如下:

<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wj.broadcasttest2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="13"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.wj.broadcasttest2.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="com.wj.broadcasttest2.AnotherBroadcastReceiver">
            <intent-filter >
                <action android:name="com.wj.broadcasttest.MY_BROADCAST"/>
            </intent-filter>
        </receiver>

    </application>

</manifest>

AnotherBroadcastReceiver同样接收的是com.wj.broadcasttest.MY_BROADCAST这条广播。

现在运行BroadcastTest2项目将这个程序安装到模拟器上,然后回到BroadcastTest项目的主界面,并点击send broadcast按钮,会弹出下面的信息:

上面的这个小案例,就证明了我们应用程序发出的广播是可以被其他应用程序接收到的。不过到目前为止我们发送的广播都还是标准广播,现在我们来尝试下发送有序广播。

修改BroadcastTest项目的MainActivity里面的代码,代码如下:

package com.wj.broadcasttest;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
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.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.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);

		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("com.wj.broadcasttest.MY_BROADCAST");
				//sendBroadcast(intent);
				/*将sendBroadcast(intent)方法改成sendOrderedBroadcast(intent, null)
				 * 就可以发送有序广播了。sendOrderedBroadcast(intent, null)方法接收两个参数
				 * ,第一个参数是仍然是Intent,第二参数是一个与权限相关的字符串,这里传入的是null。
				 * */
				sendOrderedBroadcast(intent, null);//发送有序广播。
			}
		});

		intentFilter=new IntentFilter();
		intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
		networkChangeReceiver=new NetworkChangeReceiver();
		registerReceiver(networkChangeReceiver, intentFilter);
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		unregisterReceiver(networkChangeReceiver);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	//继承BroadcastReceiver,重写onReceiver方法,进行广播接收处理。
	class NetworkChangeReceiver extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			ConnectivityManager connectivityManager=(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
			if(networkInfo!=null&&networkInfo.isAvailable()){
				/*Toast.makeText(context, "network is Available",
						Toast.LENGTH_LONG).show();*/
			}else{
				Toast.makeText(context, "network is unAvailable",
						Toast.LENGTH_LONG).show();
			}

		}

	}

}

sendOrderedBroadcast(intent, null);//发送有序广播。发送有序广播,运行程序,点击send broadcast按钮,你会发现这2个应用程序仍然都会接收到这条广播。看上去好像和标准广播没什么区别,不过别忘了,这个时候的广播接收器是有先后顺序的,而且前面的广播接收器还可以将广播截断,以阻止其继续传播。

那么该如何设定广播接收器的先后顺序了?这个是在注册的时候进行设定的,代码如下:

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

android:priority="100"属性给广播接收器设置了优先级,优先级比较高广播接收器就可以先收到广播。这里把MyBroadcastReceiver的优先级设置为100,以保证它一定会在AnotherBroadcastReceiver之前收到广播。

既然已经获得了接收广播的优先权,那么MyBroadcastReceiver就可以选择释放允许广播继续传递了,修改MyBroadcastReceiver的代码如下所示:

package com.wj.broadcasttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyBroadcastReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub

		Toast.makeText(context, "received in MyBroadcastReceiver",
				Toast.LENGTH_SHORT).show();
		abortBroadcast();//该方法拦截了有序广播,后面的广播就无法在接收到这条广播了
	}

}

在运行程序,这时候就只有MyBroadcastReceiver能收到广播了,弹出信息提示。

使用本地广播

前面发送和接收的广播全部是属于系统全局广播,即发出的广播可以被其他任何的应用程序接收到,并且我们也可以接收到来自于其他任何应用程序的广播。这样很容易引起安全问题。为了解决广播的安全问题,android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递。并且广播接收器也只能接收来自应用程序发出的广播,这样所有的安全问题就都不存在了。在本地广播的使用主要是使用了LocalBroadcastManager来对广播进行管理。并提供了发送广播和注册广播接收器的方法,下面是具体的实例。修改BroadcastTest项目的MainActivity的代码。

package com.wj.broadcasttest;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
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.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

	private IntentFilter intentFilter;
	private NetworkChangeReceiver networkChangeReceiver;
	private LocalReceiver localReceiver;
	private LocalBroadcastManager localBroadcastManager;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//获取LocalBroadcastManager的实例
		localBroadcastManager=LocalBroadcastManager.getInstance(this);
		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("com.wj.broadcasttest.MY_BROADCAST");*/
				//sendBroadcast(intent);
				/*将sendBroadcast(intent)方法改成sendOrderedBroadcast(intent, null)
				 * 就可以发送有序广播了。sendOrderedBroadcast(intent, null)方法接收两个参数
				 * ,第一个参数是仍然是Intent,第二参数是一个与权限相关的字符串,这里传入的是null。
				 * */
				/*sendOrderedBroadcast(intent, null);//发送有序广播。*/		

				//发送本地广播
				Intent intent=new Intent("com.wj.broadcasttest.LOCAL_BROADCAST");
				localBroadcastManager.sendBroadcast(intent);//发送本地广播
				}
		});

		/*intentFilter=new IntentFilter();
		intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
		networkChangeReceiver=new NetworkChangeReceiver();
		registerReceiver(networkChangeReceiver, intentFilter);*/

		//注册本地广播
		intentFilter=new IntentFilter();
		intentFilter.addAction("com.wj.broadcasttest.LOCAL_BROADCAST");
		localReceiver=new LocalReceiver();
		localBroadcastManager.registerReceiver(localReceiver, intentFilter);

	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		/*unregisterReceiver(networkChangeReceiver);*/
		localBroadcastManager.unregisterReceiver(localReceiver);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	class LocalReceiver extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			Toast.makeText(context, "receiver local broadcast",
					Toast.LENGTH_SHORT).show();
		}

	}

	//继承BroadcastReceiver,重写onReceiver方法,进行广播接收处理。
	class NetworkChangeReceiver extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			ConnectivityManager connectivityManager=(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();
			if(networkInfo!=null&&networkInfo.isAvailable()){
				/*Toast.makeText(context, "network is Available",
						Toast.LENGTH_LONG).show();*/
			}else{
				Toast.makeText(context, "network is unAvailable",
						Toast.LENGTH_LONG).show();
			}

		}

	}

}

上面的代码和前面学的动态注册广播以及发送广播的代码是一样的。只不过现在首先是通LocalBroadcastManager

的getInstance方法得到它的一个实例,然后在注册广播接收器的时候调用的是LocalBroadcastManager的registerReceiver方法,在发送广播的时候调用的是LocalBroadcastManager的sendBroadcast方法。

运行程序,效果如下:

注意:本地广播是无法通过静态注册的方式来接收的。其实这也完全可以理解,因为静态注册主要就是为了让程序在未启动的情况下也能收到广播,而发送本地广播时,我们的程序肯定是已经启动了,因此也完全不需要使用静态注册的功能。

使用本地广播的优势:

1.发送的广播不会离开我们的程序,因此不需要担心机密数据泄漏问题。

2.其他的程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的问题。

3.发送本地广播比发送系统全局广播将会更加高效。

转载请注明来至:http://blog.csdn.net/j903829182/article/details/40713385

时间: 2024-10-10 21:27:33

android学习九(android的广播)的相关文章

android学习笔记--android启动过程之init.rc文件浅析

1.  init.rc文件结构文件位置:init.c  : /system/core/initinit.rc  : /system/core/rootdir 首先init.rc文件是以模块为单位的,每个模块里的内容都是一起执行的,模块分为3种类型:on.service.import.我们可以看下init.rc文件是怎么写的:1.import import /init.usb.rc import /init.${ro.hardware}.rc import /init.trace.rc 上面的内容

Android学习——在Android中使用OpenCV的第一个程序

刚开始学习Android,由于之前比较熟悉OpenCV,于是就想先在Android上运行OpenCV试试 =================================================================================== 1.环境配置 JDK Eclipse ADT CDT Android SDK Android NDK cygwin OpenCV for Android 2.4.9 这部分网上很多,我就不再赘述了,可以参考:http://bl

[Android学习笔记]Android向下兼

Android向下兼容的思路:使用高版本的API,在运行时判断真实运行平台的API版本,根据不同版本做不同的处理 关键类:Build.class里面定义了API版本相关信息 内部类:VERSION定义当前系统的版本信息,其中包含SDK版本信息Build.VERSION.SDK_INT可以获取到当前运行的系统的SDK版本号 内部类:VERSION_CODES定义了各个版本的枚举信息 适配时: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONE

[Android学习笔记]Android中多线程开发的一些概念

线程安全: 在多线程的情况下,不会因为线程之间的操作而导致数据错误. 线程同步: 同一个资源,可能在同一时间被多个线程操作,这样会导致数据错误.这是一个现象,也是一个问题,而研究如何解决此类问题的相关工作就叫做线程同步. android中,处理线程同步的手段就是:锁 一般分为公平锁和非公平锁: synchronized(内部锁,互斥锁):synchronized是JVM提供的线程同步机制,如果出现问题,JVM能捕获异常,并释放资源,具体实现机制需要查看JVM源码 synchronized的使用特

Android学习九:屏幕自适应

android中不同手机分辨率适配问题 在项目开发的过程中,同一个布局对应不同的手机会显示出不同的效果.导致这个现象产生的原因是不同手机的分辨率不同.在android sdk提供的帮助文档中,我们可以看到各种手机的分辨率和对应的屏大小.QVGA (240x320),WQVGA400(240x400),WQVGA432 (240x432),HVGA (320x480),WVGA800 (480x800),WVGA854 (480x854). 目前android手机的分辨率大致就是帮助文档中描述的几

Android学习笔记-Android应用程序初步认识

一直觉得自己的技术没有一门专长,似乎什么都会一点,但是却一点都不深入.决定学习Android的开发,说不出的理由,希望自己能够坚持下去. 其实之前已经搭建好了Android的开发环境eclipse+ADT+SDK,这里就不做具体介绍了,个人觉得还是非常有必要把这3个软件单独安装一下, 这样对开发工具能有个系统的认识.Eclipse是一个IDE,针对多门开发语言都能够使用,SDK是针对Android应用开发提供的一个框架,其中有开发 过程中使用到的包和一些集成的工具,ADT是安装在eclipse上

[Android学习十一]Android开发单元测试

网上关于Android单元测试的文字帖子不胜枚举,看完之后能解决问题是好事,不能解决问题那就是浪费时间和经历.大多数文章来自于这篇文章:http://rexstjohn.com/unit-testing-with-android-studio/       自从投入到Android Studio IDE之后基本上就赖着不走了.这里仅讨论AS(Android Studio)中Android单元测试.           开发一个Android应用单元测试这种程序员的自我修养和基本道德测试是必不可少

Android学习十---Android Camera

Android camera用来拍照和拍摄视频的先看一下最后实现的效果图             最后的效果图 一.准备 在你的应用程序上使用android拍照设备,需要考虑以下几个方面 1. 是否是一定需要camera 如果需要,那么就无法安装在没有摄像头的设备. 需要在mainfest 中声明 <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:nam

(转)Android学习笔记 --- android任务栈和启动模式

1.一个应用程序一般都是由多个activity组成的,任务栈(task stack),记录和存放用户开启的activity. 2.当一个应用程序被打开时,系统就会给他分配拟一个任务栈,当任务栈中所有的activity都退出的时候,任务栈就清空了.任务栈中的id是一个integer的数据类型(自增长的). 3.在android操作系统里面会存在多个任务栈,一个应用程序对应一个任务栈. 4.默认情况下,关闭掉一个应用程序,系统就会清空了这个应用程序.但是应用程序的进程还会被保留 为什么要引入任务栈的