原文地址:Getting Your SMS Apps Ready for KitKat

发送和接收短信是手机最基本的功能,很多的开发者也开发了很多成功的应用来增强Android这一方面的体验。你们当中的某些人可能基于隐藏API来开发短信应用,这种做法我们是不推荐的,因为隐藏API可能会有改变或者被移除,这样新的设备可能无法通过兼容性测试。因此,为了让你能够用到全面支持的API集来开发短信应用,以及短信应用体验的可预见性,Android 4.4 (KitKat)公开了现有的API并且增加了默认短信应用的概念,也就是说用户可以在系统设置中进行选择默认短信。

这意味着如果你在之前的Android版本中使用了隐藏API,你需要对你的应用进行一些调整以便让你的应用可以在今年晚些时候Android 4.4发布之后能够在Android4.4上继续使用。

让你的应用成为默认短信

在Android 4.4上,只有一个应用能接收到新增的SMS_DELIVER_ACTION intent,这个intent是当系统接收到新短信时用来发送广播的。哪个应用接收这个广播取决于用户在系统设置里选择了哪个应用作为默认短信应用。同样的,也只有默认的短信应用能在系统接收到新彩信的时候接收到Android
4.4新增加的WAP_PUSH_DELIVER_ACTION intent。

其他只想读取新信息的应用可以接收SMS_RECEIVED_ACTION广播,这个广播也是系统接收到新短信时发送的。但是只有接收到SMS_DELIVER_ACTION的应用(用户指定的默认短信应用)可以写入由android.provider.Telephony类和子类定义的SMS
Provider。因此,尽快升级你的短信应用让它可以成为默认短信应用是很重要的,因为就算你现有的应用不会在Android 4.4的设备上crash,但它尝试写入SMS Provider的时候会在没有提示的情况下失败。

为了让你的应用在系统设置中作为一个可选的默认短信应用,你的manifest文件必须声明一些特定的内容。所以你必须为你的应用更新以下内容:

  • 在一个broadcast receiver中包含一个SMS_DELIVER_ACTION("android.provider.Telephony.SMS_DELIVER")的intent
    filter。这个broadcast receiver同样需要BROADCAST_SMS权限。

    这让你的应用可以直接接收到进来的短信。

  • 在一个broadcast receiver包含一个WAP_PUSH_DELIVER_ACTION("android.provider.Telephony.WAP_PUSH_DELIVER")的intent
    filter,MIME类型是"application/vnd.wap.mms-message"。这个broadcast receiver同样需要BROADCAST_WAP_PUSH权限。

    这让你的应用可以直接接收到进来的彩信。

  • 在你用来发送新信息的activity中包含一个ACTION_SENDTO("android.intent.action.SENDTO")的intent
    filter,schemas为sms:, smsto:, mms:, 和mmsto:。

    这让你的应用可以接收到其他想发送信息的应用请求的intent。

  • 在一个service里面包含一个ACTION_RESPONSE_VIA_MESSAGE("android.intent.action.RESPOND_VIA_MESSAGE")的intent
    filter,schemas是sms:, smsto:, mms:, 和 mmsto:。这个service同样需要SEND_RESPOND_VIA_MESSAGE权限。

    这让用户在来电的时候用你的应用进行即时的短信息回复。

举个例子,这是一个含有必要组件和intent filter的manifest文件:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<manifest>
...
<application>
<!-- BroadcastReceiver that listens for incoming SMS messages -->
<receiver android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver> <!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver android:name=".MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver> <!-- Activity that allows the user to send new SMS/MMS messages -->
<activity android:name=".ComposeSmsActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity> <!-- Service that delivers messages from the phone "quick response" -->
<service android:name=".HeadlessSmsSendService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
</manifest>

现有所有接收带SMS_RECEIVED_ACTION这个filter的广播的应用可以照常的在Android 4.4上工作,但只能作为新信息的查看者,因为除非你的应用也能接收到SMS_DELIVER_ACTION广播,否则你无法在Android 4.4上写入SMS Provider。

从Android 4.4开始,你应该停止监听SMS_RECEIVED_ACTION广播,你可以通过运行时来检查Android平台的版本,然后通过PackageManager.setComponentEnabledSetting()来禁用掉接收SMS_RECEIVED_ACTION的broadcast receiver。当然如果你的应用只需要读取一些特定的短信息比如用来做电话号码校验的,你也可以继续监听这个广播。如果你在Android 4.4上确实需要处理SMS_RECEIVED_ACTION这个intent,那么不要调用API取消掉这个broadcast,因为别的应用可能也会需要接收这个广播。

