了解Intent(中)

Intent的构成

Intent可以带有action,data(由URI表达),extra data(key/value map,键值对),指定的类名(成为component name)。一个intent至少携带上述的一个内容。

Action。Action名,在上一笔记中已经给出两种例子,一种是系统自带的,如Intent.ACTION_DAIL,一种是开发者通过AndroidManifest.xml进行注册的,在创建intent时给出:Intent intent=new Intent(String action_name);。action_name字符串的名字前缀是类名。

Data。由不同action决定有效的URI的格式。intent.setData(Uri.parse(”xxxxxx”));。被唤起的activity可以同activity.getIntent()来获得intent,然后通该intent的getData()来获取数据。

//触发方。 
Intent i = new Intent(actionName);
String uriStr = "wei://www.flowingflying.com";
i.setData(Uri.parse(uriStr));
this.startActivity(i);


//被触发方。需要在AndroidManifest.xml中在intent-filter中注册data信息,后文详细说明
Intent intent = this.getIntent();
String data = intent.getData();

通用的action即数据传递。Action和唤起的并非是一对一的,例如Intent.ACTION_VIEW根据data,唤起不同的应用。这种一对多,也就是通用的action,在manifest中注册时,需要声明数据(URI)的要求。具体可以参考:http://developer.android.com/guide/topics/manifest/data-element.html。ACTION_VIEW是通过schema进行区分。通过class名字、action名字等方式进行指定的称为explicit intent,可以一对多的称为implicit intent。

<activity......>
    <intent-filter>
 
         <action android:name="android.intent.action.VIEW" />
         <data android:scheme="http"/>
         <data android:scheme="https"/>

    </intent-filter>
</activity>

如果我们自己的intent要传递data,也必须要在manifest中注册data,否则intent会唤起失败,报告ActivityNotFoundException的异常。

比较常用的还有MIME type,例如注册<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />表示要查看notes的集合(即目录),而注册<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />则表示查看具体item,即查看具体的note。

扩展数据(Extra data)传递。uri的方式限制了信息的传递量。Extra的格式key/value对,key名字通常以包名开头,而value可以是任何基础数据类型,或者是实现android.os.Parcelable的对象。

在IntentTestDemo.java(通过intent i唤起IntentBasicViewActivity)通过下面传递extra数据。
1、extra数据以bundle的方式在intent中存放,如果已经有bundle,将新的键值对加入其中,如果没有bundle,则创建一个。未来确保key的唯一性
2、key名通常以包名开头,本例以常量方式,实际为:cn.flowingflying.android.pro.extra.string。
3、下面是最最简单据类型,还可以是array,例如putExtra(String name, int[] values);
      可以是Serializable对象,如putExtra(String name, Serializable value);以及Parcelable对象,如putExtra(String name,Parcelable value); 。
      可以将bundle进行传递,如putExtra(String name, Bundle value);,
      可以将Intent进行传递,如putExtra(String name, Intent anotherIntent);
      可以支持Array list:如putIntegerArrayListExtra(String name, ArrayList arrayList); putParcelableArrayListExtra(String name, ArrayList arrayList);和putStringArrayListExtra(String name, ArrayList arrayList)
     【注意】在intent中传递的不是reference(指针),而是copy一份,我们修改对象,并不会影响已经copy进intent中bundle的数据,这点需要非常注意。

i.putExtra(IntentBasicViewActivity.EXTRA_FLOWINGFLYING_STRING, "Hello, Intent! ");

在IntentBasicViewActivity.java中通过以下代码获取extra数据。
Intent intent = this.getIntent();
Bundle b = intent.getExtras(); 
String s =  b.getString(EXTRA_FLOWINGFLYING_STRING));

Android系统有已定义的key值,具体参见http://developer.android.com/reference/android/content/Intent.html#EXTRA_ALARM_COUNT

使用Component来唤起Activity

之前例子,我们通过action name来唤起Activity。对于explicit intent,即明确指定调用哪个activity,可以通过给出该Component的的package name和class name来进行调用。下面我们试验采用四种类似的方式进行调用,这四种方式本质没有区别。

