有时候我们程序需要添加连到到其它应用程序中,比如做一个定时发送短信的程序,想在联系人应用程序中选择send SMS/MMS时,出现我们自己的程序让用户选择是否发送定时短信。
要实现这种效果要用到intent-filter,关于intent-filter觉得写的最形象的一篇文章是http://www.roiding.com/index.php/archives/tag/intent-filter
俺是一个只会蛮干的粗人,理论在这就不多说,直接上代码。以后贴的代码都是在G1实机测试通过。
以上面那个在联系人应用程序中选择send SMS/MMS时,出现我们自己的程序让用户选择是否发送定时短信的效果为例,首先在我们需要接收短信程序发送过来的数据(如联系人的手机号码)的Acitivity中添加一个intent-filter
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<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" />
</intent-filter>
然后在Activity中用下面代码取得联系人APP传过来的用户手机号码
在android中用直接使用smsManager.sendTextMessage()方法发送中文或其它unicode字符会显示不正确。
目前来说想正确发送中文,需要自己构造PDU,然后在JAVA中用反射调用SmsManager的private sendRawPdu方法来实现。
参考:http://www.android123.com.cn/androidkaifa/180.html
上文中只说了PDU构造实现原理,具体怎么使用没有涉及。俺这再补一把,直接贴出代码。其实android本身SDK就有相应方法以UCS2编码发送,只是默认不会调用。
以下代码G1下测试通过
public class SmsHelper {
public static final int MAX_USER_DATA_BYTES = 140;
private Context mContext;
public SmsHelper(Context c) {
mContext = c;
}
public void sendUnicodeMessage(String phone, String text) {
SmsManager smsManager = SmsManager.getDefault();
Class clazz = smsManager.getClass();
try {
Class[] types = new Class[4];
types[0] = byte[].class;
types[1] = byte[].class;
types[2] = Class.forName("android.app.PendingIntent");
types[3] = Class.forName("android.app.PendingIntent");
Object[] params = new Object[4];
params[0] = null;
params[1] = getSubmitPdu(null, phone, text).encodedMessage;
params[2] = PendingIntent
.getBroadcast(mContext, 0, new Intent(), 0);
// params[2] = null;
params[3] = null;
Method m = clazz.getDeclaredMethod("sendRawPdu", types);
m.setAccessible(true);
m.invoke(smsManager, params);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public static SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, String message) {
if (message == null || destinationAddress == null) {
return null;
}
SubmitPdu ret = new SubmitPdu();
byte mtiByte = (byte) (0x01 | 0x00);
ByteArrayOutputStream bo = getSubmitPduHead(scAddress,
destinationAddress, mtiByte, false, ret);
byte[] userData, textPart;
// Encoding to the 7-bit alphabet failed. Let's see if we can
// send it as a UCS-2 encoded message
try {
textPart = message.getBytes("utf-16be");
} catch (UnsupportedEncodingException uex) {
uex.printStackTrace();
return null;
}
userData = textPart;
if (userData.length > MAX_USER_DATA_BYTES) {
// Message too long
return null;
}
// TP-Data-Coding-Scheme
// Class 3, UCS-2 encoding, uncompressed
bo.write(0x0b);
// (no TP-Validity-Period)
// TP-UDL
bo.write(userData.length);
bo.write(userData, 0, userData.length);
ret.encodedMessage = bo.toByteArray();
return ret;
}
private static ByteArrayOutputStream getSubmitPduHead(String scAddress,
String destinationAddress, byte mtiByte,
boolean statusReportRequested, SubmitPdu ret) {
ByteArrayOutputStream bo = new ByteArrayOutputStream(
MAX_USER_DATA_BYTES + 40);
// SMSC address with length octet, or 0
if (scAddress == null) {
ret.encodedScAddress = null;
} else {
ret.encodedScAddress = PhoneNumberUtils
.networkPortionToCalledPartyBCDWithLength(scAddress);
}
// TP-Message-Type-Indicator (and friends)
if (statusReportRequested) {
// Set TP-Status-Report-Request bit.
mtiByte |= 0x20;
}
bo.write(mtiByte);
// space for TP-Message-Reference
bo.write(0);
byte[] daBytes;
daBytes = PhoneNumberUtils
.networkPortionToCalledPartyBCD(destinationAddress);
// destination address length in BCD digits, ignoring TON byte and pad
// TODO Should be better.
bo.write((daBytes.length - 1) * 2
- ((daBytes[daBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0));
// destination address
bo.write(daBytes, 0, daBytes.length);
// TP-Protocol-Identifier
bo.write(0);
return bo;
}
}