提示:要区分这两个短信广播,可以想象成SMS_RECEIVED_ACTION只是简单地说“嘿,系统接收到一条短信”而SMS_DELIVER_ACTION却是说“系统传递给你的应用一条短信,因为你是系统默认的短信应用”。

当不是默认短信应用时禁用掉相应的功能

当你的应用不是当前系统默认的短信应用,那么把你应用发送新信息的功能禁用掉是很重要的。因为你无法写入SMS Provider,所有你发送的信息在用户默认的短信应用中都不可见。所以当你的activity resume的时候你可以通过查询Telephony.Sms.getDefaultSmsPackage()来检查你的应用是不是默认的短信应用,这个方法返回当前默认短信应用的包名。如果结果跟你的包名不匹配,那么就把发送信息的功能禁用掉。

要让你的应用能够接收和发送信息,你可以弹出一个让用户可以选择你的应用作为默认短信应用的系统对话框。要弹出这个对话框,调用startActivity(),用Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT这个intent作为参数,这个intent包含一对key-value值,分别是Sms.Intents.EXTRA_PACKAGE_NAME和你的包名。

要提供一个良好的用户体验,可以在你的activity resume的时候检查默认的短信应用,并且修改你的UI,把让用户修改默认短信应用这样一个信息给包括进来。比如,你的Activity可能会包括像下面这样的代码:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class ComposeSmsActivity extends Activity {

    @Override
protected void onResume() {
super.onResume(); final String myPackageName = getPackageName();
if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {
// App is not default.
// Show the "not currently set as the default SMS app" interface
View viewGroup = findViewById(R.id.not_default_app);
viewGroup.setVisibility(View.VISIBLE); // Set up a button that allows the user to change the default SMS app
Button button = (Button) findViewById(R.id.change_default_app);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent =
new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
myPackageName);
startActivity(intent);
}
});
} else {
// App is the default.
// Hide the "not currently set as the default SMS app" interface
View viewGroup = findViewById(R.id.not_default_app);
viewGroup.setVisibility(View.GONE);
}
}
}

给短信备份还原类应用的建议

由于写SMS Provider这样一个功能局限在用户选择的默认短信应用,当前所有只为短信备份还原设计的应用在Android 4.4上会无法还原短信。一个备份还原短信的应用同样需要被设置成默认的短信应用才能写入短信到SMS Provider当中去。当然,一个应用如果没有发送和接收短信的功能,那么它也不应该一直被设置成默认短信应用。所以当用户打开你的应用准备做一次性还原操作时,你可以根据以下的设计提供一个功能性的UI体验:

  1. 查询当前默认的短信应用包名并把包名保存起来。

    String defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(context);

  2. 请求用户把你的应用设置成默认短信应用以便进行短信还原(你必须作为默认短信应用才可以写入数据到SMS Provider中)。

1
2
3
Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, context.getPackageName());
startActivity(intent);
  1. 当你还原完所有短信之后,请求用户把步骤一保存的应用设置回默认短信应用。
1
2
3
Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, defaultSmsApp);
startActivity(intent);

准备升级你的短信应用

为了给你的用户提供最好的Android体验,我们建议你尽可能快的升级你的应用。为了帮助你做出调整,我们马上会提供Android 4.4必要的SDK组件以便让你能编译和测试你在Android 4.4上做出的修改。敬请期待!

