Android開發歷程_14(廣播機制)


 

     廣播機制按照字面理解就是廣於播之,在計算機網絡中這個詞比較常見,它的意思是說發送端把信息發送出去,是以廣播的方式發送出去,該信息可以同時被多個接收端介紹,當然接收端也可以不接收,另外接收端介紹到這信息后怎么處理廣播的發送端也是不用考慮的。因此廣播機制還是挺有用的,利用廣播信息可以為觸發的一些事件發送消息。Android中的廣播機制可以參考mars老師的這張圖片:

  

     如圖所示,有多個廣播接收者在android中注冊過,當一個事件產生后,它可以發送一個廣播信息,然后這些接收者來接收該信息。廣播接收者的實現一般是寫成一個類,該類繼承android提供的類BroadcastReceiver,並且我們需要復寫該類的onCreate方法,因為我們需要在該方法中實現接收到信息后的處理過程。

 

  下面通過2個簡單的例子來學會怎樣在andorid中使用廣播信息,其實在文章Android開發歷程_13(Service的使用)中已經使用過廣播機制,即在servier下發送廣播信息,主activity中接收該信息來更新UI。在那個程序中使用的是intentFilter這個類,然后在activity中使用registerReceiver函數來發送廣播信息,這些代碼的實現都是在java語句中實現。這是第一種注冊廣播消息的方法,另外一種方法是在AndroidMainifest.xml文件中注冊。下面2個例子就分別介紹了這2中方法。

  在介紹這2個例子之前,我們先來看看這2種注冊方法的去別:

  1. 在Manifest.xml文件中注冊的話,因為需要一個android:name設置,所以我們繼承BroadcastReceiver的類需要單獨作為一個類文件出現,而在java代碼中注冊,我們可以使用一個內部類就可以了。

     2.  在Mainfest.xml文件中注冊過的BroadcastReceiver,即使我們對應的程序已經關閉,但是只要我們的系統(比如說手機,平板)開啟,這該BroadcastReceiver依然處於活動狀態,依然可以接受到廣播信息。

     3. 如果我們需要實時監測某個廣播信息,則可以采用在Mainfest.xml中進行注冊,但如果我們用廣播信息來更新activity的UI,則應該采用在java代碼中進行注冊。

 

 

     例一:

     采用在AndroidMainifest.xml文件中注冊BroadcastReceiver。

     首先發送端還是先建立一個intent,然后采用intent的setAction方法設置接收器的action類型,最后在activity中啟動broadcast,即使用函數sendBroadcast(intent)。

 

     實驗說明:

     在com.example.broadcast1包下新建一個TestReceiver類,該類繼承BroadcastReceiver,繼承的這個類的對象的生命周期只有在其接受到了廣播信息的時候才存在,當其接受完了廣播信息且處理完信息內容后,該對象也就結束了。如果下次又有廣播信息被接受,則該對象又重新啟動一遍。 同時,我們在TestReceiver這個類的構造函數中打印"TestReceiver"語句,在onReceive方法中打印"OnReceiver"信息。

     主界面中有一個按鈕,按鈕按下時就發生廣播消息。主界面啟動時打印"onCreate"。

     下面是當按下一次start按鈕后的輸出信息:

   

     由此可見,廣播信息被接受成功了。

        

     實驗主要代碼及注釋(附錄有實驗工程code下載鏈接):

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcast1"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver 
            android:name=".TestReceiver">
            <intent-filter>
                <action android:name="android.intent.action.EDIT"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

 

MainActivity.java:

