|
|
@@ -1,127 +1,131 @@
|
|
|
-package com.example.uicceditor;
|
|
|
+package com.example.uicceditor
|
|
|
|
|
|
-import android.content.Intent;
|
|
|
-import android.telephony.PhoneNumberUtils;
|
|
|
-import android.telephony.SmsManager;
|
|
|
-import android.util.Log;
|
|
|
+import android.content.Intent
|
|
|
+import android.telephony.PhoneNumberUtils
|
|
|
+import android.telephony.SmsManager
|
|
|
+import android.util.Log
|
|
|
+import java.io.ByteArrayOutputStream
|
|
|
+import java.io.IOException
|
|
|
+import java.io.UnsupportedEncodingException
|
|
|
+import java.nio.charset.StandardCharsets
|
|
|
+import java.util.Calendar
|
|
|
+import java.util.GregorianCalendar
|
|
|
|
|
|
-import java.io.ByteArrayOutputStream;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.UnsupportedEncodingException;
|
|
|
-import java.lang.reflect.Method;
|
|
|
-import java.nio.charset.StandardCharsets;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.Calendar;
|
|
|
-import java.util.GregorianCalendar;
|
|
|
-
|
|
|
-public class SmsUtils {
|
|
|
+object SmsUtils {
|
|
|
// 获取对应的Intent数据
|
|
|
- public static Intent getSmsIntent(String number, String body) {
|
|
|
- SmsManager smsManager = SmsManager.getDefault();
|
|
|
+ fun getSmsIntent(number: String, body: String?): Intent {
|
|
|
+ val smsManager = SmsManager.getDefault()
|
|
|
// 防止短信过长
|
|
|
- ArrayList<String> messages = smsManager.divideMessage(body);
|
|
|
- int size = messages.size();
|
|
|
- Object[] objArray = new Object[size];
|
|
|
- for (int i = 0; i < size; ++i) {
|
|
|
- byte[] pduu = createFakeSms(number, messages.get(i));
|
|
|
- objArray[i] = pduu;
|
|
|
+ val messages = smsManager.divideMessage(body)
|
|
|
+ val size = messages.size
|
|
|
+ val objArray = arrayOfNulls<Any>(size)
|
|
|
+ for (i in 0 until size) {
|
|
|
+ val pduu = createFakeSms(number, messages[i])
|
|
|
+ objArray[i] = pduu
|
|
|
}
|
|
|
- Intent intent = new Intent();
|
|
|
- intent.setAction("android.provider.Telephony.SMS_DELIVER");
|
|
|
- intent.putExtra("pdus", objArray);
|
|
|
- intent.putExtra("format", "3gpp");
|
|
|
- intent.putExtra("subscription", 12);
|
|
|
- return intent;
|
|
|
+ val intent = Intent()
|
|
|
+ intent.setAction("android.provider.Telephony.SMS_DELIVER")
|
|
|
+ intent.putExtra("pdus", objArray)
|
|
|
+ intent.putExtra("format", "3gpp")
|
|
|
+ intent.putExtra("subscription", 12)
|
|
|
+ return intent
|
|
|
}
|
|
|
|
|
|
// 创建pdu
|
|
|
- public static byte[] createFakeSms(String sender, String body) {
|
|
|
- byte[] pdu = null;
|
|
|
- byte[] scBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD("0000000000");
|
|
|
- byte[] senderBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(sender);
|
|
|
- int lsmcs = scBytes.length;
|
|
|
+ fun createFakeSms(sender: String, body: String): ByteArray? {
|
|
|
+ var pdu: ByteArray? = null
|
|
|
+ val scBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD("0000000000")
|
|
|
+ val senderBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(sender)
|
|
|
+ val lsmcs = scBytes.size
|
|
|
// 时间处理,包括年月日时分秒以及时区和夏令时
|
|
|
- byte[] dateBytes = new byte[7];
|
|
|
- Calendar calendar = new GregorianCalendar();
|
|
|
- dateBytes[0] = reverseByte((byte) (calendar.get(Calendar.YEAR)));
|
|
|
- dateBytes[1] = reverseByte((byte) (calendar.get(Calendar.MONTH) + 1));
|
|
|
- dateBytes[2] = reverseByte((byte) (calendar.get(Calendar.DAY_OF_MONTH)));
|
|
|
- dateBytes[3] = reverseByte((byte) (calendar.get(Calendar.HOUR_OF_DAY)));
|
|
|
- dateBytes[4] = reverseByte((byte) (calendar.get(Calendar.MINUTE)));
|
|
|
- dateBytes[5] = reverseByte((byte) (calendar.get(Calendar.SECOND)));
|
|
|
- dateBytes[6] = reverseByte((byte) ((calendar.get(Calendar.ZONE_OFFSET)
|
|
|
- + calendar.get(Calendar.DST_OFFSET)) / (60 * 1000 * 15)));
|
|
|
+ val dateBytes = ByteArray(7)
|
|
|
+ val calendar: Calendar = GregorianCalendar()
|
|
|
+ dateBytes[0] = reverseByte(calendar[Calendar.YEAR].toByte())
|
|
|
+ dateBytes[1] = reverseByte((calendar[Calendar.MONTH] + 1).toByte())
|
|
|
+ dateBytes[2] = reverseByte(calendar[Calendar.DAY_OF_MONTH].toByte())
|
|
|
+ dateBytes[3] = reverseByte(calendar[Calendar.HOUR_OF_DAY].toByte())
|
|
|
+ dateBytes[4] = reverseByte(calendar[Calendar.MINUTE].toByte())
|
|
|
+ dateBytes[5] = reverseByte(calendar[Calendar.SECOND].toByte())
|
|
|
+ dateBytes[6] = reverseByte(
|
|
|
+ ((calendar[Calendar.ZONE_OFFSET]
|
|
|
+ + calendar[Calendar.DST_OFFSET]) / (60 * 1000 * 15)).toByte()
|
|
|
+ )
|
|
|
try {
|
|
|
- ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
|
|
- bo.write(lsmcs);// 短信服务中心长度
|
|
|
- bo.write(scBytes);// 短信服务中心号码
|
|
|
- bo.write(0x04);
|
|
|
- bo.write((byte) sender.length());// 发送方号码长度
|
|
|
- bo.write(senderBytes);// 发送方号码
|
|
|
- bo.write(0x00);// 协议标示,00为普通GSM,点对点方式
|
|
|
+ val bo = ByteArrayOutputStream()
|
|
|
+ bo.write(lsmcs) // 短信服务中心长度
|
|
|
+ bo.write(scBytes) // 短信服务中心号码
|
|
|
+ bo.write(0x04)
|
|
|
+ bo.write(sender.length.toByte().toInt()) // 发送方号码长度
|
|
|
+ bo.write(senderBytes) // 发送方号码
|
|
|
+ bo.write(0x00) // 协议标示,00为普通GSM,点对点方式
|
|
|
try {
|
|
|
- String className = "com.android.internal.telephony.GsmAlphabet";
|
|
|
- Class<?> clazz = Class.forName(className);
|
|
|
- Method method = clazz.getMethod("stringToGsm7BitPacked", new Class[]{String.class});
|
|
|
- method.setAccessible(true);
|
|
|
- byte[] bodybytes = (byte[]) method.invoke(null, body);
|
|
|
+ val className = "com.android.internal.telephony.GsmAlphabet"
|
|
|
+ val clazz = Class.forName(className)
|
|
|
+ val method = clazz.getMethod(
|
|
|
+ "stringToGsm7BitPacked", *arrayOf<Class<*>>(
|
|
|
+ String::class.java
|
|
|
+ )
|
|
|
+ )
|
|
|
+ method.isAccessible = true
|
|
|
+ val bodybytes = method.invoke(null, body) as ByteArray
|
|
|
|
|
|
- byte[] bodybytes1 = GsmAlphabet.stringToGsm7BitPacked(body);
|
|
|
+ val bodybytes1 = GsmAlphabet.stringToGsm7BitPacked(body)
|
|
|
|
|
|
// compare the two byte arrays
|
|
|
- if (bodybytes1.length != bodybytes.length) {
|
|
|
- System.out.println("The two byte arrays are not the same length.");
|
|
|
+ if (bodybytes1.size != bodybytes.size) {
|
|
|
+ println("The two byte arrays are not the same length.")
|
|
|
} else {
|
|
|
- boolean same = true;
|
|
|
- for (int i = 0; i < bodybytes1.length; i++) {
|
|
|
+ var same = true
|
|
|
+ for (i in bodybytes1.indices) {
|
|
|
if (bodybytes1[i] != bodybytes[i]) {
|
|
|
- same = false;
|
|
|
- break;
|
|
|
+ same = false
|
|
|
+ break
|
|
|
}
|
|
|
}
|
|
|
- Log.d("stringToGsm7BitPacked", "createFakeSms: " + same);
|
|
|
+ Log.d("stringToGsm7BitPacked", "createFakeSms: $same")
|
|
|
}
|
|
|
|
|
|
- bo.write(0xf1); // encoding: 0 for default 7bit
|
|
|
- bo.write(dateBytes);
|
|
|
- bo.write(bodybytes);
|
|
|
- } catch (Exception e) {
|
|
|
+ bo.write(0xf1) // encoding: 0 for default 7bit
|
|
|
+ bo.write(dateBytes)
|
|
|
+ bo.write(bodybytes)
|
|
|
+ } catch (e: Exception) {
|
|
|
// 下面是UCS-2编码的处理,中文短信就需要用此种方式
|
|
|
- byte[] bodyBytes = encodeUCS2(body, null);
|
|
|
- bo.write(0x08); // encoding: 8 for UCS-2
|
|
|
- bo.write(dateBytes);
|
|
|
- bo.write(bodyBytes);// 其中encodeUCS2是从系统中复制过来的,并不是我写的
|
|
|
+ val bodyBytes = encodeUCS2(body, null)
|
|
|
+ bo.write(0x08) // encoding: 8 for UCS-2
|
|
|
+ bo.write(dateBytes)
|
|
|
+ bo.write(bodyBytes) // 其中encodeUCS2是从系统中复制过来的,并不是我写的
|
|
|
// 源码具体位置在
|
|
|
// frameworks/base/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
|
|
|
}
|
|
|
|
|
|
- pdu = bo.toByteArray();
|
|
|
- } catch (IOException e) {
|
|
|
+ pdu = bo.toByteArray()
|
|
|
+ } catch (e: IOException) {
|
|
|
}
|
|
|
- return pdu;
|
|
|
+ return pdu
|
|
|
}
|
|
|
|
|
|
- private static byte reverseByte(byte b) {
|
|
|
- return (byte) ((b & 0xF0) >> 4 | (b & 0x0F) << 4);
|
|
|
+ private fun reverseByte(b: Byte): Byte {
|
|
|
+ return ((b.toInt() and 0xF0) shr 4 or ((b.toInt() and 0x0F) shl 4)).toByte()
|
|
|
}
|
|
|
|
|
|
- private static byte[] encodeUCS2(String message, byte[] header) throws UnsupportedEncodingException {
|
|
|
- byte[] userData, textPart;
|
|
|
- textPart = message.getBytes(StandardCharsets.UTF_16BE);
|
|
|
+ @Throws(UnsupportedEncodingException::class)
|
|
|
+ private fun encodeUCS2(message: String, header: ByteArray?): ByteArray {
|
|
|
+ val userData: ByteArray
|
|
|
+ val textPart = message.toByteArray(StandardCharsets.UTF_16BE)
|
|
|
|
|
|
if (header != null) {
|
|
|
// Need 1 byte for UDHL
|
|
|
- userData = new byte[header.length + textPart.length + 1];
|
|
|
+ userData = ByteArray(header.size + textPart.size + 1)
|
|
|
|
|
|
- userData[0] = (byte) header.length;
|
|
|
- System.arraycopy(header, 0, userData, 1, header.length);
|
|
|
- System.arraycopy(textPart, 0, userData, header.length + 1, textPart.length);
|
|
|
+ userData[0] = header.size.toByte()
|
|
|
+ System.arraycopy(header, 0, userData, 1, header.size)
|
|
|
+ System.arraycopy(textPart, 0, userData, header.size + 1, textPart.size)
|
|
|
} else {
|
|
|
- userData = textPart;
|
|
|
+ userData = textPart
|
|
|
}
|
|
|
- byte[] ret = new byte[userData.length + 1];
|
|
|
- ret[0] = (byte) (userData.length & 0xff);
|
|
|
- System.arraycopy(userData, 0, ret, 1, userData.length);
|
|
|
- return ret;
|
|
|
+ val ret = ByteArray(userData.size + 1)
|
|
|
+ ret[0] = (userData.size and 0xff).toByte()
|
|
|
+ System.arraycopy(userData, 0, ret, 1, userData.size)
|
|
|
+ return ret
|
|
|
}
|
|
|
}
|