zoukankan      html  css  js  c++  java
  • Pro Android学习笔记(十一):了解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时,系统给予用户的选择。

    相关链接: 我的Android开发相关文章

  • 相关阅读:
    嵌入式 VFS: Cannot open root device "mtdblock2" or unknown-block(2,0)
    嵌入式 hi3518x平台h264+g711a封装mp4代码demo
    嵌入式 十个最值得阅读学习的C开源项目代码
    嵌入式 arm平台ping域名指定ip小结
    嵌入式 busybox自带的tftp、telnet、ftp服务器
    嵌入式 hi3518平台检测网线是否插上
    嵌入式 hi3518平台获取网络环境中的ip、netmask、broadcast等信息
    jdbcUrl is required with driverClassName错误解决
    class path resource [processes/] cannot be resolved to URL because it does not exist
    SpringBoot2.0--- 多数据源配置
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4094654.html
Copyright © 2011-2022 走看看