package com.example.broadcast1;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

    private Button start = null;
    private TextView text = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        System.out.println("onCreate");
        start = (Button)findViewById(R.id.start);
        start.setOnClickListener(new MyStartOnClickListener());
        text = (TextView)findViewById(R.id.text);
    }

    public class MyStartOnClickListener implements OnClickListener
    {

        public void onClick(View arg0) {
            // TODO Auto-generated method stub
        //    TestReceiver tr = new TestReceiver();
            Intent intent = new Intent();//采用intent發送數據
            intent.setAction(Intent.ACTION_EDIT);//只發送給action為ACTION_EDIT的對象
            MainActivity.this.sendBroadcast(intent);//通過廣播方式發送該intent,只有特定
                                                    //action的接收者才能收到該廣播信息
        }
        
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

 

TestReceiver.java:

package com.example.broadcast1;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Button;
import android.widget.TextView;

import com.example.broadcast1.R;


public class TestReceiver extends BroadcastReceiver{
    
    private Button start = null;
    private TextView text = null;    
    
    public TestReceiver()
    {
        System.out.println("TestReceiver");
        
    }
    @Override
    public void onReceive(Context arg0, Intent arg1) {
        System.out.println("OnReceiver");
        
    }
    
}

 

 

 

     例二:

     這個例子主要是學習在java代碼中注冊broadcastReceiver,通過接收一個發送短信的廣播,順便學習下在android中跟發送和接收短信有關的操作.

 

  實驗說明

     和上面例子一樣,我們同樣寫一個類,該類繼承BroadcastReceiver,在該類的onReceive方法中讀取接收到的短信內容,並將短信內容打印到后台。在主activity中我們注冊一個廣播接收器,設置的action過濾為"android.provider.Telephony.SMS_RECEIVED",即只有具備該action的廣播接收器才能給接收到短信。發送短信采用的是DDMS來模擬的,即該短信的發送是由另外的程序執行的,我們也可以理解為系統發出,因此廣播信息的發送在這個例子中不用我們用代碼來實現。DDMS發送出來的短信息是通過intent發送的,intent里面就自帶了名為"android.provider.Telephony.SMS_RECEIVED"的action,所以我們的接收器中intent過濾器中也是設置的該aciton,因此是可以收到短信的。

     要使自己寫的android程序能夠收到短信息來臨的廣播,則不管是在java程序中注冊broadcastReceiver還是在manifest.xml中注冊,在manifest.xml文件中必須添加一句代碼:

<uses-permission android:name="android.permission.RECEIVE_SMS"/>並且該代碼是和application平級的,也就是說是manifest的直接子標簽.如果沒有改句,即使程序中注冊過廣播接收,同樣也收不到短信的。

     用broadcastReceiver讀取短信內容的代碼基本上可以固定,在onReceive()方法中實現的,代碼如下:

     單擊一次Start Broadcast按鈕后,在DDMS中發送一條消息,然后再單擊Stop Broadcast按鈕后的,后台顯示如下:

  

 

     實驗主要部分代碼(附錄有實驗工程code下載鏈接):

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcast2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        >
          
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>      
        <receiver 
             android:name=".SMSReceiver">
            <!--  
             <intent-filter>
                 <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
                 
              </intent-filter>
              -->
        </receiver>
        
    </application>

</manifest>

 

MainActivity.java:

package com.example.broadcast2;

import android.app.Activity;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

    private Button start = null;
    private Button stop = null;
    private SMSReceiver sms_receiver = null;
    private static final String SMS_ACTION = "android.provider.Telephony.SMS_RECEIVED";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        start = (Button)findViewById(R.id.start_broadcast);
        start.setOnClickListener(new StartOnClickListener());
        stop = (Button)findViewById(R.id.stop_broadcast);
        stop.setOnClickListener(new StopOnClickListener());
    }

    class StartOnClickListener implements OnClickListener
    {

        public void onClick(View v) {
            // TODO Auto-generated method stub
            sms_receiver = new SMSReceiver();
            IntentFilter intent_filter = new IntentFilter();
            intent_filter.addAction(SMS_ACTION);
            MainActivity.this.registerReceiver(sms_receiver, intent_filter);
            System.out.println("Start Broadcast!");
        }
        
    }
    
    class StopOnClickListener implements OnClickListener
    {

        public void onClick(View v) {
            // TODO Auto-generated method stub
            MainActivity.this.unregisterReceiver(sms_receiver);
            System.out.println("Stop Broadcast!");
        }
        
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

 

SMSReceiver.java:

package com.example.broadcast2;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;

public class SMSReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        System.out.println("receive message");
        //獲得intent中的bundle
        Bundle bundle = intent.getExtras();
        //該bundle中有個名為“pdus”的鍵值對
        Object[] myOBJpdus = (Object[])bundle.get("pdus");
        //新建一個SmsMessage數組,用於存儲消息內容的
        SmsMessage[] messages = new SmsMessage[myOBJpdus.length];
        System.out.println(messages.length);//一條短信的長度為1
        for(int i = 0; i < messages.length; i++)
        {
            //輸入內容到messages數組
            messages[i] = SmsMessage.createFromPdu((byte[])myOBJpdus[i]);
            System.out.println(messages[i].getDisplayMessageBody());
        }
    }
    
}

 

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >


    <Button 
        android:id="@+id/stop_broadcast"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/stop_broadcast"
        android:layout_alignParentBottom="true"
        />
    <Button 
        android:id="@+id/start_broadcast"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/start_broadcast"
        android:layout_above="@id/stop_broadcast"
    />

</RelativeLayout>

 

 

     總結:android中的廣播機制可以由2種方法來注冊,每種方法的應用領域不同,我們應該根據我們的需求來選擇。

 

 

     參考資料:

     http://www.mars-droid.com/bbs/forum.php

 

 

     附錄:

     實驗工程code下載

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM