您的位置:首页 > 其它

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

2016-02-01 16:47 507 查看

一.背景

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: