安卓ComponentName简介及使用

目录


一、ComponentName是什么?

ComponentName,顾名思义,就是组件名称,用于表示Android应用程序组件的名称。在Android开发中,每个应用程序组件(如Activity、Service、BroadcastReceiver等)都有一个唯一的组件名称,用于标识该组件在Android系统中的位置。

ComponentName类的主要作用是用于创建和管理Android应用程序组件的名称。

通过ComponentName对象,可以获取组件的包名和类名,还可以比较两个ComponentName对象的大小关系。

同时,ComponentName类还实现了Parcelable接口,可以在不同组件之间传递ComponentName对象。

在Android开发中,ComponentName类通常用于与Android系统进行交互,如启动其他应用程序的组件、获取应用程序组件的信息等。

通过ComponentName类,开发者可以方便地操作和管理Android应用程序组件的名称,实现更灵活的应用程序设计。


二、类分析

java 复制代码
public final class ComponentName implements Parcelable, Cloneable, Comparable<ComponentName> {

由于实现了Parcelable、Cloneable和Comparable< ComponentName>接口,ComponentName类具有了序列化、克隆和比较功能。

2.1 构造方法

java 复制代码
   public ComponentName(@NonNull String pkg, @NonNull String cls) {
        if (pkg == null) throw new NullPointerException("package name is null");
        if (cls == null) throw new NullPointerException("class name is null");
        mPackage = pkg;
        mClass = cls;
    }

    public ComponentName(@NonNull Context pkg, @NonNull String cls) {
        if (cls == null) throw new NullPointerException("class name is null");
        mPackage = pkg.getPackageName();
        mClass = cls;
    }

    public ComponentName(@NonNull Context pkg, @NonNull Class<?> cls) {
        mPackage = pkg.getPackageName();
        mClass = cls.getName();
    }

public ComponentName(@NonNull String pkg, @NonNull String cls)

通过给定的包名和类名创建一个新的ComponentName对象。

如果包名或类名为null,则会抛出NullPointerException异常。

参数:

pkg:包名

cls:类名
public ComponentName(@NonNull Context pkg, @NonNull String cls)

通过给定的Context对象和类名创建一个新的ComponentName对象。

从Context对象中获取实际的包名。

如果类名为null,则会抛出NullPointerException异常。

参数:

pkg:实现组件的包的Context对象

cls:类名
public ComponentName(@NonNull Context pkg, @NonNull Class<?> cls)

通过给定的Context对象和Class对象创建一个新的ComponentName对象。

从Context对象中获取实际的包名,从Class对象中获取实际的类名。

参数:

pkg:实现组件的包的Context对象

cls:所需组件的Class对象

三个构造方法提供了不同的方式来创建ComponentName对象,开发者可以根据需要选择合适的构造方法来实例化ComponentName对象。通过这些构造方法,可以方便地创建表示Android应用程序组件的名称的ComponentName对象,并在应用程序中进行相关操作。

2.2 重点方法

java 复制代码
	 // 获取包名
    public @NonNull String getPackageName() {
        return mPackage;
    }

    // 获取类名
    public @NonNull String getClassName() {
        return mClass;
    }
    //该方法用于获取组件的短类名,即去除包名后的类名部分。
    public String getShortClassName() {
    if (mClass.startsWith(mPackage)) {
        int PN = mPackage.length();
        int CN = mClass.length();
        if (CN > PN && mClass.charAt(PN) == '.') {
            return mClass.substring(PN, CN);
        }
    }
    return mClass;
    }
    
    //通过createRelative()方法,可以根据给定的包名和类名创建一个相对的ComponentName对象。
	   public static @NonNull ComponentName createRelative(@NonNull String pkg, @NonNull String cls) {
	    if (TextUtils.isEmpty(cls)) {
	        throw new IllegalArgumentException("class name cannot be empty");
	    }
	
	    final String fullName;
	    if (cls.charAt(0) == '.') {
	        // Relative to the package. Prepend the package name.
	        fullName = pkg + cls;
	    } else {
	        // Fully qualified package name.
	        fullName = cls;
	    }
	    return new ComponentName(pkg, fullName);
	 }

三、ComponentName的使用

ComponentName实例化组件

第一个参数是要启动应用的包名称,这个包名称是指清单文件中列出的应用的包名称:

第二个参数是你要启动的Activity或者Service的全称(包名+类名),代码如下:

启动一个Activity:

java 复制代码
   Intent intent = new Intent();
   intent.setComponent(new ComponentName("com.android.henrytest", "com.android.henrytest.MainActivity"));
   startActivity(intent);

启动一个Service:

java 复制代码
	Intent it = new Intent();
	it.setComponent(new ComponentName("com.example.otherapp",
			"com.example.otherapp.MyService"));
	startService(it);

注意:

如果要启动的其他应用的Activity不是该应用的入口Activity,那么在清单文件中,该Activity节点一定要加上android:exported="true",表示允许其他应用打开,对于所有的Service,如果想从其他应用打开,也都要加上这个属性:

xml 复制代码
        <service
            android:name="com.example.otherapp.MyService"
            android:exported="true" >
        </service>
 
        <activity
            android:name="com.example.otherapp.MainActivity2"
            android:exported="true" >
        </activity>

对于除了入口Activity之外的其他组件,如果不加这个属性,会抛出"java.lang.SecurityException: Permission Denial."异常

入口Activity不需要加此属性的原因是:

包含了过滤器的组件,意味着该组件可以提供给外部的其他应用来使用,它的exported属性默认为true,相反,如果一个组件不包含任何过滤器,那么意味着该组件只能通过指定明确的类名来调用,也就是说该组件只能在应用程序的内部使用,在这种情况下,exported属性的默认值是false。

xml 复制代码
        <activity
            android:name="com.android.henrytest.iccpanelActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data
                android:name="meta_act"
                android:resource="@string/app_name" />
        </activity>
相关推荐
小灰灰__11 分钟前
IDEA加载通义灵码插件及使用指南
java·ide·intellij-idea
夜雨翦春韭14 分钟前
Java中的动态代理
java·开发语言·aop·动态代理
程序媛小果35 分钟前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
追风林40 分钟前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
芒果披萨1 小时前
El表达式和JSTL
java·el
无极程序员1 小时前
PHP常量
android·ide·android studio
duration~2 小时前
Maven随笔
java·maven
zmgst2 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD2 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp2 小时前
Java:数据结构-枚举
java·开发语言·数据结构