一、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")); } } }