Android-----AndroidManifests.xml 之meta-data

一、概念

meta-data:元数据、文件元数据。主要用来定义一些组件相关的配置值。

metadata是一组供父组件使用的名值对(name-value pair),一个组件元素可以包含任意数量的meta-data子元素。这些子元素的值存放在一个 Bundle 对象中,组件可以通过 PackageItemInfo.metaData 字段访问这些数据。AndroidManifests.xml下的meta-data则是对外界开放的,是向系统注册的信息,系统及外界是可以通过PackageInfo相关API获取到meta-data的信息。

1.1 语法

xml 复制代码
<meta-data android:name="string"
               android:resource="resource specification"
               android:value="string" />

标签<meta-data>是提供组件额外的数据用的,它本身就是一个键值对,可以自定义名称和值。
它可以包含在以下组件当中:
 	<activity>
    <activity-alias>
    <application>
    <provider>
    <receiver>
    <service> 

1.2 属性

  • android:name 数据项名称
    为了确保名称的唯一性,可使用 Java 风格的命名规则 --- 如:"com.example.project.activity.fred"。
  • android:resource 资源 ID
    对某个资源的引用。赋值为资源 ID 。 通过 Bundle.getInt() 方法可以从 meta-data Bundle 中读取该资源 ID。
  • android:value 数据项值
    赋给数据项的值。 下表列出了可赋予的数据类型、组件用 Bundle 对象获取该类值的方法:
Bundle 方法 类型
getString() 字符串值:(/)作为转义字符---比如"\n"、"\uxxxxx"表示 Unicode 字符
getInt() 资源ID 整数值:比如"100" 颜色值:格式为"#rgb"、"#argb"、"#rrggbb"或"#aarrggbb"
getBoolean() 布尔型值:"true"或"false"
getFloat() 浮点型值:比如"1.23"

二、 使用说明

普通类型的值:通过 value 属性来给定。

资源 ID 的值:必须用 resource 属性来指定。

定义资源

xml 复制代码
<string name="x_key">resource key</string>
//R
public static final int ic_launcher=0x7f020000;

定义metadata

xml 复制代码
<meta-data
    android:name="com.xesam.key_1"
    android:value="x_key" />
<meta-data
    android:name="com.xesam.key_2"
    android:value="@string/x_key" />
<meta-data
    android:name="com.xesam.img"
    android:resource="@drawable/ic_launcher" />
    <!--保存的是对应的Id,而不是保存的Id对应的资源-->

那么有:

java 复制代码
metadata.getString("com.xesam.key_1") ==> "x_key"
metadata.getString("com.xesam.key_2") ==> "resource key"
metadata.getInt("com.xesam.img")      ==> 0x7f020000

强烈建议不要使用多个独立的 部分定义数据。 如果有比较复杂的数据需要和某个组件关联,请把它们作为资源存储,并用 resource 属性将资源 ID 告知组件。

2.1 使用问题

xml 复制代码
<meta-data
    android:name="com.xesam.key_1"
    android:value="000" />

类似这样的值如果使用bundle.getString()的话是不起作用的,因为Bundle中使用的是形如:

java 复制代码
return (String) o;在这里插入代码片

代码获取一个StringValue值的,但是在将metadata包装成bundle的时候,"000"被解析成整数0,

因此bundle.getString("com.xesam.key_1")返回的是(String)0,显然,java是不允许这样的,因此最后得到的是null。 话说android为什么不是用String.valueOf()或者obj.toString()呢?

为了避免这种情况:

  1. 可以在形如000的字符串前面放个\0空字符,强迫android按照字符串解析000。
  2. 在资源文件中指定需要的值,然后在metadata的value中引用此值。

三、 具体应用场景解析

展示了meta-data元素在activity、application 、service和receiver元素中的读取方法

