转载请标明出处:http://blog.csdn.net/wlwlwlwl015/article/details/44280423
这篇文章写了一半在草稿箱放了半年多
之前由于换工作的原因搁置了Android的学习,但相比服务端开发,我还是对Android更有感觉一些,所以决定以后会继续坚持做Android,废话不多说,继续我的安卓学习之路,半年多没接触Android发现移动端的开发技术确实是日新月异,和传统的服务端开发技术相比更新速度太快了,听说Broadcast已渐渐的被EventBus这个东东替代,但是针对系统广播来讲应该还是无法被替代的,不管是否过时,学了再说吧。学习Broadcast Recivier参考的主要是官方文档和郭神的《第一行代码》之中的部分内容,本篇blog就记录一下我的学习过程以及自己的一些总结体会吧!
为了方便系统级别的消息通知,Android也引入了一整套完整的API用于发送广播or接收广播,而用于接收广播的“接收器”也正是大名鼎鼎的Android四大组件之一的BroadcastReceiver,首先看一下官方文档中对它的介绍:
简单看一下,BroadCastReceiver可以接收到由sendBroadcast()发出的意图(广播),如果不需要跨应用去发送广播,可以考虑使用LocalBroadcastManager去替代它,LocalBroadcastManager可以带给你更为高效的实现,并且让你避免考虑当其它应用接收或发送你的广播时的一些安全问题。你也可以通过Context.registerReceiver()方法去动态的注册一个BroadcastReceiver实例,亦或是通过在AndroidMannifest.xml中定义一个<receiver>标签来静态的声明一个BroadcastReceiver。
根据这段话了解到注册一个广播接收器有两种方式:
package com.wl.broadcastdemo; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.widget.Toast; public class MainActivity extends Activity { private IntentFilter intentFilter; private NetWorkRecevier netWorkRecevier; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); intentFilter = new IntentFilter(); intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); netWorkRecevier = new NetWorkRecevier(); registerReceiver(netWorkRecevier, intentFilter); } class NetWorkRecevier 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_SHORT).show(); } else { Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show(); } } } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); unregisterReceiver(netWorkRecevier); } }
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />这样就OK了,运行程序之后,我们改变手机的网络状态,均可以看到Toast的提示信息。
<receiver>
tag in your AndroidManifest.xml
.在manifest文件中通过receiver标签来注册广播接收器。那么什么情况下需要静态注册,或者说静态注册广播接收器有什么好处呢?相比较动态注册接收器,我们不难发现:需要动态注册接收器的话是通过registerReceiver方法去实现的,而只要调用registerReceiver方法那么必定要执行onCreat方法,换句话说,就是必须启动应用程序才能接收到广播!而静态注册的方式可以实现不启动应用就可以接收广播!那么何时需要不启用应用就要接收广播呢?想想我们做服务端开发的时候,是不是在生产环境的服务器上的许多服务需要开机启动?比如:数据库服务、缓存服务、负载均衡的Nginx服务等等,那么回到Android中来看,如果我们需要做一个“开机启动”的APP,那么必然要通过静态注册BroadcastReceiver去实现了!示例代码依然是郭神书中的例子,很简单,首先自定义一个BroadcastReceiver,然后在manifest文件中通过receiver标签去声明这个广播接收器即可,下面是最简单的一个自定义广播接收器:
package com.wl.broadcastdemo.receiver; 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(); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wl.broadcastdemo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" /> <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=".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=".receiver.BootCompleteReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> </application> </manifest>
package com.wl.broadcastdemo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; public class MainActivity extends Activity { private Button btnSend; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSend = (Button) findViewById(R.id.btn_send); btnSend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub sendBroadcast(new Intent("com.wl.broadcastdemo.MY_BROADCAST")); } }); } @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; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
package com.wl.broadcastdemo.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Toast.makeText(context, "MyReceiver", Toast.LENGTH_LONG).show(); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wl.broadcastdemo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> <application android:allowBackup="true" android:icon="@drawable/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=".receiver.MyReceiver" > <intent-filter> <action android:name="com.wl.broadcastdemo.MY_BROADCAST" /> </intent-filter> </receiver> </application> </manifest>
package com.wl.broadcastdemo2.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Toast.makeText(context, "MyReceiver in other app", Toast.LENGTH_LONG).show(); } }可以看到这个MyReceiver和刚才的没有任何变化,唯独修改了Toast的文本用来区分。再看一下manifest:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wl.broadcastdemo2" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> <application android:allowBackup="true" android:icon="@drawable/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=".receiver.MyReceiver"> <intent-filter> <action android:name="com.wl.broadcastdemo.MY_BROADCAST"/> </intent-filter> </receiver> </application> </manifest>
sendOrderedBroadcast(new Intent("com.wl.broadcastdemo.MY_BROADCAST"), null);
<receiver android:name=".receiver.MyReceiver" > <intent-filter android:priority="60"> <action android:name="com.wl.broadcastdemo.MY_BROADCAST" /> </intent-filter> </receiver>
<receiver android:name=".receiver.MyReceiver"> <intent-filter android:priority="100"> <action android:name="com.wl.broadcastdemo.MY_BROADCAST"/> </intent-filter> </receiver>
package com.wl.broadcastdemo2.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast; public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Toast.makeText(context, "MyReceiver in other app", Toast.LENGTH_LONG).show(); abortBroadcast(); } }
package com.wl.broadcastdemo; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.v4.content.LocalBroadcastManager; import android.view.View; import android.widget.Button; import android.widget.Toast; public class SecondActivity extends Activity { private Button btnSend; private IntentFilter intentFilter; // 自定义Receiver private LocalReceiver localReceiver; private LocalBroadcastManager localBroadcastManager; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); // 实例化LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this); btnSend = (Button) findViewById(R.id.btn_send_two); btnSend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent("com.wl.broadcastdemo.LOCAL_BROADCAST"); // 发送本地广播 localBroadcastManager.sendBroadcast(intent); } }); intentFilter = new IntentFilter(); intentFilter.addAction("com.wl.broadcastdemo.LOCAL_BROADCAST"); localReceiver = new LocalReceiver(); // 注册广播接收器 localBroadcastManager.registerReceiver(localReceiver, intentFilter); } class LocalReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Toast.makeText(context, "received local broadcast!", Toast.LENGTH_LONG).show(); } } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); // 解除注册 localBroadcastManager.unregisterReceiver(localReceiver); } }