Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d165530f authored by Joseph Mangmang's avatar Joseph Mangmang
Browse files

Merge branch 'master' of https://github.com/moezbhatti/qksms

parents b55b8a28 44ae58ae
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -62,11 +62,10 @@ public class Conversation {
            Threads.READ
    };

    private static final String UNREAD_SELECTION = "(read=0 OR seen=0)";
    public static final String UNREAD_SELECTION = "(read=0 OR seen=0)";
    public static final String FAILED_SELECTION = "error != 0";

    private static final String[] SEEN_PROJECTION = new String[]{
            "seen"
    };
    public static final String[] SEEN_PROJECTION = new String[]{"seen"};

    public static final int ID = 0;
    public static final int DATE = 1;
+73 −0
Original line number Diff line number Diff line
package com.moez.QKSMS.receiver;

import android.content.BroadcastReceiver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import com.google.android.mms.MmsException;
import com.moez.QKSMS.data.Conversation;
import com.moez.QKSMS.mmssms.Message;
import com.moez.QKSMS.mmssms.Transaction;
import com.moez.QKSMS.transaction.SmsHelper;
import com.moez.QKSMS.ui.messagelist.MessageColumns;
import com.moez.QKSMS.ui.messagelist.MessageItem;

/**
 * Listen for changes to the Airplane Mode status, so that we can attempt to re-send failed messages
 * once we have signal
 */
