ComponentName的使用

ComponentName是安卓提供给我们的通过A应用启动B应用的一个类,与Intent同位于Android.content包下,这个类主要用来定义可见一个应用程序组件,例如:Activity,Service,BroadcastReceiver或者ContentProvider。
这是ComponentName的构造函数:ComponentName(String pkg,String cls)
在Android中详细描述一个组件,我们需要知道该组件所在的应用包名,也就是在AndroidManifest.xml文件中manifest根结点下的package=“com.XXXXX.XXXXX",还有组件在应用程序中的完整路径名,拿Activity来说,也就是activity节点中name属性的值,如

mActivityName = "com.XxX.XXX.activity.diagnose.DiagnoseActivity"

所以ComponentName可以用来封装一个组件的应用包名和组件的名字

我们已经知道,在Android中组件之间的交流往往使用意图(Intent)来完成的,那么在Intent中有一个方法可以封装一个ComponentName,最后我们在使用意图去完成我们需要实现的功能。下面来讲一下ComponentName如何使用。

Android 开发有时需要在一个应用中启动另一个应用,比如Launcher加载所有的已安装的程序的列表,当点击图标时可以启动另一个应用。一般我们知道了另一个应用的包名和MainActivity的名字之后便可以直接通过如下代码来启动(其中className是指完整的类名):
启动目标APP的主页面

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);            
ComponentName cn = new ComponentName(packageName, className);            
intent.setComponent(cn);
startActivity(intent);

启动目标APP的内部普通页面

      ComponentName cn = new ComponentName(mPackageName, mActivityName);
        try {
            Intent intent = new Intent();
            Bundle bundle = new Bundle();
            bundle.putString("type", "1");//传递值
            intent.putExtras(bundle);
            intent.setComponent(cn);
            startActivityForResult(intent, REQUEST_ID);//等待目标页面返回的结果
        } catch (Exception e) {
            e.printStackTrace();
        }

但是有的时候,我们一般都不知道应用程序的启动Activity的类名,而只知道包名,我们可以通过ResolveInfo类来取得启动Acitivty的类名。

    private void openApp(String packageName) {
        PackageInfo pi = getPackageManager().getPackageInfo(packageName, 0);

        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        resolveIntent.setPackage(pi.packageName);

        List<ResolveInfo> apps = pm.queryIntentActivities(resolveIntent, 0);

        ResolveInfo ri = apps.iterator().next();
        if (ri != null) {
            String packageName = ri.activityInfo.packageName;
            String className = ri.activityInfo.name;

            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);

            ComponentName cn = new ComponentName(packageName, className);

            intent.setComponent(cn);
            startActivity(intent);
        }
    }

Android:exported

     一个activity是否能被其他app的组件启动– “true”能,“false”不能。如果是“false”,这个activity只能被相同app的组件启动,或者是相同user ID的app的组件启动。

注意

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

        <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不用添加这个属性就可以被其他应用启动呢?我们来看一段入口Activity的注册代码:

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

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

转载自:https://blog.csdn.net/u012532559/article/details/52766348
https://blog.csdn.net/u012702547/article/details/49557905/

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值