Home | History | Annotate | Download | only in transaction
      1 /*
      2  * Copyright (C) 2008 Esmertec AG.
      3  * Copyright (C) 2008 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.mms.transaction;
     19 
     20 import com.android.mms.LogTag;
     21 import com.android.mms.ui.MessagingPreferenceActivity;
     22 import com.google.android.mms.MmsException;
     23 import android.database.sqlite.SqliteWrapper;
     24 
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.SharedPreferences;
     28 import android.database.Cursor;
     29 import android.database.sqlite.SQLiteException;
     30 import android.net.Uri;
     31 import android.preference.PreferenceManager;
     32 import android.provider.Telephony.Sms;
     33 import android.util.Log;
     34 
     35 public class SmsMessageSender implements MessageSender {
     36     protected final Context mContext;
     37     protected final int mNumberOfDests;
     38     private final String[] mDests;
     39     protected final String mMessageText;
     40     protected final String mServiceCenter;
     41     protected final long mThreadId;
     42     protected long mTimestamp;
     43 
     44     // Default preference values
     45     private static final boolean DEFAULT_DELIVERY_REPORT_MODE  = false;
     46 
     47     private static final String[] SERVICE_CENTER_PROJECTION = new String[] {
     48         Sms.Conversations.REPLY_PATH_PRESENT,
     49         Sms.Conversations.SERVICE_CENTER,
     50     };
     51 
     52     private static final int COLUMN_REPLY_PATH_PRESENT = 0;
     53     private static final int COLUMN_SERVICE_CENTER     = 1;
     54 
     55     public SmsMessageSender(Context context, String[] dests, String msgText, long threadId) {
     56         mContext = context;
     57         mMessageText = msgText;
     58         if (dests != null) {
     59             mNumberOfDests = dests.length;
     60             mDests = new String[mNumberOfDests];
     61             System.arraycopy(dests, 0, mDests, 0, mNumberOfDests);
     62         } else {
     63             mNumberOfDests = 0;
     64             mDests = null;
     65         }
     66         mTimestamp = System.currentTimeMillis();
     67         mThreadId = threadId;
     68         mServiceCenter = getOutgoingServiceCenter(mThreadId);
     69     }
     70 
     71     public boolean sendMessage(long token) throws MmsException {
     72         // In order to send the message one by one, instead of sending now, the message will split,
     73         // and be put into the queue along with each destinations
     74         return queueMessage(token);
     75     }
     76 
     77     private boolean queueMessage(long token) throws MmsException {
     78         if ((mMessageText == null) || (mNumberOfDests == 0)) {
     79             // Don't try to send an empty message.
     80             throw new MmsException("Null message body or dest.");
     81         }
     82 
     83         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
     84         boolean requestDeliveryReport = prefs.getBoolean(
     85                 MessagingPreferenceActivity.SMS_DELIVERY_REPORT_MODE,
     86                 DEFAULT_DELIVERY_REPORT_MODE);
     87 
     88         for (int i = 0; i < mNumberOfDests; i++) {
     89             try {
     90                 Sms.addMessageToUri(mContext.getContentResolver(),
     91                         Uri.parse("content://sms/queued"), mDests[i],
     92                         mMessageText, null, mTimestamp,
     93                         true /* read */,
     94                         requestDeliveryReport,
     95                         mThreadId);
     96             } catch (SQLiteException e) {
     97                 SqliteWrapper.checkSQLiteException(mContext, e);
     98             }
     99         }
    100         // Notify the SmsReceiverService to send the message out
    101         mContext.sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,
    102                 null,
    103                 mContext,
    104                 SmsReceiver.class));
    105         return false;
    106     }
    107 
    108     /**
    109      * Get the service center to use for a reply.
    110      *
    111      * The rule from TS 23.040 D.6 is that we send reply messages to
    112      * the service center of the message to which we're replying, but
    113      * only if we haven't already replied to that message and only if
    114      * <code>TP-Reply-Path</code> was set in that message.
    115      *
    116      * Therefore, return the service center from the most recent
    117      * message in the conversation, but only if it is a message from
    118      * the other party, and only if <code>TP-Reply-Path</code> is set.
    119      * Otherwise, return null.
    120      */
    121     private String getOutgoingServiceCenter(long threadId) {
    122         Cursor cursor = null;
    123 
    124         try {
    125             cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(),
    126                             Sms.CONTENT_URI, SERVICE_CENTER_PROJECTION,
    127                             "thread_id = " + threadId, null, "date DESC");
    128 
    129             if ((cursor == null) || !cursor.moveToFirst()) {
    130                 return null;
    131             }
    132 
    133             boolean replyPathPresent = (1 == cursor.getInt(COLUMN_REPLY_PATH_PRESENT));
    134             return replyPathPresent ? cursor.getString(COLUMN_SERVICE_CENTER) : null;
    135         } finally {
    136             if (cursor != null) {
    137                 cursor.close();
    138             }
    139         }
    140     }
    141 
    142     private void log(String msg) {
    143         Log.d(LogTag.TAG, "[SmsMsgSender] " + msg);
    144     }
    145 }
    146