之前提到Meta-data中的内容会被收集到一个Bundle对象中,并且提供给组件的PackageItemInfo.metaData属性字段。可以通过调用PackageItemInfo 对象的metaData属性获得。而中ActivityInfo、ServiceInfo、 ApplicationInfo都是直接或间接继承自PackageItemInfo。

获取相应的PackageItemInfo值的时候要注意:

1 AppliacationInfo需要传递包名,

2 其他的传递ComponentName,所以需要构造一个 ComponentName对象,而不是使用getComponentName()方法。

getComponentName()方法返回的是当前组件。可能获取Meta-data值得地方不在对应的组件中。

AndroidMainfest.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <!--Application的MetaData的配置-->
        <meta-data android:name="applicationMetadataKey" android:value="applicationMetadataValue"/>
        <activity android:name=".MainActivity" android:exported="true">
        	<!--注意:targetSdkVersion大于等于SDK 31(也就是Android 12)时,如果Activity配置了Intent-filter,必须也同时配置exported属性,否则编译失败。-->
            <!--Activity的MetaData的配置-->
            <meta-data android:name="activityMetadataKey" android:value="activityMetadataValue"/>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".MainReceiver">
            <!--Receiver的MetaData的配置-->
            <meta-data android:name="receiverMetadataKey" android:value="receiverMetadataValue"/>
        </receiver>
        <service android:name=".MainService">
            <!--Service的MetaData的配置-->
            <meta-data android:name="serviceMetadataKey" android:value="serviceMetadataValue"/>
        </service>
    </application>

</manifest>

MainActivity.java

java 复制代码
package com.example.myapplication;

import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView result;
    private Context mContext;
    private ComponentName componentName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        componentName = this.getComponentName();
        result = (TextView) findViewById(R.id.result);
        findViewById(R.id.app).setOnClickListener(this);
        findViewById(R.id.act).setOnClickListener(this);
        findViewById(R.id.rec).setOnClickListener(this);
        findViewById(R.id.ser).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.app){
            try {
                ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(mContext.getPackageName(), PackageManager.GET_META_DATA);
                String appMV = appInfo.metaData.getString("applicationMetadataKey");
                result.setText(appMV);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
        }
        else if(v.getId() == R.id.act){
            try {
                ActivityInfo actInfo = mContext.getPackageManager().getActivityInfo(componentName, PackageManager.GET_META_DATA);
                String actMV = actInfo.metaData.getString("activityMetadataKey");
                result.setText(actMV);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
        }
        else if(v.getId() ==  R.id.rec){
            ComponentName recCn = new ComponentName(mContext, MainReceiver.class);
             try {
                 ActivityInfo recInfo = mContext.getPackageManager().getReceiverInfo(recCn, PackageManager.GET_META_DATA);
                 String recMV = recInfo.metaData.getString("receiverMetadataKey");result.setText(recMV);
             } catch (PackageManager.NameNotFoundException e) {
                 e.printStackTrace();
             }
        } else if (v.getId() ==  R.id.ser) {
            ComponentName serCn = new ComponentName(mContext, MainService.class);
            try {
                ServiceInfo serInfo = mContext.getPackageManager().getServiceInfo(serCn, PackageManager.GET_META_DATA);
                String serMV = serInfo.metaData.getString("serviceMetadataKey");
                result.setText(serMV);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

转载链接

https://blog.csdn.net/xuangelouzhu/article/details/113661113

相关推荐
恋猫de小郭1 小时前
Flutter 发布官方 Skills ,Flutter 在 AI 领域再添一助力
android·前端·flutter
Kapaseker6 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴6 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭16 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab17 小时前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe1 天前
Now in Android 架构模式全面分析
android·android jetpack
二流小码农1 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos
鹏程十八少1 天前
4.Android 30分钟手写一个简单版shadow, 从零理解shadow插件化零反射插件化原理
android·前端·面试
Kapaseker1 天前
一杯美式搞定 Kotlin 空安全
android·kotlin
三少爷的鞋1 天前
Android 协程时代,Handler 应该退休了吗?
android