
meta-data常見(jiàn)于我們使用第三方SDK時(shí),比如友盟統(tǒng)計(jì),比如訊飛SDK,配置appid會(huì)用到,而實(shí)際上,meta-data可做的遠(yuǎn)不止這些。在公司我的框架中某一功能是依賴meta-data的,今天就好好介紹一下這個(gè)看起來(lái)不起眼的家伙。
簡(jiǎn)介-meta是什么
meta-data是應(yīng)用的清單文件AndroidManifest.xml中application,activity,activity-alias,provider,receiver,service下的子標(biāo)簽,比intent-filter多些父標(biāo)簽.像友盟這些統(tǒng)計(jì)服務(wù)一般只需要一個(gè)AppID等,只需要定義在Application中,如果你想給某個(gè)組件添加meta-data,那么meta-data必須定義在其組件申明內(nèi)。
基礎(chǔ)使用
事實(shí)上,meta-data我們拿到的時(shí)候是一個(gè)Bundle,知道了這一點(diǎn),我們就可以不畏懼它了,不信你看。
public Bundle metaData;
先看一下友盟的應(yīng)用場(chǎng)景,在Application中定義APPID, 我們也可以直接給一個(gè)resource給meta-data
<application
....
<meta-data
android:name="jerey"
android:value="sdf123456">
</meta-data>
</application>
獲取Application中的meta-data方法:
ApplicationInfo appInfo = null;
appInfo = this.getPackageManager()
.getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
Bundle bundle = appInfo.metaData;
Log.i(TAG, "bundle.getString(jerey) : " + bundle.getString("jerey"));
可以看到打印為:
I/MainActivity: bundle.getString("jerey") : sdf123456
若我們像下面這種方式使用:
<string-array name="test1">
<item>test1_hello</item>
<item>test1_hello2</item>
</string-array>
<meta-data
android:name="test_array"
android:resource="@array/test1">
</meta-data>
在獲取時(shí),獲取到的是id,R.id的id,我們還需要getResource.get...去獲取。我們測(cè)試一下:
int id = bundle.getInt("test_array");
String[] aString = getResources().getStringArray(id);
for (int i = 0; i < aString.length; i++) {
Log.i(TAG, "onCreate: " + aString[i]);
}
logcat可以看到:
10-17 15:57:55.966 5247-5247/avatar.com.demos I/MainActivity: onCreate: test1_hello
10-17 15:57:55.966 5247-5247/avatar.com.demos I/MainActivity: onCreate: test1_hello2
既然知道了如何獲取Application中的參數(shù),那么其他的也如出一轍。
//在Activity應(yīng)用<meta-data>元素。
ActivityInfo info = this.getPackageManager()
.getActivityInfo(getComponentName(),PackageManager.GET_META_DATA);
info.metaData.getString("meta_name");
//在service應(yīng)用<meta-data>元素。
ComponentName cn = new ComponentName(this, ×××Service.class);
ServiceInfo info = this.getPackageManager().getServiceInfo(cn, PackageManager.GET_META_DATA);
info.metaData.getString("meta_name");
//在receiver應(yīng)用<meta-data>元素。
ComponentName cn = new ComponentName(context, ×××Receiver.class);
ActivityInfo info = context.getPackageManager().getReceiverInfo(cn, PackageManager.GET_META_DATA);
info.metaData.getString("meta_name");
擴(kuò)展應(yīng)用-配合PackageManager
舉一個(gè)擴(kuò)展應(yīng)用場(chǎng)景,我們都知道,Android系統(tǒng)的多應(yīng)用打開(kāi)功能,即比如你有三個(gè)瀏覽器,那么我們發(fā)送一個(gè)url的時(shí)候,如果沒(méi)有默認(rèn)瀏覽器,會(huì)讓我們選擇一個(gè)瀏覽器。
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
Uri content_url = Uri.parse("https://www.baidu.com");
intent.setData(content_url);
startActivity(intent);
現(xiàn)在我們喜歡,彈出的選擇界面多一點(diǎn)介紹,每個(gè)能夠接收這個(gè)Action的應(yīng)用都能夠做一下自我介紹,在選擇的界面上下面顯示小字提示。
這個(gè)需求,我們肯定不是說(shuō)提前記住每個(gè)應(yīng)用的介紹,并且這種肯定是要控制反轉(zhuǎn),即每個(gè)應(yīng)用單獨(dú)提供自己的介紹的。這個(gè)時(shí)候meta-data就起到作用了,我們可以讓每個(gè)做公共跳轉(zhuǎn)的應(yīng)用的Activity都添加一個(gè)叫title的meta-data,那么我們就能獲取到它,怎么獲取呢,看下面操作,(我居然能突然奇想到這個(gè)例子,OMG)
操作1,利用PackageManager查詢Intent的功能,這個(gè)功能常用來(lái)判斷一個(gè)Intent是否有接收者的,比如從相冊(cè)選擇圖片,為了防止沒(méi)有相冊(cè)往往會(huì)做這樣的判斷。
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, PackageManager.GET_ACTIVITIES);
拿到List<ResolveInfo> activities,接下來(lái)干什么?
for (ResolveInfo info : activities) {
ActivityInfo mActivityInfo = info.activityInfo;
mActivityInfo.packageName;
mActivityInfo.name;
Bundle data = info.activityInfo.metaData;
}
我們拿到了應(yīng)用的ActivityInfo,以及對(duì)應(yīng)的meta-data,上述需求基本上算沒(méi)有難度了。
像上述拿其他應(yīng)用的meta-data,看上去沒(méi)有什么應(yīng)用場(chǎng)景,但是有些時(shí)候可以干很多出奇的事情的。