1. 程式人生 > >android四大元件(3)(BroadcastReceiver)

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