private void basicTest1(){
    Intent intent = new Intent();
   //方式1:setComponent(ComponentName name);
    intent.setComponent(new ComponentName("cn.flowingflying.android.pro",
                                                                                 "cn.flowingflying.android.pro.IntentBasicViewActivity"));
    startActivity(intent);
}

//要写完整的class Name,不能写IntentBasicViewActivity或者.IntentBasicViewActivity,否则报告找不到Activity的错误
private void basicTest2(){
    Intent intent = new Intent(); 
    //方式2:setClassName(String packageName, String classNameInThatPackage); 
   intent.setClassName("cn.flowingflying.android.pro",   
                                       "cn.flowingflying.android.pro.IntentBasicViewActivity");

    startActivity(intent);
}
//要写完整的class Name,不能写IntentBasicViewActivity或者.IntentBasicViewActivity,否则报告找不到Activity的错误
private void basicTest3(){
    Intent intent = new Intent();
   //方式3:setClassName(Context context, String classNameInThatContext);
    intent.setClassName(this,"cn.flowingflying.android.pro.IntentBasicViewActivity");
    startActivity(intent);
}

private void basicTest4(){
    Intent intent = new Intent();
    //方式4:setClass(Context context, Class classObjectInThatContext);
   intent.setClass(this,IntentBasicViewActivity.class);
    startActivity(intent);
}

Intent的Category属性

在AndroidManifest.xml中,我们可以设置intent的category,例如:

<activity ……>
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

在应用启动是,将寻找Activity标记为CATEGORY_LAUNCHER来加载。Android定义了多个Category,具体可以在http://developer.android.com/reference/android/content/Intent.html#CATEGORY_ALTERNATIVE中查阅。例如CATEGORY_HOME可以作为该应用的home screen,而CATEGORY_GADGET适合嵌入到某个activity中。

下面是两个例子。例子1指明了action name,由于存在多个匹配,系统将列出来,供用户进行选择,如下。

例子2在例子1的基础上增加了intent.addCategory(Intent.CATEGORY_LAUNCHER);,增加对Category名字的匹配,可以看到系统进行了进一步的过滤。:

我们可以通过PackageManager在代码中,可以不唤起intent就获得匹配的activity信息。如下

Intent intent = new Intent(Intent.ACTION_MAIN,null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager pm = getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);


for(ResolveInfo ri : list){ 
    String packageName = ri.activityInfo.packageName;
    String className = ri.activityInfo.name
    ... ....
    //有了packageName和className,就可以进行分析,然后通过Intent i= new Intent(packaname,className); startActivity(i);唤起我们所需的acitivity。 
}

然而,通过PackageManager获得匹配的Activity的数量多于例子中系统提供给用户选择的activities的数量,为何?特别是没有将本应用显示出来。通过category筛选属于implicit intent的调用方式,不属于指定软件包名及类名的explicit intent的精确调用方式,对于implicit intent调用需要进行声明,如下:

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

activity的intent-filter中可以有多个category描述,其中CATEGORY_DEFAULT表示可以使用implicit intent调用,当我们增加此项声明后,本应用就出现在匹配的activity列表中。同样,对于通过action name来调用的,不指定包名和类名的,也属于implicit intent,同样需要进行CATEGORY_DEFAULT的声明,否则会出现ActivityNotFoundException的错误。如果activity没有在intent fliter中设置为CATEGORY_DEFAULT,我们可以用PackageManager获取匹配的activities的信息,分析后得到确切的包名和类名,通过explicit的方式唤起该activity。

此外Android说如果从launcher screen唤起时不需要DEFAULT,也就是此时acitivty只需MAIN和LAUNCHER,当然我们也可以DEFAULT设上。Android在DEFAULT上似乎有些繁杂,简单说如果我们不希望App被其他App通过implicit调用,我们就不要设置DEFAULT。

在category中有一个有趣的类别:<category android:name="android.intent.category.HOME"/>,我们在MainActivity以及另外一个Activity增加该类别。

<application ...... >
    <activity ...... >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME"/>
            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>
    <activity android:name=".IntentBasicViewActivity" android:label="@string/intent_basic_test">
        <intent-filter>
                <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>
    ......
