• Android 应用的交互------Intent


      为了让用户能够从一个activity跳到另一个activity,我们的app必须使用Intent来定义自己的意图。当使用startActivity()的方法,且参数是intent时,系统会使用这个 Intent 来定义并启动合适的app组件。使用intents甚至还可以让app启动另一个app里面的activity。

      Activity、Service和BroadcastReceiver,都是通过Intent机制激活的,而不同类型的组件在传递Intent时有不同的方式。

    一.Intent的组成部分

    • Component属性需要接受一个ComponentName对象,ComponentName需要指定包名和类名,这就可唯一确定一个组件类,这样应用程序即可根据给定的组件去启动特定的组件。
    • Action属性和Category属性都是一个普通的字符串,其中Action代表该Intent所要完成的一个抽象“动作”,而Category则用于为Action增加额外的附加类别信息。通常Action属性会与Category属性结合使用。
    • Data属性通常用于向Action属性提供操作的数据。Data属性接受一个Uri对象,Uri字符串总满足如下格式:scheme://host:port/path
    • Type属性用于指定该Data所指定Uri对应的MIME类型,这种MIME类型可以是任何自定义的MIME类型,只要符合abc/xyz格式的字符串即可。
    • Extra属性通常用于在多个Action之间进行数据交换,Intent的Extra属性值应该是一个Bundle对象。
    • Flag属性用于为该Intent添加一些额外的控制旗标

    二.Intent的调用方法

    1.显示(explicit)调用

      显式Intent需要明确指定要启动或者触发的组件的类名 

      

    2.隐示(implicit)调用

      隐式Intent只是指定需要启动或者触发的组件应满足怎样的条件。对于隐式Intent而言,Android系统需要对该Intent进行解析,解析出它的条件,然后再去系统中查找与之匹配的目标组件。如果找到符合条件的组件,就启动或触发它们。

      Implicit intents并不声明要启动组件的具体类名,而是声明一个需要执行的action。这个action指定了我们想做的事情,例如查看,编辑,发送或者是获取一些东西。Intents通常会在发送action的同时附带一些数据,例如你想要查看的地址或者是你想要发送的邮件信息。数据的具体类型取决于我们想要创建的Intent,比如URL或其他规定的数据类型,或者甚至也可能根本不需要数据。

    例如:

    //打电话
    Uri number = Uri.parse("tel:5551234");
    Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
    
    //看地图
    // Map point based on address
    Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
    // Or map point based on latitude/longitude
    // Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
    Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
    
    //打开网页
    Uri webpage = Uri.parse("http://www.android.com");
    Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
    

      一些需要其他数据的隐示Intent,我们可以使用putExtra()方法来添加一些数据。如果我们没有在intent中包含一个Uri, 则通常需要使用 setType() 方法来指定intent附带的数据类型。设置MIME type 是为了指定应该接受这个intent的activity。

    //发送一个带附件的email
    Intent emailIntent = new Intent(Intent.ACTION_SEND);
    // The intent does not have a URI, so declare the "text/plain" MIME type
    emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
    emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
    emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
    // You can also attach multiple items by passing an ArrayList of Uris
    
    
    //创建一个日历事件:
    Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
    Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
    Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);
    calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
    calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
    calendarIntent.putExtra(Events.TITLE, "Ninja class");
    calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
    

    验证是否有App去接收这个Intent:

      当触发了一个intent,但是没有任何一个app中的activity来接受,则app会crash。所以我们需要确保有intent会被系统内置的app(such as the Phone, Email, or Calendar app)之一接收。为了验证是否有合适的activity会响应这个intent,需要执行queryIntentActivities() 来获取到能够接收这个intent的所有activity的list。若返回的List非空,那么我们才可以安全的使用这个intent。例如:

    PackageManager packageManager = getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
    boolean isIntentSafe = activities.size() > 0;
    

    显示分享App的选择界面

      请注意,当以startActivity()的形式传递一个intent,并且有多个app可以handle时,用户可以在弹出dialog的时候选择默认启动的app(通过勾选dialog下面的选择框,如上图所示)。该功能对于用户有特殊偏好的时候非常有用(例如用户总是喜欢启动某个app来查看网页,总是喜欢启动某个camera来拍照)。

      为了显示多个打开方式, 需要使用createChooser()来创建Intent:

    Intent intent = new Intent(Intent.ACTION_SEND);
    ...
    
    // Always use string resources for UI text. This says something like "Share this photo with"
    String title = getResources().getText(R.string.chooser_title);
    // Create and start the chooser
    Intent chooser = Intent.createChooser(intent, title);
    startActivity(chooser);

    三.接收Activity返回的结果

      启动另外一个activity并不一定是单向的。我们也可以启动另外一个activity然后接受一个返回的result。为接受result,我们需要使用startActivityForResult() ,而不是startActivity()

      当然,被启动的activity需要指定返回的result。它需要把这个result作为另外一个intent对象返回,我们的activity需要在onActivityResult()的回调方法里面去接收result。

      对于startActivityForResult() 方法中的intent与之前介绍的并无太大差异,不过是需要在这个方法里面多添加一个int类型的参数。

    该integer参数称为"request code",用于标识请求。当我们接收到result Intent时,可从回调方法里面的参数去判断这个result是否是我们想要的。

    //启动activity
    static final int PICK_CONTACT_REQUEST = 1;  // The request code
    ...
    private void pickContact() {
        Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
        pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
        startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
    }
    //接收Result
    /*
    当用户完成了启动之后activity操作之后,系统会调用我们activity中的onActivityResult() 回调方法。该方法有三个参数:
    通过startActivityForResult()传递的request code。
    第二个activity指定的result code。如果操作成功则是RESULT_OK ,如果用户没有操作成功,而是直接点击回退或者其他什么原因,那么则是RESULT_CANCELED
    包含了所返回result数据的intent。
    */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Check which request we're responding to
        if (requestCode == PICK_CONTACT_REQUEST) {
            // Make sure the request was successful
            if (resultCode == RESULT_OK) {
                // The user picked a contact.
                // The Intent's data Uri identifies which contact was selected.
    
                // Do something with the contact here (bigger example below)
            }
        }
    }

      处理Intent的activity返回result只需要执行setResult()通过指定一个result code与result intent。操作完成之后,用户需要返回到原来的activity,通过执行finish() 关闭被唤起的activity。

     // Create intent to deliver some kind of result data
    Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri");
    setResult(Activity.RESULT_OK, result);
    finish();
    

      result code的值通常RESULT_OK或RESULT_CANCELED(默认)。如果只是纯粹想要返回一个int来表示某些返回的result数据之一,则可以设置result code为任何大于0的数值。如果我们返回的result只是一个int,那么连intent都可以不需要返回了,可以调用setResult()。

    setResult(RESULT_COLOR_RED);
    finish();

    四.Intent过滤

      通过在manifest文件中的<activity>标签下添加<intent-fliter>的属性,使其他的app能够启动我们的activity。

      为了尽可能确切的定义activity能够handle的intent,每一个intent filter都应该尽可能详尽的定义好action与data。

    • Action:一个想要执行的动作的名称。通常是系统已经定义好的值,如ACTION_SENDACTION_VIEW。 在intent filter中通过<action>指定它的值,值的类型必须为字符串,而不是API中的常量(看下面的例子)

    • Data:Intent附带数据的描述。在intent filter中通过<data>指定它的值,可以使用一个或者多个属性,我们可以只定义MIME type或者是只指定URI prefix,也可以只定义一个URI scheme,或者是他们综合使用。

    • Category:提供一个附加的方法来标识这个activity能够handle的intent。通常与用户的手势或者是启动位置有关。系统有支持几种不同的categories,但是大多数都很少用到。而且,所有的implicit intents都默认是 CATEGORY_DEFAULT 类型的。在intent filter中用<category>指定它的值。
    <activity android:name="ShareActivity">
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="text/plain"/>
            <data android:mimeType="image/*"/>
        </intent-filter>
    </activity>
  • 相关阅读:
    【转】Android实战技巧:ViewStub的应用
    3.11 返回数据到前一个Activity
    在用android日志的时候老是弹出一个窗口,内容为:"Copy" did not complete normally. Please see the log 和 什么函数,能达到和android手机上按“返回”键一样的效果?
    Windows下的Android模拟器设置内存大小
    AlertDialog.Builder对话框类的用法(二)
    android版计算器
    【转】Android中字符串的拆分split
    readelf
    6200 uboot 测试版分析(二)
    cpp
  • 原文地址:https://www.cnblogs.com/slothccc/p/7397666.html
Copyright © 2020-2023  润新知