让你的短信应用迎接Android 4.4(KitKat)的更多相关文章

  1. 做好准备,让你的短信应用迎接Android 4.4(KitKat)

    Android团队通过Android开发博客透漏今年会放出Android 4.4 (KitKat) ,同时更新了 SMS 的部分API.博客上讲只有default SMS app才能对短信数据库有写权 ...

  2. 无废话Android之常见adb指令、电话拨号器、点击事件的4种写法、短信发送器、Android 中各种布局(1)

    1.Android是什么 手机设备的软件栈,包括一个完整的操作系统.中间件.关键的应用程序,底层是linux内核,安全管理.内存管理.进程管理.电源管理.硬件驱动 2.Dalvik VM 和 JVM ...

  3. Android4.4 往短信收件箱中插入自定义短信(伪造短信)

    这段时间稍微有点空闲,把前一段学习Android做过的一些小项目整理整理.虽然没有什么工程量很大的项目,但是对于一个新手,解决这些问题还是花了一段时间.感觉还是非常有记录的意义呢~~~么么哒*—* 今 ...

  4. 转载:Android自动化测试- 自动获取短信验证码

    前言:android应用的自动化测试必然会涉及到注册登录功能,而许多的注册登录或修改密码功能常常需要输入短信验证码,因此有必要能够自动获得下发的短信验证码. 主要就是实时获取短信信息. android ...

  5. android自动获取短信验证码

    前言:android应用的自动化测试必然会涉及到注册登录功能,而许多的注册登录或修改密码功能常常需要输入短信验证码,因此有必要能够自动获得下发的短信验证码.主要就是实时获取短信信息.android上获 ...

  6. Android接收短信

    Android收到短信时会广播android.provider.Telephony.SMS_RECEIVED消息,因此只要定义一个Receiver,收听该消息,就能接收短信. <receiver ...

  7. java攻城师之路(Android篇)--搭建开发环境、拨打电话、发送短信、布局例子

    一.搭建开发环境 1.所需资源 JDK6以上 Eclipse3.6以上 SDK17, 2.3.3 ADT17 2.安装注意事项 不要使用中文路径 如果模拟器默认路径包含中文, 可以设置android_ ...

  8. android 入门 002 (拨打电话,发送短信)

    一.拨打电话 1.首先做好界面,代码如下: layout =>activity_main.xml 中 <LinearLayout xmlns:android="http://sc ...

  9. Android学习4—短信发送器的实现

    界面预览: 由图中可以看出,此APP需要的组件有:两个TextView,一个用于显示手机号码的标题,另一个用于显示短信内容的标题.                                    ...

随机推荐

  1. MYSQL的全表扫描,主键索引(聚集索引、第一索引),非主键索引(非聚集索引、第二索引),覆盖索引四种不同查询的分析

    文章出处:http://inter12.iteye.com/blog/1430144 MYSQL的全表扫描,主键索引(聚集索引.第一索引),非主键索引(非聚集索引.第二索引),覆盖索引四种不同查询的分 ...

  2. Ajax异步的回调函数执行了多遍

    问题: 在做下拉滚动加载时(类似于qq空间下拉加载),数据向下滚动一次,就会加载一次,即append一下,跟踪js后,发现回调函数执行了多次,导致append将上次的append结果append上了, ...

  3. Microsoft_Sql_Server_2008:无法对数据库执行删除,因为它正用于复制

    解决办法: sp_removedbreplication'StationErp' DROP DATABASE StationErp

  4. 0基础学习ios开发笔记第二天

    C语言的基本结构 c语言的入口函数是main函数. main函数的返回值行业标准是int return 数字:返回值 每条语句最后以分号结尾 注释:行注释.块注释 int main(void) { / ...

  5. C#微信开发之旅--基本信息的回复

    上一篇说到配置和验证<C#微信开发之旅--准备阶段> 下面来实现一下简单的信息回复. 也就是接收XML,返回XML 可以去看下微信开发文档的说明:http://mp.weixin.qq.c ...

  6. js hashMap

    /** * MAP对象,实现MAP功能 * * 接口: * size() 获取MAP元素个数 * isEmpty() 判断MAP是否为空 * clear() 删除MAP所有元素 * put(key, ...

  7. 安装hadoop多节点 各种整理

    ubuntu烧制usb启动盘链接: 点击打开链接https://help.ubuntu.com/community/Installation/FromUSBStick ubuntu磁盘分区: 点击打开 ...

  8. nodejs实现单文件上传。

    new了formidable的一个实例. formidable模块可以直接捕获当前数据流的状态并返回文件路径. 主要使用了file事件和end事件. var form = new formidable ...

  9. javascript 单行向上滚动文字

    <html><head><meta http-equiv="Content-Type" content="text/html; charse ...

  10. NetSerialComm的基本使用方法

    近期搞一个com口传输的小项目,原来认为是一个挺简单的一个小功能,结果生产商发来com以后直接傻眼了,还要对相关的硬件流进行处理 如下 // 硬件流控制设置 dcb.fOutxCtsFlow = FA ...