一、aandroid的四大组件BroadcastReceiver广播接收器(用于接收程序所发出的Broadcast Intent),其本生就是一个全局的监听器,用于监听系统全局的广播消息。由于BroadcastReceiver是全局的监听器,所以它可以非常方便地实现系统中不同组件之间地通信。
例如:客户端于一个service(用startService())启动的服务通信,就可以借助于BroadcastReceiver来实现通信。
二、发送广播
1、需要创建BroadcastReceiver的Intent
2、需要为intent添加Action属性,intent.setAction(".........");
3、调用Context的sendBroadcast(Intent intent)(发送普通广播)或者sendOrderedBroadcast(Intent intent)(发送有序广播)。
其中普通广播是完全异步的,可同一时刻被所有接受者收到,消息传递的效率比较高。
其中有序广播,接收者将按照预先声明的优先级依次接收广播信息,优先级高的可以切断广播,阻止其向下传播(abortBroadcast()),其中设置优先级是在, <intent-filter......./>元素的android:priority属性中,数越大优先级越大,取值范围在-1000~1000中,也可以调用IntentFilter对象的setPriority()设置优先级。
收到消息的广播可以通过setResultExtras(Bundle )的方法将处理的结果传如Broadcast中,然后传递给下一个接收者,下一个接收者通过,Bundle bundle=getResultExtras(true)来获取上一个接收者存入的数据。
三、重写广播接收器:BroadcastReceive
重写BroadcastReceive的子类,继承BroadcastReceive
只需要重写onReceive(Context context,Intent intent)方法。
四:注册BroadcastReceive
有两种方法:
1、重写了BroadcastReceive的子类后,静态注册,在androidManifest.xml文件中静态注册:
<receiver android:name=".SmsReceiver.SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
2、重写了BroadcastReceive的子类后,在java代码中动态注册:
IntentFilter intentFilter=new IntentFilter(); //创建IntentFilter对象
intentFilter.addAction("android.totole"); //给IntentFilter对象添加action
SmsReceiver receiver=new SmsReceiver(); //接收者实例
registerReceiver(receiver,intentFilter); //注册广播接收器
五、接收系统广播信息:
六、本地广播
本地广播的几个优势:
1、只在自己的程序中发送广播,不但行数据的泄露
2、其他程序的广播无法送进我们的程序
3、本地广播比发送全局广播更有效
本地广播是要使用一个LocalBroadcastManager来对广播进行管理,并提供,发送广播,和注册广播接收器。
LocalBroadcastManager实例:是通过LocalBroadcastManager.getInstance(this)获取
发送广播:LocalBroadcastManager.sendBroadcast(intent) ;//发送
注册广播:LocalBroadcastManager.registerReceiver(localReceiver,intentFilter); //注册
实例:后台服务播放的音乐,前台发送广播给后台服务,服务收到消息,就开始播放或者其他动作,中间的信息传递通过广播来实现:
1、后台的service
public class MusicService extends Service {
MyReceiver receiver=new MyReceiver();
MediaPlayer mediaPlayer=new MediaPlayer();
private List<String> mMusicList=new ArrayList();
//定义音乐播放器,0x11代表没有播放,0x12代表正在播放,0x13代表暂停播放,0x14代表下一曲,0x15代表上一曲
int status=0x11;
int current=0;
MyBinder binder=new MyBinder();
class MyBinder extends Binder{
public void init(List<String> list){
mMusicList=list;
Toast.makeText(MusicService.this,"数据传输成功",Toast.LENGTH_SHORT).show();
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public void onCreate(){
super.onCreate();
//注册广播接受器,监听前台发过来的消息
IntentFilter filter=new IntentFilter();
filter.addAction(MainActivity.CTL_ACTION);
registerReceiver(receiver,filter);
//mediaPlayer注册监听器,监听是否播放完毕,如果播放发完毕,播放下一曲,并通知Activity更新ui
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
current++;
if(current>=mMusicList.size())
current=0;
//播放完一曲,播放下一曲,并发出广播Activity界面更新
Intent intent=new Intent(MainActivity.UPDATE_ACTION);
intent.putExtra("current",current);
intent.putExtra("status",status);
sendOrderedBroadcast(intent,null);
Toast.makeText(MusicService.this,"向前台发广播信息",Toast.LENGTH_SHORT).show();
//播放下一曲
preparedAndPlay(mMusicList.get(current));
}
});
}
//广播接受器,接受Activity界面传过来的消息
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(MusicService.this,"接收到前台的广播信息",Toast.LENGTH_SHORT).show();
int control=intent.getIntExtra("control",-1);
switch (control){
case 1:{ //前台Activity按下Start按钮
if(status==0x11){ //后台还处于没有播放音乐,按下Start按钮
//准备并播放
preparedAndPlay(mMusicList.get(current));
status=0x12;
}
else if (status==0x12){ //后台处于播放状态,按下Start按钮
//暂停
mediaPlayer.pause();
status=0x13;
}
else if(status==0x13){// 后台原来处于暂停状态,按下Start按钮
//播放
mediaPlayer.start();
status=0x12;
}
Toast.makeText(MusicService.this,"播放:"+mMusicList.get(current),Toast.LENGTH_SHORT).show();
break;
}
case 2:{ //前台Activity按下Stop按钮
if(status==0x12||status==0x13){ //后台如果正在播放或者暂停,按下Stop按钮
//停止播放
mediaPlayer.stop();
status=0x11;
}
break;
}
case 3:{ //前台Activity按下front按钮
current++;
if(current>=mMusicList.size()){
current=0;
}
preparedAndPlay(mMusicList.get(current));
status=0x14;
break;
}
case 4:{ //前台Activity按下next按钮
current--;
if(current<0) {
current = mMusicList.size() - 1;
}
preparedAndPlay(mMusicList.get(current));
status=0x15;
break;
}
default:
break;
}
abortBroadcast();
//发出广播通知activity更新ui
Intent intent1=new Intent(MainActivity.UPDATE_ACTION);
intent1.putExtra("update",status);
intent1.putExtra("current",current);
sendOrderedBroadcast(intent1,null);
Toast.makeText(MusicService.this,"向前台发广播信息",Toast.LENGTH_SHORT).show();
}
}
private void preparedAndPlay(String music){
try{
mediaPlayer.reset();
mediaPlayer.setDataSource(mMusicList.get(current));
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、在xml的界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.asus.musicplay.MainActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/list"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放"
android:id="@+id/Start"
android:layout_margin="5px"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂停"
android:layout_margin="5px"
android:id="@+id/Stop"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上一曲"
android:layout_margin="5px"
android:id="@+id/front"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下一曲"
android:layout_margin="5px"
android:id="@+id/next"/>
</LinearLayout>
</LinearLayout>
3、activity
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button Start=null;
private Button Stop=null;
private Button front=null;
private Button next=null;
private ListView list=null;
//数据
private List<String> mMusicList=new ArrayList();//前端
private List<String> mMusicList1=new ArrayList();//后台服务
//前台Activity按下按钮时,发出的广播信息 (也是后台服务的广播接受器,接受前台打过来的广播)
public static final String CTL_ACTION="CTL_ACTION";
//前台Activity接受后台服务发过来的广播信息 (也是后台向前台发送的广播信息)
public static final String UPDATE_ACTION="UPDATE_ACTION";
public int statu=0x11; //定义音乐播放器,0x11代表没有播放,0x12代表正在播放,0x13代表暂停播放,0x14代表下一曲,0x15代表上一曲
private static final String MUSIC_PATH=new String("/sdcard/");
private MusicService.MyBinder binder;
private ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
binder=(MusicService.MyBinder)iBinder;
Toast.makeText(MainActivity.this,"服务连接成功",Toast.LENGTH_SHORT).show();
binder.init(mMusicList1);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Start=findViewById(R.id.Start);
Stop=findViewById(R.id.Stop);
front=findViewById(R.id.front);
next=findViewById(R.id.next);
list=findViewById(R.id.list);
Start.setOnClickListener(this);
Stop.setOnClickListener(this);
front.setOnClickListener(this);
next.setOnClickListener(this);
if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
}else{
musicList();
}
//注册广播接受器,监听后台服务打过来的消息
ActivityReceive receive=new ActivityReceive();
IntentFilter filter=new IntentFilter();
filter.addAction(UPDATE_ACTION);
registerReceiver(receive,filter);
Intent intent=new Intent(this,MusicService.class);
bindService(intent,connection,BIND_AUTO_CREATE);
}
public void onRequestPermissionsResult(int requestCode,String []permissions,int []grantResults){
switch (requestCode){
case 1:{
if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
musicList();
}else{
Toast.makeText(this,"拒绝授权",Toast.LENGTH_SHORT).show();
}
}
break;
default:
}
}
public void musicList(){
File home=new File(MUSIC_PATH);
if(home.listFiles(new MusicFilter()).length>0){
for(File file:home.listFiles(new MusicFilter())) {
Log.i("TAG",file.getAbsolutePath());
mMusicList.add(file.getName());
mMusicList1.add(file.getPath());
}
}
ArrayAdapter<String> adapter=new ArrayAdapter<String>(MainActivity.this,R.layout.musicitem,mMusicList);
list.setAdapter(adapter);
}
@Override
public void onClick(View view) {
//界面Activity发出广播消息,后台服务的广播接受到消息,服务进行相应的播放
Intent intent=new Intent();
intent.setAction(CTL_ACTION);
switch (view.getId()){
case R.id.Start:{
intent.putExtra("control",1);
break;
}
case R.id.Stop:{
intent.putExtra("control",2);
break;
}
case R.id.front:{
intent.putExtra("control",3);
break;
}
case R.id.next:{
intent.putExtra("control",4);
break;
}
default:
break;
}
//发送消息
sendOrderedBroadcast(intent,null);
Toast.makeText(MainActivity.this,"向后台发广播信息",Toast.LENGTH_SHORT).show();
}
//
public class ActivityReceive extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(MainActivity.this,"接收到后台发广播信息",Toast.LENGTH_SHORT).show();
//获取Intent中的update消息,update代表播放状态
int update=intent.getIntExtra("update",-1);
int current=intent.getIntExtra("current",-1);
if(current>=0){
Toast.makeText(MainActivity.this,mMusicList.get(current)+"",Toast.LENGTH_SHORT).show();
}
//根据后台服务发送的广播信息,看播放的情况是什么(播放还是暂停),更新ui
switch (update){
case 0x11:
statu=0x11;
break;
case 0x12:
statu=0x12;
break;
case 0x13:
statu=0x13;
break;
case 0x14:
statu=0x14;
break;
case 0x15:
statu=0x15;
break;
default:
break;
}
abortBroadcast();
}
}
class MusicFilter implements FilenameFilter
{
public boolean accept(File dir,String name){
return (name.endsWith(".mp3"));
}
}
}