public class AirplaneModeReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // If we're going into airplane mode, no need to do anything
        if (intent.getBooleanExtra("state", true)) {
            return;
        }

        // Cursor to find the conversations that contain failed messages
        Cursor conversationCursor = context.getContentResolver().query(
                SmsHelper.CONVERSATIONS_CONTENT_PROVIDER,
                Conversation.ALL_THREADS_PROJECTION,
                Conversation.FAILED_SELECTION, null,
                SmsHelper.sortDateDesc
        );

        // Loop through each of the conversations
        while (conversationCursor.moveToNext()) {
            Uri uri = ContentUris.withAppendedId(SmsHelper.MMS_SMS_CONTENT_PROVIDER, conversationCursor.getLong(Conversation.ID));

            // Find the failed messages within the conversation
            Cursor cursor = context.getContentResolver().query(uri, MessageColumns.PROJECTION,
                    SmsHelper.FAILED_SELECTION, null, SmsHelper.sortDateAsc);

            // Map the cursor row to a MessageItem, then re-send it
            MessageColumns.ColumnsMap columnsMap = new MessageColumns.ColumnsMap(cursor);
            while (cursor.moveToNext()) {
                try {
                    MessageItem message = new MessageItem(context, cursor.getString(columnsMap.mColumnMsgType),
                            cursor, columnsMap, null, true);
                    sendSms(context, message);
                } catch (MmsException e) {
                    e.printStackTrace();
                }
            }
            cursor.close();
        }

        conversationCursor.close();
    }

    private void sendSms(Context context, MessageItem messageItem) {
        Transaction sendTransaction = new Transaction(context, SmsHelper.getSendSettings(context));

        Message message = new Message(messageItem.mBody, messageItem.mAddress);
        message.setType(Message.TYPE_SMSMMS);

        context.getContentResolver().delete(messageItem.mMessageUri, null, null);

        sendTransaction.sendNewMessage(message, 0);
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ public class SmsHelper {

    public static final Uri SMS_CONTENT_PROVIDER = Uri.parse("content://sms/");
    public static final Uri MMS_CONTENT_PROVIDER = Uri.parse("content://mms/");
    public static final Uri MMS_SMS_CONTENT_PROVIDER = Uri.parse("content://mms-sms/conversations/");
    public static final Uri SENT_MESSAGE_CONTENT_PROVIDER = Uri.parse("content://sms/sent");
    public static final Uri DRAFTS_CONTENT_PROVIDER = Uri.parse("content://sms/draft");
    public static final Uri PENDING_MESSAGE_CONTENT_PROVIDER = Uri.parse("content://sms/outbox");
+0 −147
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 Esmertec AG.
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.moez.QKSMS.transaction;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SqliteWrapper;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.provider.Telephony.Sms;
import android.provider.Telephony.Sms.Inbox;
import android.util.Log;

import com.android.mms.transaction.MessageSender;
import com.google.android.mms.MmsException;
import com.moez.QKSMS.LogTag;
import com.moez.QKSMS.receiver.SmsReceiver;
import com.moez.QKSMS.ui.settings.SettingsFragment;

public class SmsMessageSender implements MessageSender {
    protected final Context mContext;
    protected final int mNumberOfDests;
    private final String[] mDests;
    protected final String mMessageText;
    protected final String mServiceCenter;
    protected final long mThreadId;
    protected long mTimestamp;
    private static final String TAG = "SmsMessageSender";

    // Default preference values
    private static final boolean DEFAULT_DELIVERY_REPORT_MODE  = false;

    private static final String[] SERVICE_CENTER_PROJECTION = new String[] {
        Sms.Conversations.REPLY_PATH_PRESENT,
        Sms.Conversations.SERVICE_CENTER,
    };

    private static final int COLUMN_REPLY_PATH_PRESENT = 0;
    private static final int COLUMN_SERVICE_CENTER     = 1;

    public SmsMessageSender(Context context, String[] dests, String msgText, long threadId) {
        mContext = context;
        mMessageText = msgText;
        if (dests != null) {
            mNumberOfDests = dests.length;
            mDests = new String[mNumberOfDests];
            System.arraycopy(dests, 0, mDests, 0, mNumberOfDests);
        } else {
            mNumberOfDests = 0;
            mDests = null;
        }
        mTimestamp = System.currentTimeMillis();
        mThreadId = threadId;
        mServiceCenter = getOutgoingServiceCenter(mThreadId);
    }

    public boolean sendMessage(long token) throws MmsException {
        // In order to send the message one by one, instead of sending now, the message will split,
        // and be put into the queue along with each destinations
        return queueMessage(token);
    }

    private boolean queueMessage(long token) throws MmsException {
        if ((mMessageText == null) || (mNumberOfDests == 0)) {
            // Don't try to send an empty message.
            throw new MmsException("Null message body or dest.");
        }

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
        boolean requestDeliveryReport = prefs.getBoolean(SettingsFragment.DELIVERY_REPORTS, DEFAULT_DELIVERY_REPORT_MODE);

        for (int i = 0; i < mNumberOfDests; i++) {
            try {
                if (LogTag.DEBUG_SEND) {
                    Log.v(TAG, "queueMessage mDests[i]: " + mDests[i] + " mThreadId: " + mThreadId);
                }
                SmsHelper.addMessageToUri(mContext.getContentResolver(), Uri.parse("content://sms/queued"), mDests[i], mMessageText, null, mTimestamp, true /* read */, requestDeliveryReport, mThreadId);
            } catch (SQLiteException e) {
                if (LogTag.DEBUG_SEND) {
                    Log.e(TAG, "queueMessage SQLiteException", e);
                }
                SqliteWrapper.checkSQLiteException(mContext, e);
            }
        }
        // Notify the SmsReceiverService to send the message out
        mContext.sendBroadcast(new Intent("com.moez.QKSMS.transaction.SEND_MESSAGE", null, mContext, SmsReceiver.class));
        return false;
    }

    /**
     * Get the service center to use for a reply.
     *
     * The rule from TS 23.040 D.6 is that we send reply messages to
     * the service center of the message to which we're replying, but
     * only if we haven't already replied to that message and only if
     * <code>TP-Reply-Path</code> was set in that message.
     *
     * Therefore, return the service center from the most recent
     * message in the conversation, but only if it is a message from
     * the other party, and only if <code>TP-Reply-Path</code> is set.
     * Otherwise, return null.
     */
    @SuppressLint("NewApi")
    private String getOutgoingServiceCenter(long threadId) {
        Cursor cursor = null;

        try {
            cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(),
                            Inbox.CONTENT_URI, SERVICE_CENTER_PROJECTION,
                            "thread_id = " + threadId, null, "date DESC");

            if ((cursor == null) || !cursor.moveToFirst()) {
                return null;
            }

            boolean replyPathPresent = (1 == cursor.getInt(COLUMN_REPLY_PATH_PRESENT));
            return replyPathPresent ? cursor.getString(COLUMN_SERVICE_CENTER) : null;
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

    private void log(String msg) {
        Log.d(LogTag.TAG, "[SmsMsgSender] " + msg);
    }
}