android四大组件(3)(BroadcastReceiver)

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


猜你喜欢

转载自blog.csdn.net/wenge1477/article/details/81386797