如何进入系统拨号盘,或者直接打电话,发短信,还有data,scheme,uri的关系

一.背景

Android做app,有时候需要去调用系统的拨号盘,或者直接拨打某个电话,还有发送短信(直接发送和带着默认的号码和内容跳到系统应用),网上有很多例子,可以直接拿来用,可是如果换做是调用其他的系统应用你会咩?

下面就授之以渔!!!

二.实例

用一个跳到短信的需求来讲怎么查源代码(点我获取应用层代码)。

(1)首先用模拟器打开新建短信,观察开启了什么Activity

          

(2)从上面可以发现启动了ComposeMessageActivity,接下来查看他的源码和Intent-filter


(3)查看



通过上面就可以知道怎么跳到信息应用,很多会对 Data,MineType还有Scheme搞不清,等会我就区分下,先讲完这里,如果要带着内容怎么搞?

(4)看看怎么带着内容跳到系统的信息应用


所以综上基本就可以知道怎么用了

(5)代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btDialDirect;
    private Button btDialInDirect;
    private Button btSendSms;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btDialDirect = (Button) findViewById(R.id.bt_dial_direct);
        btDialInDirect = (Button) findViewById(R.id.bt_dial_indirect);
        btSendSms = (Button) findViewById(R.id.bt_sendSms);
        btSendSms.setOnClickListener(this);
        btDialDirect.setOnClickListener(this);
        btDialInDirect.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        Uri data = null;
        if(btDialDirect == v){
            //直接打出去
            intent.setAction(Intent.ACTION_CALL);
            data = Uri.parse("tel:"+110);
        }else if(btDialInDirect == v){
            //跳到拨号盘然后自己打
            intent.setAction(Intent.ACTION_DIAL);
            data = Uri.parse("tel:"+110);
        }else if(btSendSms == v){
            intent.setAction(Intent.ACTION_SENDTO);
            data = Uri.parse("smsto:" + 5556);
            intent.putExtra("sms_body","come here");
        }
        intent.setData(data);
        startActivity(intent);
    }
}
详细的源码就不放了,不能再简单了。。。

三.讲讲data,scheme,uri的关系

Activity之间的跳转分为2种:

       (1)显式跳转:

在可以引用到那个类, 并且可以引用到那个类的字节码时可以使用。一般用于自己程序的内部。显式跳转不可以跳转到其他程序的页面中。

       (2) 隐式跳转:

可以在当前程序跳转到另一个程序的页面。隐式跳转不需要引用到那个类,但是必须得知道那个界面的动作(action)和信息(category),有时还需要Data

Activity之间通过Intent进行通信。Intent即意图,用于描述一个页面的信息,同时也是一个数据的载体。

隐式跳转的Activity(自己写这个Activity要在清单文件注册action,和category,data(有时),其他app隐式调用这个Activity,就不用注册Activity

因为自己的如果不注册,那触发这些action,category都不知道是启动哪个Activity隐式跳转可以跳转到其他程序的Activity只要知道Activity的动作(action)以及信息(category)。因此,能够被隐式跳转的Activity,在清单文件中声明时必须指定动作和信息这两个属性。





上面的写的android.intent.category.DEFAULT可以不写原因是系统用过startActivity或者startActivityForResult的时候会默认为Intent加上“android.intent.category.Default”这个category

(3)系统入口:

若清单文件中的Activity声明为:

则此Activity将作为程序的入口,有几个作为入口的Activity,apk文件安装的时候就会生成几个图标。

(4)data,mimeType和URI的区别

<data android:scheme="http" />
                <data android:scheme="https" />
                <data android:scheme="inline" />
                <data android:mimeType="text/html"/>
                <data android:mimeType="text/plain"/>
                <data android:mimeType="application/xhtml+xml"/>
                <data android:mimeType="application/vnd.wap.xhtml+xml"/>
或者
 <data 			android:scheme="http"
                android:scheme="https"
                android:scheme="inline" 
               android:mimeType="text/html"
                android:mimeType="text/plain"
                android:mimeType="application/xhtml+xml"
                android:mimeType="application/vnd.wap.xhtml+xml"/>

可以看出上面的data由两部分组成mimeType和URI组成

mimeType(媒体类型,比如 image/jpeg,audio/mpeg4-generic 和video)

URI,下面是它的结构<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]

实际例子

Content://com.example.project:200/folder/subfolder/etc

http://www.baidu.com:80/search/info

Scheme:URI的模式(URI默认值为content和file),比如http,file,content等,如果URI中没有指定scheme,那么整个URI的其他参数无效,他也意味着URI是无效的(就像Uri.parse("smsto:" + 5556);如果没有写smsto,那后面的5556就没有什么软用

Host:是URI的主机名

Port:URI中的端口号

注意:

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

 

意这种规则制定了媒体类型为所有类型的图片,虽然没有指定URI,但是却有默认值,URI默认值为content和file,也就是虽然没有指定URI,但是Intent中的URI部分的scheme必须为Content或者file才能匹配

intent.setDataAndType(Uri.parse(“file://abc”),”image/png”).(注意setData和setType不能单独写否则会互相清空

(5)一些注意事项

Intent-Filter的匹配规则对于Service和BroadCastReceiver也是同样的道理,不过系统对于service的建议是尽量使用显示调用方式来启动服务。

但是要注意一点,如果硬是方式开启一个Activity的时候,需要做一个判断,看是否有Activity能够匹配我们的隐式Intent 

判断是否有匹配的隐式 (避免不匹配直接崩掉)

1.PackManager    resolveActivity

2.Intent    resolveActivity

3.PackMagager   querryIntentActivityes,这个方法和resolveActivity方法不同的是:它不是返回最佳匹配的Activity信息而是返回所有成功匹配的Activity信息,我们看一下两者的原型

 

Public abstract List<ResolveInfo> queryIntentActivities(Intent intent, int flags)

Public abstract ResolveInfo resolveActivity (Intent intent ,int flags)

 

第二个参数要使用 MATCH_DEFAULT_ONLY 这个标记位,这个标记为的含义是仅仅匹配那些在intent-filter中声明了<category android:name = “android.intent.category.Default/>”这个category的Activity

 

这个标记为的意义在于,只要上述的两个方法不返回null,那么startActivity一定可以成功,如果不用这个标记位,就会把intent-filter中category不含Default的那些Activity匹配出来,从而导致导致startActivity可能失败,因为不含有Default这个category的Activity是无法接收隐式Intent


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值