zoukankan      html  css  js  c++  java
  • Android Intent详解

    一、简介

      在Android OS中,隐式Intent可以启动其它应用Activity。在显示Intent中,指定要启动的Activity类,OS会负责启动它。在隐式Intent中,描述清楚要完成的任务,OS会找到合适的应用,并在其中启动相应的Activity。

    二、典型隐式Intent的组成

    • 一个隐式Intent的主要组成部分:

        1. 要执行的操作

        通常以Intent类中的常量表示。例如,要访问查看某个URL,可以使用Intent.ACTION_VIEW;要发送邮件,可以使用Intent.ACTION_SEND。

        2. 要访问数据的位置

        可能是设备以外资源,如某个网页UIL,也可以是指向某个文件的URI,或者是指向ContentProvider中某条记录的某个内容URI(Content URI)。

        3. 操作涉及的数据类型

        指的是MIME形式的数据数据,如text/htme或audio/mpeg3。如果一个Intent包含某类数据的位置,那么通常可以从中推测出数据类型。

        4. 可选类别

        如果操作用于描述具体要做什么,那么类别通常用来描述我们何时、何地或者说如何使用某个Activity的。Android的android.intent.category.LAUNCHER类别表明,activity应该显示在顶级应用启动器中。而android.intent.category.INFO类别表明,虽然Activity向用户显示包信息,但它不应该显示在启动器中。

    PS:一个Intent由四方面组成,分别为:动作(action)、 操作类别(category)、数据、数据类型。

      动作(action):通过Intent类,指定activity做什么操作,比如:发送邮件。

      类别(category):动作的描述,选择用哪些activity来完成任务。

      数据:Intent传递的数据。

      数据类型(MIME):传递数据的格式。

    示例:

      一个用来查看某个网址的简单隐式Intent会包括一个Intent.ACTION_VIEW操作,以及某个具体URL网址的URI数据。

      基于以上信息,操作系统将启动适用应用的适用Activity(如果有多个适用应用可选,用户可自行如何选择)。

      通过配置文件中的Intent过滤器设置,activity会对外宣称自己是适合处理ACTION_VIEW的Activity。如果是开发一款浏览器应用,为响应ACTION_VIEW操作,需要在Activity声明中包含以下过滤器:

    1 <activity
    2     android:name=".BrowserActivity"
    3     android:label="@string/app_name">
    4     <intent-filter>
    5         <action android:name="android.intent.action.VIEW"/>
    6         <category android:name="android.intent.category.DEFAULT"/>
    7         <data android:scheme="http" android:host="www.baidu.com"/>
    8     </intent-filter>
    9 </activity>

      DEFAULT类别必须明确地在Intent过滤器中进行设置。Intent过滤器中的action元素告诉OS,activity能够处理指定的任务,DEFAULT类别告诉OS,activity愿意处理某项任务。

      DEFAULT类别实际隐含添加到了几乎每一个隐式Intent中。(唯一的例外是LAUNCHER类别)

    隐藏Intent启动OS中其它应用的与此Intent相匹配的activity:

     1 Button choose = (Button)v.findViewById(R.id.choose_btn);
     2 choose.setOnClickListener(new Button.OnClickListener()
     3 {
     4     @Override
     5     public void onClick(View v)
     6     {
     7         Intent i = new Intent(Intent.ACTION_SEND);
     8         i.setType("text/plain");
     9         i.putExtra(Intent.EXTRA_TEXT, "Choose");
    10         i.putExtra(Intent.EXTRA_SUBJECT, "Choose Suspect");
    11         i = Intent.createChooser(i, "Chooser");
    12         startActivity(i);
    13     }
    14 });

       使用隐式Intent,通过startActivity(...)方法启动activity,启动外部应用,隐式的将类别附给Intent,启动的activity是应用中manifest文件中,对activity配置了DEFAULT类别。实际上调用startActivity(Intent)方法意味着“启动与发送的隐式Intent相匹配的默认Activity”。

      前面说过,MAIN/LAUNCHER intent过滤器并不一定包含CATEGORY DEFAULT类别,因此,是否可以与通过startActivity(Intent)方法发送的隐式Intent匹配,谁也说不准。

      在设备已经安装的应用中,使用隐式Intent对象,匹配相同类别的应用中的Activity。因为,不能确保Intent过滤器,一定设置了GATEGORY DEFAULT类别,所以,通过包管理器查找,PackageManager类设备已经安装应用的包管理器。

      示例:通过PackageManager获取已安装的应用中与Intent相匹配的Activity列表:

    1 // Intent对象,设置动作
    2 Intent startIntent = new Intent(Intent.ACTION_MAIN);
    3 // 设备Intent对象的操作类别
    4 startIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    5 // 获取PackageManager对象
    6 PackageManager pm = getActivity().getPackageManager();
    7 // 获取Activity列表,及相关应用包的信息和Activity信息
    8 List<ResolveInfo> activities = pm.queryIntentActivities(startIntent, 0);

      对象获取的Activity列表排序,按字母排序:

     1 // new Comparator<T>(){}此写法是对Comparator类的compare(...)覆盖重写
     2 Collections.sort(activities, new Comparator<ResolveInfo>()
     3 {
     4     // 重写排序方法的实现
     5     @Override
     6     public int compare(ResolveInfo lhs, ResolveInfo rhs)
     7     {
     8         // 获取PackManager对象
     9         PackageManager pm = getActivity().getPackageManager();
    10         // loadLabel(...)方法是按字母排序
    11         int ret = String.CASE_INSENSITIVE_ORDER.compare(lhs.loadLabel(pm).toString(),
    12                                                         rhs.loadLabel(pm).toString());
    13         return ret;
    14     }
    15 });

      在列表ListView上显示应用名称列表:

     1 // 使用匿名内部类,创建适配器。在列表中显示
     2 ArrayAdapter<ResolveInfo> adapter = new ArrayAdapter<ResolveInfo>(getActivity(),
     3                                                                   android.R.layout.simple_list_item_1, activities)
     4 {
     5     // 覆盖基类的getView(...)方法
     6     @Override
     7     public View getView(int pos, View converView, ViewGroup parent)
     8     {
     9         View v = super.getView(pos, converView, parent);
    10         // 获取PackageManager对象
    11         PackageManager pm = getActivity().getPackageManager();
    12         // 获取指定包的相关信息
    13         ResolveInfo info = getItem(pos);
    14         TextView tv = (TextView)v;
    15         tv.setText(info.loadLabel(pm));
    16         tv.setTextColor(Color.rgb(255, 64, 129));
    17         
    18         return v;
    19     }
    20 };
    21 // 指定适配器对象
    22 setListAdapter(adapter);

    PS:ArrayAdapter<T>对象创建就使用的匿名内部类

      通过显示Intent对象启动指定的Activity:

     1 @Override
     2 public void onListItemClick(ListView listView, View view, int pos, long id)
     3 {
     4     // 获取选定应用的应用信息,包括包信息及Activity信息
     5     ResolveInfo resolveInfo = (ResolveInfo)listView.getAdapter().getItem(pos);
     6     // 获取指定的Activity信息
     7     ActivityInfo activityInfo = resolveInfo.activityInfo;
     8     
     9     if (null == activityInfo)
    10     {
    11         return;
    12     }
    13     // 创建显示的Intent对象
    14     Intent i = new Intent(Intent.ACTION_MAIN);
    15     // 指定要启动的Activity信息,包名和Activity名
    16     i.setClassName(activityInfo.applicationInfo.packageName, activityInfo.name);
    17     startActivity(i);
    18 }
  • 相关阅读:
    你不是真正的快乐
    春天里
    一生有你
    故乡
    第一天
    直来直往
    恋恋风尘
    烦恼歌
    because of you
    从头再来
  • 原文地址:https://www.cnblogs.com/naray/p/5300592.html
Copyright © 2011-2022 走看看