/** {@inheritDoc} */
 protected void sendText(
     String destAddr,
     String scAddr,
     String text,
     PendingIntent sentIntent,
     PendingIntent deliveryIntent) {
   SmsMessage.SubmitPdu pdu =
       SmsMessage.getSubmitPdu(scAddr, destAddr, text, (deliveryIntent != null));
   sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
 }
 /** {@inheritDoc} */
 protected void sendData(
     String destAddr,
     String scAddr,
     int destPort,
     byte[] data,
     PendingIntent sentIntent,
     PendingIntent deliveryIntent) {
   SmsMessage.SubmitPdu pdu =
       SmsMessage.getSubmitPdu(scAddr, destAddr, destPort, data, (deliveryIntent != null));
   sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
 }
  /**
   * Send a multi-part text based SMS which already passed SMS control check.
   *
   * It is the working function for sendMultipartText().
   *
   * @param destinationAddress the address to send the message to
   * @param scAddress is the service center address or null to use
   *   the current default SMSC
   * @param parts an <code>ArrayList</code> of strings that, in order,
   *   comprise the original message
   * @param sentIntents if not null, an <code>ArrayList</code> of
   *   <code>PendingIntent</code>s (one for each message part) that is
   *   broadcast when the corresponding message part has been sent.
   *   The result code will be <code>Activity.RESULT_OK<code> for success,
   *   or one of these errors:
   *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
   *   <code>RESULT_ERROR_RADIO_OFF</code>
   *   <code>RESULT_ERROR_NULL_PDU</code>.
   * @param deliveryIntents if not null, an <code>ArrayList</code> of
   *   <code>PendingIntent</code>s (one for each message part) that is
   *   broadcast when the corresponding message part has been delivered
   *   to the recipient.  The raw pdu of the status report is in the
   *   extended data ("pdu").
   */
  private void sendMultipartTextWithPermit(
      String destinationAddress,
      String scAddress,
      ArrayList<String> parts,
      ArrayList<PendingIntent> sentIntents,
      ArrayList<PendingIntent> deliveryIntents) {

    // check if in service
    int ss = mPhone.getServiceState().getState();
    if (ss != ServiceState.STATE_IN_SERVICE) {
      for (int i = 0, count = parts.size(); i < count; i++) {
        PendingIntent sentIntent = null;
        if (sentIntents != null && sentIntents.size() > i) {
          sentIntent = sentIntents.get(i);
        }
        SmsTracker tracker = SmsTrackerFactory(null, sentIntent, null);
        handleNotInService(ss, tracker);
      }
      return;
    }

    int refNumber = getNextConcatenatedRef() & 0x00FF;
    int msgCount = parts.size();
    int encoding = android.telephony.SmsMessage.ENCODING_UNKNOWN;

    mRemainingMessages = msgCount;

    TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount];
    for (int i = 0; i < msgCount; i++) {
      TextEncodingDetails details = SmsMessage.calculateLength(parts.get(i), false);
      if (encoding != details.codeUnitSize
          && (encoding == android.telephony.SmsMessage.ENCODING_UNKNOWN
              || encoding == android.telephony.SmsMessage.ENCODING_7BIT)) {
        encoding = details.codeUnitSize;
      }
      encodingForParts[i] = details;
    }

    for (int i = 0; i < msgCount; i++) {
      SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
      concatRef.refNumber = refNumber;
      concatRef.seqNumber = i + 1; // 1-based sequence
      concatRef.msgCount = msgCount;
      concatRef.isEightBits = false;
      SmsHeader smsHeader = new SmsHeader();
      smsHeader.concatRef = concatRef;
      if (encoding == android.telephony.SmsMessage.ENCODING_7BIT) {
        smsHeader.languageTable = encodingForParts[i].languageTable;
        smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable;
      }

      PendingIntent sentIntent = null;
      if (sentIntents != null && sentIntents.size() > i) {
        sentIntent = sentIntents.get(i);
      }

      PendingIntent deliveryIntent = null;
      if (deliveryIntents != null && deliveryIntents.size() > i) {
        deliveryIntent = deliveryIntents.get(i);
      }

      SmsMessage.SubmitPdu pdus =
          SmsMessage.getSubmitPdu(
              scAddress,
              destinationAddress,
              parts.get(i),
              deliveryIntent != null,
              SmsHeader.toByteArray(smsHeader),
              encoding,
              smsHeader.languageTable,
              smsHeader.languageShiftTable);

      HashMap<String, Object> map = new HashMap<String, Object>();
      map.put("smsc", pdus.encodedScAddress);
      map.put("pdu", pdus.encodedMessage);

      SmsTracker tracker = SmsTrackerFactory(map, sentIntent, deliveryIntent);
      sendSms(tracker);
    }
  }
  /** {@inheritDoc} */
  protected void sendMultipartText(
      String destinationAddress,
      String scAddress,
      ArrayList<String> parts,
      ArrayList<PendingIntent> sentIntents,
      ArrayList<PendingIntent> deliveryIntents) {

    int refNumber = getNextConcatenatedRef() & 0x00FF;
    int msgCount = parts.size();
    int encoding = android.telephony.SmsMessage.ENCODING_UNKNOWN;

    mRemainingMessages = msgCount;

    TextEncodingDetails[] encodingForParts = new TextEncodingDetails[msgCount];
    for (int i = 0; i < msgCount; i++) {
      TextEncodingDetails details = SmsMessage.calculateLength(parts.get(i), false);
      if (encoding != details.codeUnitSize
          && (encoding == android.telephony.SmsMessage.ENCODING_UNKNOWN
              || encoding == android.telephony.SmsMessage.ENCODING_7BIT)) {
        encoding = details.codeUnitSize;
      }
      encodingForParts[i] = details;
    }

    for (int i = 0; i < msgCount; i++) {
      SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
      concatRef.refNumber = refNumber;
      concatRef.seqNumber = i + 1; // 1-based sequence
      concatRef.msgCount = msgCount;
      // TODO: We currently set this to true since our messaging app will never
      // send more than 255 parts (it converts the message to MMS well before that).
      // However, we should support 3rd party messaging apps that might need 16-bit
      // references
      // Note:  It's not sufficient to just flip this bit to true; it will have
      // ripple effects (several calculations assume 8-bit ref).
      concatRef.isEightBits = true;
      SmsHeader smsHeader = new SmsHeader();
      smsHeader.concatRef = concatRef;
      if (encoding == android.telephony.SmsMessage.ENCODING_7BIT) {
        smsHeader.languageTable = encodingForParts[i].languageTable;
        smsHeader.languageShiftTable = encodingForParts[i].languageShiftTable;
      }

      PendingIntent sentIntent = null;
      if (sentIntents != null && sentIntents.size() > i) {
        sentIntent = sentIntents.get(i);
      }

      PendingIntent deliveryIntent = null;
      if (deliveryIntents != null && deliveryIntents.size() > i) {
        deliveryIntent = deliveryIntents.get(i);
      }

      SmsMessage.SubmitPdu pdus =
          SmsMessage.getSubmitPdu(
              scAddress,
              destinationAddress,
              parts.get(i),
              deliveryIntent != null,
              SmsHeader.toByteArray(smsHeader),
              encoding,
              smsHeader.languageTable,
              smsHeader.languageShiftTable);

      sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
    }
  }