</application>

左图在代码中通过PackageManager来查看匹配CATEGORY_HOME的信息;中图通过StartActivity(intent)来唤起匹配CATEGORY_HOME的Activities时,系统给予用户的选择,如果在应用中按Home键,有同样效果;右图为退出应用,按Home键,要求进入Home UI时,系统给予用户的选择。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以通过以下命令禁用intent: ``` adb shell pm disable <package_name>/<component_name> ``` 其,`<package_name>` 是应用程序包名,`<component_name>` 是组件名称,可以是 Activity、Service、BroadcastReceiver 等。 例如,禁用 com.example.app 应用程序的 MainActivity,可以使用以下命令: ``` adb shell pm disable com.example.app/.MainActivity ``` 请注意,禁用组件可能会影响应用程序的功能,请谨慎操作。 ### 回答2: adb(Android Debug Bridge)是用于与安卓设备进行通信的调试工具。它可以通过adb命令向设备发送指令,执行各种调试操作。而Intent则是Android系统用于在组件之间传递消息和数据的机制。 在某些情况下,我们可能需要禁止通过adb发送Intent到设备上的组件。其一种情况是为了保护设备安全。如果未经授权的第三方应用可以通过adb发送恶意Intent到设备上的组件,可能会造成数据泄露或者安全漏洞。因此,禁止Intent的使用可以提高设备的安全性。 另外一种情况是为了限制应用的功能。某些应用可能希望禁止通过adb发送Intent到设备上的组件,以确保用户只能通过应用提供的特定界面或流程来操作设备。这样可以避免用户绕过应用的功能,并防止应用的滥用或盗版。 要禁止adb发送Intent,可以通过以下步骤实现: 1. 在设备上启用开发者选项,并启用USB调试模式。 2. 在计算机上打开终端或命令提示符,进入adb的安装目录。 3. 使用adb命令连接到设备:adb connect <设备IP地址> 4. 确认设备已成功连接后,使用以下adb命令禁用Intent: adb shell settings put global adb_enabled 0 以上命令将禁用adb发送Intent到设备上的组件。如果想要恢复adb的Intent功能,只需将最后一个命令的“0”改为“1”即可。 需要注意的是,禁止adb发送Intent可能会影响某些应用的正常使用,因此在实施之前应谨慎考虑,并确保了解可能带来的影响。 ### 回答3: ADB(Android Debug Bridge)是Android开发工具包的一部分,它提供了一种与Android设备进行通信和调试的方式。ADB具有很多功能,包括发送和接收IntentIntent是一种用于在Android应用程序和组件之间进行通信的机制。它可以用于启动Activity、发送广播、启动服务等。在调试过程,我们可以使用ADB发送Intent来测试应用程序的功能。 然而,有时候我们可能希望禁止通过ADB发送Intent,这可能是因为安全性的考虑或者其他原因。要实现禁止ADB发送Intent的功能,可以采取以下步骤: 1. 在应用程序的AndroidManifest.xml文件添加以下权限声明: ```xml <uses-permission android:name="android.permission.SET_DEBUG_APP" /> ``` 2. 在应用程序的代码,检查是否有已连接的调试器。可以使用如下代码进行判断: ```java import android.os.Debug; boolean isDebuggerConnected = Debug.isDebuggerConnected(); ``` 3. 如果发现有已连接的调试器,则禁止通过Intent发送。可以使用如下代码实现: ```java if (isDebuggerConnected) { PackageManager packageManager = getPackageManager(); packageManager.setComponentEnabledSetting( new ComponentName(this, YourActivity.class), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP ); } ``` 以上代码的YourActivity可以替换为你想禁止通过Intent发送的组件,如MainActivity。 通过以上步骤,我们可以在有已连接调试器的情况下禁止应用程序通过ADB发送Intent。这可以增加应用程序的安全性,并防止潜在的恶意操作。 当然,禁止通过ADB发送Intent可能会对应用程序的测试和调试造成一定的影响。因此,在实际使用需要权衡利弊,并根据实际需求进行操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值