美文网首页Android OtherAndroid开发Android知识
Android知识点回顾之Intent/IntentFilter

Android知识点回顾之Intent/IntentFilter

作者: 星泉毅 | 来源:发表于2017-10-30 23:12 被阅读32次

    定义:Intent是一个消息传送对象,可以用它来访问另外一个组件

    可以用于以下三个场景:

    • startActivity
    startActivity()
    
     startActivityForResult()
    
    • startService
      Android 5.0以上可以使用JobScheduler启动
      所有版本可以使用:
      startService();
      bindService();
    
    • sendBroadcast
      三种调用方法
    sendBroadCast()
    
    sendOrderedBroadCast()
    
    sendStickyBroadcast()
    

    Intent 类型

    • 显示类型
      直接指定调用组件的名字,一般用于自己的APP内部
    • 隐式类型
      没有指定组件的名字,而是声明一般的action行为,用此方法可以允许调用另外一个APP的组件

    启动Service最好使用显示Intent,否则会存在安全风险,因为无法确定service什么时候被调用,而service又是用户感知不到的组件

    Android 5.0开始,如果bindService()隐式调用启动service,会抛出异常

    Intent的创建

    一个Intent对象包含了Android系统应该启动哪个组件的信息

    一个Intent可以包含以下信息:

    • componentName
      指定需要启动组件的名字
      此项是可选的,用来区分显示Intent和隐式Intent。
      赋值的方法有以下几种

      • Intent的构造方法
      • setComponent()
      • setClass()
      • setClassName
    • action
      指定Intent要完成的动作,为字符串常量
      action可自定义,也可使用系统的,一般自定义的话最好加上自己APP的包名前缀
      一些系统标准的Action常量
      ACTION_VIEW,startActivity(),唤起系统相册
      ACTION_SEND,startActivity(),把一些数据发送给另外的一些APP,如email,社交软件等
      ACTION_CALL,startActivity(),唤起打电话界面
      不定期补充...
      除了Intent定义了Action常量,其他的类也有定义,比如Settings,可以用来跳转到系统指定的设置界面
      action赋值的方法有一下几种:

      • Intent的构造方法
      • setAction()
    • data
      根据给定的Uri寻找匹配的目标组件,如果不给定MIME类型,会进行推导,给定MIME类型,则强制使用此类型。
      不同的Action有对应的data数据指定。
      其中data的值设置为setData(),MIME的设置为setType()
      常用值如下所示:
      tel://:      号码数据格式,后跟电话号码。 
      mailto://:    邮件数据格式,后跟邮件收件人地址。
      smsto://:    短息数据格式,后跟短信接收号码。
      content://:   内容数据格式,后跟需要读取的内容。 
      file://:      文件数据格式,后跟文件路径。
      geo:// latitude, longitude:经纬数据格式,在地图上显示经纬度所指定的位置。
      Uri指定数据指向那种数据格式,MIME指定数据具体的类型。比如Image和Audio有同样的Uri,但是MIME的类型是不同的。

    setData()和setType()会互相覆盖,所以当需要同时设置Uri和MIME时,为了避免这种情况,可以调用setDataAndType()

    • category
      执行Action的附加信息。可以放置很多category,但是大多数intent是不需要category的
      常用值如下:
      CATEGORY_DEFAULT:Android系统中默认的执行方式,按照普通Activity的执行方式执行。 
      CATEGORY_HOME:设置该组件为Home Activity。
      CATEGORY_PREFERENCE:设置该组件为Preference。 
      CATEGORY_LAUNCHER:设置该组件为在当前应用程序启动器中优先级最高的Activity,通常为入口ACTION_MAIN配合使用。 
      CATEGORY_BROWSABLE:设置该组件可以使用浏览器启动。 
      CATEGORY_GADGET:设置该组件可以内嵌到另外的Activity中。
      通过addCategory()指定
    • extras
      用来存放需要传递的数据,以键值对的形式进行存储和访问
      通过putExtras()方法设置
    • flags
      设置Activity的启动模式,例如:
      FLAG_ACTIVITY_CLEAR_TOP
      FLAG_ACTIVITY_NEW_TASK
      FLAG_ACTIVITY_NO_HISTORY
      FLAG_ACTIVITY_SINGLE_TOP
      具体的笔记放到Activity上
      通过setFlags()方法设置

    显示Intent的例子

    Intent downloadIntent = new Intent(this, DownloadService.class);
    downloadIntent.setData(Uri.parse(fileUrl));
    startService(downloadIntent);
    

    隐式Intent的例子

    其中resolveActivity()用来判断Intent是否能够被解析,防止APP崩溃

    Intent sendIntent = new Intent();
    sendIntent.setAction(Intent.ACTION_SEND);
    sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
    sendIntent.setType("text/plain");
    //Intent chooser = Intent.createChooser(sendIntent, title);//强制使用选择器
    //if (sendIntent.resolveActivity(getPackageManager()) != null) {
    //    startActivity(chooser);
    //}
    // Verify that the intent will resolve to an activity
    if (sendIntent.resolveActivity(getPackageManager()) != null) {
        startActivity(sendIntent);
    }
    

    接收一个隐式Intent

    需要在manifest文件中配置<intent-filter>,<intent-filter>包含如下三个子项:
    <action>
    <data>
    <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"/>
        </intent-filter>
    </activity>
    

    MIME类型 application/vnd.google.panorama360+jpg为指定的全景照片数据类型

    <activity android:name="MainActivity">
        <!-- This activity is the main entry, should appear in app launcher -->
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    
    <activity android:name="ShareActivity">
        <!-- This activity handles "SEND" actions with text data -->
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="text/plain"/>
        </intent-filter>
        <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <action android:name="android.intent.action.SEND_MULTIPLE"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="application/vnd.google.panorama360+jpg"/>
            <data android:mimeType="image/*"/>
            <data android:mimeType="video/*"/>
        </intent-filter>
    </activity>
    

    使用PendingIntent

    PendingIntent是对Intent的包装,使外部的APP能够像在内部APP那样对所包含的Intent进行使用
    主要有如下的使用场景:

    • Notification
    • App Widget
    • AlarmManager

    取得实例的方法如下:
    PendingIntent.getActivity(),启动Activity
    PendingIntent.getService(),启动Service
    PendingIntent.getBroadcast(),启动BroadcastReceiver

    状态栏通知:

    
      int icon = android.R.drawable.my_icon;
      long when = System.currentTimeMillis();//通知发生的时间为系统当前时间
      Notification notification = new Notification(icon, null, when);//新建一个通知,第一个参数为图标,第二个参数为短暂提示标题,第三个为通知时间
      notification.defaults = Notification.DEFAULT_SOUND;//发出默认声音
      notification.flags |= Notification.FLAG_AUTO_CANCEL;//点击通知后自动清除通知
      Intent openintent = new Intent(this, OtherActivity.class);
      PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);//当点击消息时就会向系统发送openintent意图
      notification.setLatestEventInfo(this, "标题", "内容", contentIntent);//setLatestEventInfo表示设置点击该通知的事件
        int notifyCode = 0;
    //获取通知管理器
      NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
      mNotificationManager.notify(notifyCode , notification);//第一个参数为自定义的通知唯一标识
    

    action匹配规则

    如果intent-filter设置了action的过滤规则,比如下面的XML代码,

    <intent-filter>
        <action android:name="android.intent.action.EDIT" />
        <action android:name="android.intent.action.VIEW" />
        ...
    </intent-filter>
    

    那么:

    • intent不设置action,则直接不通过
    • intent设置了多个Action,则只要有一个匹配上,则可以通过
    //不通过
    Intent intent = new Intent();
    
    //通过
    intent.setAction("android.intent.action.EDIT");
    
    //通过
    intent.setAction("android.intent.action.EDIT");
    intent.setAction("android.intent.action.test");
    

    Category匹配规则

    如果intent-filter设置了category的过滤规则,如下面的XML代码,

    <intent-filter>
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        ...
    </intent-filter>
    

    那么:

    • Intent不设置category,则都通过,不论intent-filter设置多少category
    • intent设置了category,intent上的category能够匹配上intent-filter设置的category,才能够通过

    比如:

    //通过
    Intent intent = new Intent();
    
    //通过
    intent.addCategory("android.intent.category.DEFAULT"),可以匹配上
    
    //通过
    intent.addCategory("android.intent.category.BROWSABLE")
    
    //不通过
    intent.addCategory("android.intent.category.DEFAULT")
    intent.addCategory("android.intent.category.test")
    

    Data匹配规则

    intent-filter中的<data>结构由Uri和MIME Type组成
    Uri包括如下几部分:

    • scheme:整个Uri的模式,如http,ftp,content等
      如果scheme未指定,则忽略host
      如果只指定scheme,则所有和intent-filter相同的scheme都匹配

    • host:Uri的域名,如www.google.com
      如果host未指定,则忽略port

    • port:Uri的端口

    • path:包含的路径信息,如:folder/subfolder/etc
      如果scheme,host都未指定,则忽略path

    整体组成:<scheme>://<host>:<port>/<path>,如 content://com.example.project:200/folder/subfolder/etc

    MIME Type:表示image/ipeg,video/*等媒体类型

    匹配规则如下:
    intent中的data必须和intent-filter完全匹配才能通过。有如下几种情况:
    a.intent没有设置Uri和MIME Type,同时intent-filter也没有设置
    b.intent只包含Uri,但未包含MIME Type,同时能够匹配上intent-filter设置的Uri,并且intent-filter为设置MIME Type
    c.intent只设置MIME Type,同时intent-filter也设置了相同的MIME Type并且未指定Uri
    d.intent设置了Uri和MIME Type,intent-filter只设置了MIME Type,则intent的Uri的scheme必须为content:或是file:。即,intent-filter如果没有设置Uri,只设置了MIME Type,则Uri为content:或file:的模式。也就是说,过滤的规则希望组件能够从文件(file)或内容提供者(content provider)获取到本地数据。

    规则d例子,从相册获取图片:

    <intent-filter>
        <data android:mimeType="image/*" />
        ...
    </intent-filter>
    

    则intent的匹配规则为:

     Intent intent = new Intent();
     intent.setDataAndType(Uri.parse("file://test"), "image/*");
     startActivity(intent);
    

    如果intent-filter设置了多个data,则intent中的data只要和其中一个匹配就可以通过

    为了防止APP崩溃,所有的intent匹配规则进行调用前都要进行判断处理:
    if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
    }

    本知识点完~

    相关文章

      网友评论

        本文标题:Android知识点回顾之Intent/IntentFilter

        本文链接:https://www.haomeiwen.com/subject/ozwypxtx.html