BroadcastReceiver所對應的廣播分兩類:無序廣播和有序廣播敛助。
無序廣播即為我們平時經(jīng)常使用的廣播,其主要是通過public abstract void sendBroadcast (Intent intent)方法進行發(fā)送盈魁,并通過intent傳遞數(shù)據(jù)贤牛。代碼示例如下:
Intent nonOrderIntent = new Intent();
nonOrderIntent.setAction(ACTION);
sendBroadcast(nonOrderIntent);
無序廣播會被注冊了的相應的感興趣(intent-filter匹配)接收,且順序是無序的急黎。如果發(fā)送廣播時有相應的權(quán)限要求健提,BroadCastReceiver如果想要接收此廣播琳猫,也需要有相應的權(quán)限。
無序廣播的廣播接收者不可以使用setResultData()方法和abortBroadcast()方法私痹,如果使用了會報錯脐嫂。 但是可以使用getResultData()方法,雖然不報錯紊遵,但是獲取到的數(shù)據(jù)為null账千。但是在一種<u>特殊情況</u>下,getResultData()方法能取到無序廣播傳遞的數(shù)據(jù)暗膜,下文會說明在什么情況下匀奏。
無序廣播不可以被攔截,不可以被終止桦山,不可以被修改,無序廣播任何接收者只要匹配條件都可以接收到醋旦,無優(yōu)先級問題恒水。
如果想通過無序廣播傳遞數(shù)據(jù),則可以調(diào)用intent.putExtra方法傳遞饲齐, 接收者可通過intent.get...接收钉凌,不可通過getResultData接收。
有序廣播主要是通過public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)方法進行發(fā)送捂人。代碼示例如下:
Intent intent = new Intent();
intent.setAction(ACTION);
sendOrderedBroadcast(intent, null, new Priority2BroadcastReceiver(), null, Activity.RESULT_OK, "MainActivity發(fā)送了一個有序廣播", null);
先介紹一下public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)方法
官網(wǎng)api的參數(shù)解釋:
Parameters
intent The Intent to broadcast; all receivers matching this Intent will receive the broadcast.
receiverPermission String naming a permissions that a receiver must hold in order to receive your broadcast. If null, no permission is required.
resultReceiver Your own BroadcastReceiver to treat as the final receiver of the broadcast.
scheduler A custom Handler with which to schedule the resultReceiver callback; if null it will be scheduled in the Context's main thread.
initialCode An initial value for the result code. Often Activity.RESULT_OK.
initialData An initial value for the result data. Often null.
initialExtras An initial value for the result extras. Often null.
第一個intent:不多說指定intent御雕,所有廣播接收者的匹配規(guī)則
第二個receiverPermission:指定廣播接收器的權(quán)限矢沿,一般自定義,不常用酸纲,可傳null捣鲸。
第三個resultReceiver:指定一個最終的廣播接收器,相當于finally功能闽坡,不論優(yōu)先級栽惶,最后都要接收一次廣播,而這一次收到的廣播為無序廣播(可以在BroadcastReceiver中通過boolean orderedBroadcast = isOrderedBroadcast()方法驗證)疾嗅,但是卻可以通過getResultData等方法取得數(shù)據(jù)外厂,這就是上面提到的特殊情況。
第四個scheduler:看英文沒怎么看懂什么意思代承,一般傳null汁蝶。
第五個initialCode:指定一個code,一般傳Activity.RESULT_OK论悴。
第六個initialData:傳一個字符串數(shù)據(jù)掖棉。對應的在BroadcastReceiver中通過String resultData = getResultData()取得數(shù)據(jù);通過setResultData("優(yōu)先級為3的setResultData的數(shù)據(jù)")修改數(shù)據(jù)意荤,將數(shù)據(jù)傳給下一個優(yōu)先級較低的BroadcastReceiver啊片;如果在優(yōu)先級較高的BroadcastReceiver中沒有使用setResultData修改數(shù)據(jù),那么優(yōu)先級較低的接收到的數(shù)據(jù)還是最原始的數(shù)據(jù)玖像,即initialData的值紫谷。
第七個initialExtras:傳一個Bundle對象,也就是可以傳多種類型的數(shù)據(jù)捐寥。對應的在BroadcastReceiver中通過Bundle bundle = getResultExtras(false)取得Bundle對象笤昨,然后再通過bundle的各種get方法取得數(shù)據(jù);通過setResultExtras()傳入一個修改過的bundle握恳,將該bundle對象傳給下一個優(yōu)先級較低的BroadcastReceiver瞒窒;如果在優(yōu)先級較高的BroadcastReceiver中沒有使用setResultExtras修改數(shù)據(jù),那么優(yōu)先級較低的接收到的數(shù)據(jù)還是最原始的bundle對象乡洼,即initialExtras的值崇裁。
有序廣播所對應的所有的receiver按照在intent-filter中設置的android:priority屬性依次執(zhí)行,android:priority表示優(yōu)先級束昵,值越大拔稳,其所對應的廣播接收者,越先接收到廣播锹雏。在android:priority相同的情況下巴比,如果廣播接收器是通過靜態(tài)注冊的,則接收到廣播的順序不確定,如果是動態(tài)注冊的轻绞,先注冊的將先收到廣播采记。
有序廣播可以被攔截,?可以在較高優(yōu)先級的接收器中通過abortBroadcast()攔截廣播政勃,這樣就會導致較低優(yōu)先級的接收器無法收到廣播了唧龄,但是sendOrderedBroadcast第三個參數(shù)指定的BroadcastReceiver還是會收到廣播的,而且能獲得數(shù)據(jù)稼病。
有序廣播可以通過原始intent.putExtra這種方式傳遞數(shù)據(jù)給BroadcastReceiver选侨,也能通過sendOrderedBroadcast方法的最后2個參數(shù)傳遞數(shù)據(jù),但是通過第一種方式傳遞的數(shù)據(jù)無法中途修改然走,通過第二種方式傳遞的可以通過上面參數(shù)說明中的方式進行修改援制。
具體驗證方式可通過如下代碼驗證以上結(jié)論:
MainActivity
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.tbc.hsx.testbroadcast.receiver.Priority2BroadcastReceiver;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String ACTION = "com.tbc.hsx.testbroadcast.MainActivity";
public static final String DATA = "data";
public static final String ORDER_DATA = "order_data";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
findViewById(R.id.send_broadcast_btn).setOnClickListener(this);
findViewById(R.id.send_ordered_broadcast_btn).setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
Handler handler = new Handler() {
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
}
};
@Override
public void onClick(View view) {
if (view.getId() == R.id.send_broadcast_btn) {
Intent nonOrderIntent = new Intent();
nonOrderIntent.setAction(ACTION);
sendBroadcast(nonOrderIntent);
} else if (view.getId() == R.id.send_ordered_broadcast_btn) {
Intent intent = new Intent();
intent.putExtra(DATA, "有序廣播通過intent.putExtra傳遞的數(shù)據(jù)");
intent.setAction(ACTION);
Bundle bundle = new Bundle();
bundle.putString(ORDER_DATA, "有序廣播通過bundle傳遞的數(shù)據(jù)");
sendOrderedBroadcast(intent, null, new Priority2BroadcastReceiver(), handler, Activity.RESULT_OK, "MainActivity發(fā)送了一個有序廣播", bundle);
}
}
}
Priority1BroadcastReceiver
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* Created by Doraemon
* Date: 16/4/27
* Time: 16:35
* Summary:優(yōu)先級為1的廣播接收器
*/
public class Priority1BroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String resultData = getResultData();//獲取有序廣播的數(shù)據(jù)
System.out.println("優(yōu)先級為1的接收到的廣播數(shù)據(jù)resultData---->" + resultData);
setResultData("優(yōu)先級為1的setResultData的數(shù)據(jù)");//修改有序廣播的數(shù)據(jù)
}
}
Priority2BroadcastReceiver
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.tbc.hsx.testbroadcast.MainActivity;
/**
* Created by Doraemon
* Date: 16/4/27
* Time: 16:35
* Summary:
*/
public class Priority2BroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
boolean orderedBroadcast = isOrderedBroadcast();
if (orderedBroadcast) {
System.out.println("優(yōu)先級為1的接收者接收到的是有序廣播");
} else {
System.out.println("優(yōu)先級為1的接收者接收到的是無序廣播");
}
Bundle bundle=getResultExtras(false);
if (bundle != null) {
String orderData = bundle.getString(MainActivity.ORDER_DATA);
System.out.println("Priority2BroadcastReceiver-------->" + orderData);
}
String resultData = getResultData();//獲取有序廣播的數(shù)據(jù)
System.out.println("優(yōu)先級為2的接收到的廣播數(shù)據(jù)resultData---->" + resultData);
setResultData("優(yōu)先級為2的setResultData的數(shù)據(jù)");//修改有序廣播的數(shù)據(jù)
}
}
Priority3BroadcastReceiver
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.tbc.hsx.testbroadcast.MainActivity;
/**
* Created by Doraemon
* Date: 16/4/27
* Time: 16:32
* Summary:
*/
public class Priority3BroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = getResultExtras(false);
if (bundle != null) {
String orderData = bundle.getString(MainActivity.ORDER_DATA);
System.out.println("Priority3BroadcastReceiver-------->" + orderData);
}
// bundle.putString(MainActivity.ORDER_DATA, "優(yōu)先級為3的接收者修改了bundle數(shù)據(jù)");
// setResultExtras(bundle);
boolean orderedBroadcast = isOrderedBroadcast();
if (orderedBroadcast) {
System.out.println("優(yōu)先級為3的接收者接收到的是有序廣播");
} else {
System.out.println("優(yōu)先級為3的接收者接收到的是無序廣播");
}
String resultData = getResultData();//獲取有序廣播的數(shù)據(jù)
System.out.println("優(yōu)先級為3的接收到的廣播數(shù)據(jù)resultData---->" + resultData);
setResultData("優(yōu)先級為3的setResultData的數(shù)據(jù)");//修改有序廣播的數(shù)據(jù)
// abortBroadcast();
}
}
AndroidManifest.xml(BroadcastReceiver注冊部分)
<receiver android:name=".receiver.Priority1BroadcastReceiver">
<intent-filter android:priority="1">
<action android:name="com.tbc.hsx.testbroadcast.MainActivity" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.Priority2BroadcastReceiver">
<intent-filter android:priority="2">
<action android:name="com.tbc.hsx.testbroadcast.MainActivity" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.Priority3BroadcastReceiver">
<intent-filter android:priority="3">
<action android:name="com.tbc.hsx.testbroadcast.MainActivity" />
</intent-filter>
</receiver>