Broadcast(广播)是Android系统四大组件之一,Broadcast的主要作用是接收系统或者自定义的广播,并进行相关的处理工作。在广播中的操作时间不能太长,超过5s将被系统回收,造成ANR;如果需要在onReceive方法中做复杂的业务处理,最好的方法是开启一个线程来处理。
用法一:接收系统广播并进行相应的处理
接收广播的方式有两种:一是通过代码注册接收广播;二是通过xml配置的方式接收广播。
两种注册广播功能的区别:
代码注册的方式必须是该应用的进程已经启动,并且注册该广播的Activity或者Service等已经被实例化,才能接收该注册的广播;
xml配置注册广播则不需要以上的各种限制,只要系统发送了广播,就能接收到注册的广播。
在实际应用中,如果想要监听系统发出的广播,在接收到广播后做出相应的逻辑操作。如果选择代码方式注册广播,就会导致一系列问题,因为可能在系统发出广播的时候,该应用的进程并没有启动,导致应用接收不到广播,逻辑操作不能执行的问题。因此建议选择xml的方式注册广播。同时,如果大量使用XML注册广播,会降低系统性能,所以在选择广播注册方式时,应该根据具体业务需求,选择最适合的注册方式。
一、代码方式注册广播
(1)设置广播过滤器——需要接收的广播
//系统发出Intent.ACTION_MEDIA_MOUNTED的时候注册了scheme
//因此在注册监听广播的时候IntentFilter必须添加相应的Scheme才能接收相应的广播
// 接收SDCard mount(安装)广播
IntentFilter mMountFilter= new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
//需要添加Scheme
mMountFilter.addDataScheme("file");
(2)声明广播接收器——注册广播信息
// 注册广播监听
registerReceiver(mReceiver, mMountFilter);
监听SDcard安装(Mounted)广播的具体代码如下(MainActivity.java):
package com.jony.broadcast;
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 mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// do your logic
System.out.println("SDcard is mounted");
Toast.makeText(MainActivity.this, "SDcard have mounted", Toast.LENGTH_LONG).show();
}
};
protected void onStart() {
super.onStart();
//系统发出Intent.ACTION_MEDIA_MOUNTED的时候注册了scheme
//因此在注册监听广播的时候IntentFilter必须添加相应的Scheme才能接收相应的广播
mMountFilter.addDataScheme("file");
registerReceiver(mReceiver, mMountFilter);//注册广播监听
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
protected void onStop() {
super.onStop();
unregisterReceiver(mReceiver);// 取消广播监听
}
}
Manifest.xml文件比较简单,在此不再给出源码
二、XML方式注册广播
继承BroadcastReceiver类,实现onReceive方法——该方法中实现相应的业务逻辑即可
MyBroadcasrReceiver代码如下(MyBroadcasrReceiver.java)
package com.jony.broadcast.broadcast_sticky_test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyBroadcasrReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// do your logic
System.out.println("BroadcasrReceiver is starting");
Toast.makeText(context, "BroadcasrReceiver is starting", Toast.LENGTH_LONG).show();
}
}
在XML中配置自定义BroadcastReceiver的action以及相应的data,在Mainfest中进行如下定义:
<receiver android:name=".MyBroadcasrReceiver" android:label="@string/receiver">
<intent-filter>
<action android:name="com.jony.normalbroadcast"/>
<data android:scheme="file"/>
</intent-filter>
<intent-filter>
<action android:name="com.jony.stickybroadcast"/>
</intent-filter>
</receiver>
小节:以上两种接收广播的方式各有优点,具体选择哪种方式监听广播,需要更具业务需求,做出相应的选择。
用法二:接收自定义广播
首先通过继承BroadcastReceiver类,实现onReceive方法——该方法中实现相应的业务逻辑即可
MyBroadcasrReceiver代码如下(MyBroadcasrReceiver.java)
package com.jony.broadcast.broadcast_sticky_test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyBroadcasrReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// do your logic
System.out.println("BroadcasrReceiver is starting");
Toast.makeText(context, "BroadcasrReceiver is starting", Toast.LENGTH_LONG).show();
}
}
在XML中配置自定义BroadcastReceiver的action以及相应的data,在Mainfest中进行如下定义:
<receiver android:name=".MyBroadcasrReceiver" android:label="@string/receiver">
<intent-filter>
<action android:name="com.jony.normalbroadcast"/>
<data android:scheme="file"/>
</intent-filter>
<intent-filter>
<action android:name="com.jony.stickybroadcast"/>
</intent-filter>
</receiver>
实现BroadcasrReceiver的子类并在Mainfest中进行了以上配置之后,接下来就是见证奇迹的时候了,看看我们怎样启动我们自定义的Broadcast吧……
启动广播的步骤大致可以分为两步:
第一步注册我们自定义的广播;
第二部发送相应的Action——即我们在Mainfest中配置<receiver>时设置的相应action
代码如下所示(MainActivity.java):
package com.jony.broadcast.broadcast_sticky_test;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.Menu;
public class MainActivity extends Activity {
private IntentFilter mFilter;
private MyBroadcasrReceiver mReceiver = new MyBroadcasrReceiver();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFilter = new IntentFilter();
mFilter.addAction("com.jony.normalbroadcast");
// 注册广播
registerReceiver(mReceiver, mFilter);// 在XML中进行广播注册
Intent intent = new Intent("com.jony.stickybroadcast");
sendBroadcast(intent);// 发送广播
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
}
用法三:Normal Broadcast和Sticky Broadcast的区别用法
StickyBroadcast一般很少用到,但是千万不要忘记小人物也有大用处,所以请尊重身边的每一个人。闲话少说,直接切入正题,在使用代码注册广播(广播被嵌入到Activity中或者是Service中)时,当发送一个广播时,被嵌入的Activity或者Service还没有被启动时,发送的normal广播是接收不到的,这时只有发送sticky广播,在应用程序启动被嵌入广播的Activity或者Service时,会接收到stick广播,因此在这样的业务中stick广播就派上了用处。
举例说明:
在使用sticky广播时,需要在AndroidManifest.xml中赋予发送sticky广播的权限
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
首先在被嵌入的Activity中注册广播,具体代码如下(SecondActivity.java):
package com.jony.broadcast.broadcast_sticky_test;
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.widget.Toast;
public class SecondActivity extends Activity{
private IntentFilter filter;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, intent.getAction(), Toast.LENGTH_LONG).show();
}
};
protected void onResume() {
super.onResume();
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
filter = new IntentFilter();
filter.addAction("com.jony.normalbroadcast");
filter.addAction("com.jony.stickybroadcast");
registerReceiver(mReceiver, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
}
在MainActivity中发送广播,代码如下所示(MainActivity.java):
package com.jony.broadcast.broadcast_sticky_test;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
private Button normal_button,sticky_button,launch_button;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init_data();
}
private void init_data() {
normal_button = (Button) findViewById(R.id.send_normal_broadcast);
sticky_button = (Button) findViewById(R.id.send_sticky_broadcast);
launch_button = (Button) findViewById(R.id.receive_broadcast);
normal_button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.jony.normalbroadcast");
sendBroadcast(intent);
}
});
sticky_button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.jony.stickybroadcast");
sendStickyBroadcast(intent);
}
});
launch_button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
startActivity(intent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
protected void onPause() {
super.onPause();
}
}
布局文件和Manifest配置文件都比较简单,在此不再给出。
最后,见证奇迹的时刻就交给大家了……