Loading src/java/android/provider/Telephony.java +22 −0 Original line number Diff line number Diff line Loading @@ -557,6 +557,28 @@ public final class Telephony { public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED"; /** * Broadcast Action: A new text based mock SMS message has been received * by the device. For development purpose only. The intent will have the * following extra values:</p> * * <ul> * <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs * that make up the message.</li> * </ul></p> * or</p> * <ul> * <li><em>scAddress</em> - The mock SC address. xe: +01123456789.</li> * <li><em>senderAddr</em> - The mock sender address. xe: +01123456789.</li> * <li><em>msg</em> - The mock message. Multiple SMS are sent if the * length of the message exceed the SMS maximum length.</li> * </ul> * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String MOCK_SMS_RECEIVED_ACTION = "android.provider.Telephony.MOCK_SMS_RECEIVED"; /** * Broadcast Action: A new WAP PUSH message has been received by the * device. The intent will have the following extra Loading src/java/com/android/internal/telephony/SMSDispatcher.java +269 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -49,10 +50,13 @@ import android.telephony.PhoneNumberUtils; import android.telephony.ServiceState; import android.telephony.SmsCbMessage; import android.telephony.SmsMessage; import android.telephony.SmsMessage.SubmitPdu; import android.telephony.TelephonyManager; import android.text.Html; import android.text.Spanned; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; import android.telephony.Rlog; import android.view.LayoutInflater; import android.view.View; Loading @@ -69,8 +73,11 @@ import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; import com.android.internal.util.HexDump; import java.io.ByteArrayOutputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.HashMap; import java.util.Random; Loading Loading @@ -154,6 +161,8 @@ public abstract class SMSDispatcher extends Handler { protected final WapPushOverSms mWapPush; private final MockSmsReceiver mMockSmsReceiver; protected static final Uri mRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw"); /** Maximum number of times to retry sending a failed SMS. */ Loading Loading @@ -221,6 +230,10 @@ public abstract class SMSDispatcher extends Handler { mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver); // Register the mock SMS receiver to simulate the reception of SMS mMockSmsReceiver = new MockSmsReceiver(); mMockSmsReceiver.registerReceiver(); createWakelock(); mSmsCapable = mContext.getResources().getBoolean( Loading Loading @@ -277,6 +290,7 @@ public abstract class SMSDispatcher extends Handler { @Override protected void finalize() { Rlog.d(TAG, "SMSDispatcher finalized"); mMockSmsReceiver.unregisterReceiver(); } Loading Loading @@ -1519,4 +1533,259 @@ public abstract class SMSDispatcher extends Handler { dispatch(intent, RECEIVE_SMS_PERMISSION, AppOpsManager.OP_RECEIVE_SMS); } } /** * A private class that allow simulating the receive of SMS.<br/> * <br/> * A developer must use {@link Context#sendBroadcast(Intent)}, using the action * {@link Intents#MOCK_SMS_RECEIVED_ACTION}. The application requires * {@linkplain "android.permission.SEND_MOCK_SMS"} permission.<br/> * <br/> * This receiver should be used in the next way:<br/> * <pre> * Intent in = new Intent(Intents.MOCK_SMS_RECEIVED_ACTION); * in.putExtra("scAddr", "+01123456789"); * in.putExtra("senderAddr", "+01123456789"); * in.putExtra("msg", "This is a mock SMS message."); * sendBroadcast(in); * </pre><br/> * or<br/> * <pre> * String pdu = "07914151551512f2040B916105551511f100006060605130308A04D4F29C0E"; * byte[][] pdus = new byte[1][]; * pdus[0] = HexDump.hexStringToByteArray(pdu); * Intent in = new Intent(Intents.MOCK_SMS_RECEIVED_ACTION); * intent.putExtra("pdus", pdus); * sendBroadcast(in); * </pre><br/> */ private final class MockSmsReceiver extends BroadcastReceiver { private static final String TAG = "MockSmsReceiver"; private static final String MOCK_ADDRESS = "+01123456789"; private static final String SEND_MOCK_SMS_PERMISSION = "android.permission.SEND_MOCK_SMS"; /** * Method that register the MockSmsReceiver class as a BroadcastReceiver */ public final void registerReceiver() { try { Handler handler = new Handler(); IntentFilter filter = new IntentFilter(); filter.addAction(Intents.MOCK_SMS_RECEIVED_ACTION); mContext.registerReceiver(this, filter, SEND_MOCK_SMS_PERMISSION, handler); Log.d(TAG, "Registered MockSmsReceiver"); } catch (Exception ex) { Log.e(TAG, "Failed to register MockSmsReceiver", ex); } } /** * Method that unregister the MockSmsReceiver class as a BroadcastReceiver */ public final void unregisterReceiver() { try { mContext.unregisterReceiver(this); } catch (Exception ex) { Log.e(TAG, "Failed to unregister MockSmsReceiver", ex); } } /** * {@inheritDoc} */ @Override public final void onReceive(Context context, Intent intent) { Log.d(TAG, "New mock SMS reception request. Intent: " + intent); try { // Check that developer option is enabled, and mock // messages are allowed boolean allowMockSMS = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ALLOW_MOCK_SMS, 0) == 1; if (!allowMockSMS) { // Mock SMS is not allowed. This Log.w(TAG, "Mock SMS is not allowed. Enable Mock SMS on Settings/Delevelopment."); return; } // Extract PDUs List<byte[][]> msgs = new ArrayList<byte[][]>(); Object[] messages = (Object[]) intent.getSerializableExtra("pdus"); if (messages != null && messages.length > 0) { // Use the PDUs from the intent byte[][] pdus = new byte[messages.length][]; for (int i = 0; i < messages.length; i++) { pdus[i] = (byte[]) messages[i]; } msgs.add(pdus); } else { // Build the PDUs from SMS data String scAddress = intent.getStringExtra("scAddr"); String senderAddress = intent.getStringExtra("senderAddr"); String msg = intent.getStringExtra("msg"); // Check that values are valid. Otherwise fill will default values if (TextUtils.isEmpty(scAddress)) { scAddress = MOCK_ADDRESS; } if (TextUtils.isEmpty(senderAddress)) { senderAddress = MOCK_ADDRESS; } if (TextUtils.isEmpty(msg)) { msg = "This is a mock SMS message."; } Log.d(TAG, String.format( "Mock SMS. scAddress: %s, senderAddress: %s, msg: %s", scAddress, senderAddress, msg)); // Fragment the text in message according to SMS length List<String> fragmentMsgs = android.telephony.SmsMessage.fragmentText(msg); for (String fragmentMsg : fragmentMsgs) { msgs.add(getPdus(scAddress, senderAddress, fragmentMsg)); } } // How messages are going to send? Log.d(TAG, String.format("Mock SMS. Number of msg: %d", msgs.size())); // Send messages for (byte[][] pdus : msgs) { Intent mockSmsIntent = new Intent(Intents.SMS_RECEIVED_ACTION); mockSmsIntent.putExtra("pdus", pdus ); mockSmsIntent.putExtra("format", android.telephony.SmsMessage.FORMAT_3GPP ); dispatch(mockSmsIntent, SMSDispatcher.RECEIVE_SMS_PERMISSION, AppOpsManager.OP_RECEIVE_SMS); } // Set result (messages were sent) setResultCode(android.app.Activity.RESULT_OK); } catch (Exception ex) { Log.e(TAG, "Failed to dispatch SMS", ex); // Set result (messages were not sent) setResultCode(android.app.Activity.RESULT_CANCELED); } } /** * Method that convert the basic SMS string data to a PDUs messages * * @param scAddress The mock the SC address * @param senderAddress The mock the sender address * @param msg The mock message body * @return byte[] The array of bytes of the PDU */ private byte[][] getPdus(String scAddress, String senderAddress, String msg) { // Get a SubmitPdu (use a phone number to get a valid pdu) SubmitPdu submitPdu = android.telephony.SmsMessage.getSubmitPdu( scAddress, MOCK_ADDRESS, msg, false); // Translate the submit data to a received PDU int dataLen = android.telephony.SmsMessage.calculateLength(msg, true)[1]; // Locate protocol + data encoding scheme byte[] pds = {(byte)0, (byte)0, (byte)dataLen}; int dataPos = new String(submitPdu.encodedMessage).indexOf(new String(pds), 4) + 2; // Set arrays dimension byte[] encSc = submitPdu.encodedScAddress; byte[] encMsg = new byte[submitPdu.encodedMessage.length - dataPos]; System.arraycopy( submitPdu.encodedMessage, dataPos, encMsg, 0, submitPdu.encodedMessage.length - dataPos); byte[] encSender = null; // Check if the senderAddress is a vanish number if (!PhoneNumberUtils.isWellFormedSmsAddress(senderAddress)) { try { byte[] sender7BitPacked = GsmAlphabet.stringToGsm7BitPacked(senderAddress); encSender = new byte[2 + sender7BitPacked.length - 1]; encSender[0] = (byte)((sender7BitPacked.length - 1) * 2); encSender[1] = (byte)0xD0; // Alphabetic sender System.arraycopy(sender7BitPacked, 1, encSender, 2, sender7BitPacked.length - 1); } catch (EncodeException e) { Log.e(TAG, "Failed to decode sender address. Using default.", e); encSender = new byte[dataPos - 4]; System.arraycopy( submitPdu.encodedMessage, 2, encSender, 0, dataPos - 4); } } else { encSender = new byte[dataPos - 4]; System.arraycopy( submitPdu.encodedMessage, 2, encSender, 0, dataPos - 4); } byte[] encTs = bcdTimestamp(); byte[] pdu = new byte[ encSc.length + 1 + /** SMS-DELIVER **/ encSender.length + 2 + /** Protocol + Data Encoding Scheme **/ encTs.length + encMsg.length]; // Copy the SC address int c = 0; System.arraycopy(encSc, 0, pdu, c, encSc.length); c+=encSc.length; // SMS-DELIVER pdu[c] = 0x04; c++; // Sender System.arraycopy(encSender, 0, pdu, c, encSender.length); c+=encSender.length; // Protocol + Data encoding scheme pdu[c] = 0x00; c++; pdu[c] = 0x00; c++; // Timestamp System.arraycopy(encTs, 0, pdu, c, encTs.length); c+=encTs.length; // Message System.arraycopy(encMsg, 0, pdu, c, encMsg.length); // Return the PDUs return new byte[][]{pdu}; } /** * Method that return the current timestamp in a BCD format * * @return byte[] The BCD timestamp */ private byte[] bcdTimestamp() { Calendar c = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("yy"); //$NON-NLS-1$ SimpleDateFormat sdf2 = new SimpleDateFormat("Z"); //$NON-NLS-1$ byte year = (byte)Integer.parseInt( String.valueOf(Integer.parseInt(sdf.format(c.getTime()))), 16); byte month = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.MONTH) + 1), 16); byte day = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.DAY_OF_MONTH)), 16); byte hour = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.HOUR)), 16); byte minute = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.MINUTE)), 16); byte second = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.SECOND)), 16); String tz = sdf2.format(c.getTime()).substring(1); int timezone = Integer.parseInt(tz) / 100; if (timezone < 0) { timezone += 0x80; } byte[] data = {year, month, day, hour, minute, second, 0}; byte[] ts = IccUtils.hexStringToBytes(IccUtils.bcdToString(data, 0, data.length)); ts[6] = (byte)Integer.parseInt(String.valueOf(timezone), 16); return ts; } } } Loading
src/java/android/provider/Telephony.java +22 −0 Original line number Diff line number Diff line Loading @@ -557,6 +557,28 @@ public final class Telephony { public static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED"; /** * Broadcast Action: A new text based mock SMS message has been received * by the device. For development purpose only. The intent will have the * following extra values:</p> * * <ul> * <li><em>pdus</em> - An Object[] od byte[]s containing the PDUs * that make up the message.</li> * </ul></p> * or</p> * <ul> * <li><em>scAddress</em> - The mock SC address. xe: +01123456789.</li> * <li><em>senderAddr</em> - The mock sender address. xe: +01123456789.</li> * <li><em>msg</em> - The mock message. Multiple SMS are sent if the * length of the message exceed the SMS maximum length.</li> * </ul> * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String MOCK_SMS_RECEIVED_ACTION = "android.provider.Telephony.MOCK_SMS_RECEIVED"; /** * Broadcast Action: A new WAP PUSH message has been received by the * device. The intent will have the following extra Loading
src/java/com/android/internal/telephony/SMSDispatcher.java +269 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; Loading @@ -49,10 +50,13 @@ import android.telephony.PhoneNumberUtils; import android.telephony.ServiceState; import android.telephony.SmsCbMessage; import android.telephony.SmsMessage; import android.telephony.SmsMessage.SubmitPdu; import android.telephony.TelephonyManager; import android.text.Html; import android.text.Spanned; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; import android.telephony.Rlog; import android.view.LayoutInflater; import android.view.View; Loading @@ -69,8 +73,11 @@ import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails; import com.android.internal.util.HexDump; import java.io.ByteArrayOutputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.HashMap; import java.util.Random; Loading Loading @@ -154,6 +161,8 @@ public abstract class SMSDispatcher extends Handler { protected final WapPushOverSms mWapPush; private final MockSmsReceiver mMockSmsReceiver; protected static final Uri mRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw"); /** Maximum number of times to retry sending a failed SMS. */ Loading Loading @@ -221,6 +230,10 @@ public abstract class SMSDispatcher extends Handler { mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver); // Register the mock SMS receiver to simulate the reception of SMS mMockSmsReceiver = new MockSmsReceiver(); mMockSmsReceiver.registerReceiver(); createWakelock(); mSmsCapable = mContext.getResources().getBoolean( Loading Loading @@ -277,6 +290,7 @@ public abstract class SMSDispatcher extends Handler { @Override protected void finalize() { Rlog.d(TAG, "SMSDispatcher finalized"); mMockSmsReceiver.unregisterReceiver(); } Loading Loading @@ -1519,4 +1533,259 @@ public abstract class SMSDispatcher extends Handler { dispatch(intent, RECEIVE_SMS_PERMISSION, AppOpsManager.OP_RECEIVE_SMS); } } /** * A private class that allow simulating the receive of SMS.<br/> * <br/> * A developer must use {@link Context#sendBroadcast(Intent)}, using the action * {@link Intents#MOCK_SMS_RECEIVED_ACTION}. The application requires * {@linkplain "android.permission.SEND_MOCK_SMS"} permission.<br/> * <br/> * This receiver should be used in the next way:<br/> * <pre> * Intent in = new Intent(Intents.MOCK_SMS_RECEIVED_ACTION); * in.putExtra("scAddr", "+01123456789"); * in.putExtra("senderAddr", "+01123456789"); * in.putExtra("msg", "This is a mock SMS message."); * sendBroadcast(in); * </pre><br/> * or<br/> * <pre> * String pdu = "07914151551512f2040B916105551511f100006060605130308A04D4F29C0E"; * byte[][] pdus = new byte[1][]; * pdus[0] = HexDump.hexStringToByteArray(pdu); * Intent in = new Intent(Intents.MOCK_SMS_RECEIVED_ACTION); * intent.putExtra("pdus", pdus); * sendBroadcast(in); * </pre><br/> */ private final class MockSmsReceiver extends BroadcastReceiver { private static final String TAG = "MockSmsReceiver"; private static final String MOCK_ADDRESS = "+01123456789"; private static final String SEND_MOCK_SMS_PERMISSION = "android.permission.SEND_MOCK_SMS"; /** * Method that register the MockSmsReceiver class as a BroadcastReceiver */ public final void registerReceiver() { try { Handler handler = new Handler(); IntentFilter filter = new IntentFilter(); filter.addAction(Intents.MOCK_SMS_RECEIVED_ACTION); mContext.registerReceiver(this, filter, SEND_MOCK_SMS_PERMISSION, handler); Log.d(TAG, "Registered MockSmsReceiver"); } catch (Exception ex) { Log.e(TAG, "Failed to register MockSmsReceiver", ex); } } /** * Method that unregister the MockSmsReceiver class as a BroadcastReceiver */ public final void unregisterReceiver() { try { mContext.unregisterReceiver(this); } catch (Exception ex) { Log.e(TAG, "Failed to unregister MockSmsReceiver", ex); } } /** * {@inheritDoc} */ @Override public final void onReceive(Context context, Intent intent) { Log.d(TAG, "New mock SMS reception request. Intent: " + intent); try { // Check that developer option is enabled, and mock // messages are allowed boolean allowMockSMS = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ALLOW_MOCK_SMS, 0) == 1; if (!allowMockSMS) { // Mock SMS is not allowed. This Log.w(TAG, "Mock SMS is not allowed. Enable Mock SMS on Settings/Delevelopment."); return; } // Extract PDUs List<byte[][]> msgs = new ArrayList<byte[][]>(); Object[] messages = (Object[]) intent.getSerializableExtra("pdus"); if (messages != null && messages.length > 0) { // Use the PDUs from the intent byte[][] pdus = new byte[messages.length][]; for (int i = 0; i < messages.length; i++) { pdus[i] = (byte[]) messages[i]; } msgs.add(pdus); } else { // Build the PDUs from SMS data String scAddress = intent.getStringExtra("scAddr"); String senderAddress = intent.getStringExtra("senderAddr"); String msg = intent.getStringExtra("msg"); // Check that values are valid. Otherwise fill will default values if (TextUtils.isEmpty(scAddress)) { scAddress = MOCK_ADDRESS; } if (TextUtils.isEmpty(senderAddress)) { senderAddress = MOCK_ADDRESS; } if (TextUtils.isEmpty(msg)) { msg = "This is a mock SMS message."; } Log.d(TAG, String.format( "Mock SMS. scAddress: %s, senderAddress: %s, msg: %s", scAddress, senderAddress, msg)); // Fragment the text in message according to SMS length List<String> fragmentMsgs = android.telephony.SmsMessage.fragmentText(msg); for (String fragmentMsg : fragmentMsgs) { msgs.add(getPdus(scAddress, senderAddress, fragmentMsg)); } } // How messages are going to send? Log.d(TAG, String.format("Mock SMS. Number of msg: %d", msgs.size())); // Send messages for (byte[][] pdus : msgs) { Intent mockSmsIntent = new Intent(Intents.SMS_RECEIVED_ACTION); mockSmsIntent.putExtra("pdus", pdus ); mockSmsIntent.putExtra("format", android.telephony.SmsMessage.FORMAT_3GPP ); dispatch(mockSmsIntent, SMSDispatcher.RECEIVE_SMS_PERMISSION, AppOpsManager.OP_RECEIVE_SMS); } // Set result (messages were sent) setResultCode(android.app.Activity.RESULT_OK); } catch (Exception ex) { Log.e(TAG, "Failed to dispatch SMS", ex); // Set result (messages were not sent) setResultCode(android.app.Activity.RESULT_CANCELED); } } /** * Method that convert the basic SMS string data to a PDUs messages * * @param scAddress The mock the SC address * @param senderAddress The mock the sender address * @param msg The mock message body * @return byte[] The array of bytes of the PDU */ private byte[][] getPdus(String scAddress, String senderAddress, String msg) { // Get a SubmitPdu (use a phone number to get a valid pdu) SubmitPdu submitPdu = android.telephony.SmsMessage.getSubmitPdu( scAddress, MOCK_ADDRESS, msg, false); // Translate the submit data to a received PDU int dataLen = android.telephony.SmsMessage.calculateLength(msg, true)[1]; // Locate protocol + data encoding scheme byte[] pds = {(byte)0, (byte)0, (byte)dataLen}; int dataPos = new String(submitPdu.encodedMessage).indexOf(new String(pds), 4) + 2; // Set arrays dimension byte[] encSc = submitPdu.encodedScAddress; byte[] encMsg = new byte[submitPdu.encodedMessage.length - dataPos]; System.arraycopy( submitPdu.encodedMessage, dataPos, encMsg, 0, submitPdu.encodedMessage.length - dataPos); byte[] encSender = null; // Check if the senderAddress is a vanish number if (!PhoneNumberUtils.isWellFormedSmsAddress(senderAddress)) { try { byte[] sender7BitPacked = GsmAlphabet.stringToGsm7BitPacked(senderAddress); encSender = new byte[2 + sender7BitPacked.length - 1]; encSender[0] = (byte)((sender7BitPacked.length - 1) * 2); encSender[1] = (byte)0xD0; // Alphabetic sender System.arraycopy(sender7BitPacked, 1, encSender, 2, sender7BitPacked.length - 1); } catch (EncodeException e) { Log.e(TAG, "Failed to decode sender address. Using default.", e); encSender = new byte[dataPos - 4]; System.arraycopy( submitPdu.encodedMessage, 2, encSender, 0, dataPos - 4); } } else { encSender = new byte[dataPos - 4]; System.arraycopy( submitPdu.encodedMessage, 2, encSender, 0, dataPos - 4); } byte[] encTs = bcdTimestamp(); byte[] pdu = new byte[ encSc.length + 1 + /** SMS-DELIVER **/ encSender.length + 2 + /** Protocol + Data Encoding Scheme **/ encTs.length + encMsg.length]; // Copy the SC address int c = 0; System.arraycopy(encSc, 0, pdu, c, encSc.length); c+=encSc.length; // SMS-DELIVER pdu[c] = 0x04; c++; // Sender System.arraycopy(encSender, 0, pdu, c, encSender.length); c+=encSender.length; // Protocol + Data encoding scheme pdu[c] = 0x00; c++; pdu[c] = 0x00; c++; // Timestamp System.arraycopy(encTs, 0, pdu, c, encTs.length); c+=encTs.length; // Message System.arraycopy(encMsg, 0, pdu, c, encMsg.length); // Return the PDUs return new byte[][]{pdu}; } /** * Method that return the current timestamp in a BCD format * * @return byte[] The BCD timestamp */ private byte[] bcdTimestamp() { Calendar c = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("yy"); //$NON-NLS-1$ SimpleDateFormat sdf2 = new SimpleDateFormat("Z"); //$NON-NLS-1$ byte year = (byte)Integer.parseInt( String.valueOf(Integer.parseInt(sdf.format(c.getTime()))), 16); byte month = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.MONTH) + 1), 16); byte day = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.DAY_OF_MONTH)), 16); byte hour = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.HOUR)), 16); byte minute = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.MINUTE)), 16); byte second = (byte)Integer.parseInt(String.valueOf(c.get(Calendar.SECOND)), 16); String tz = sdf2.format(c.getTime()).substring(1); int timezone = Integer.parseInt(tz) / 100; if (timezone < 0) { timezone += 0x80; } byte[] data = {year, month, day, hour, minute, second, 0}; byte[] ts = IccUtils.hexStringToBytes(IccUtils.bcdToString(data, 0, data.length)); ts[6] = (byte)Integer.parseInt(String.valueOf(timezone), 16); return ts; } } }