Sync MMS on sending and on failure

This commit is contained in:
Moez Bhatti
2018-01-14 18:59:53 -05:00
parent c4b672f260
commit 45f1cb1bc8
11 changed files with 229 additions and 139 deletions
@@ -1,56 +0,0 @@
/*
* Copyright (C) 2015 Jacob Klinker
*
* 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.klinker.android.send_message;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.Telephony;
import com.google.android.mms.util_alt.SqliteWrapper;
import com.klinker.android.logger.Log;
import java.io.File;
public class MmsSentReceiver extends BroadcastReceiver {
private static final String TAG = "MmsSentReceiver";
public static final String MMS_SENT = "com.klinker.android.messaging.MMS_SENT";
public static final String EXTRA_CONTENT_URI = "content_uri";
public static final String EXTRA_FILE_PATH = "file_path";
@Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "MMS has finished sending, marking it as so in the database");
Uri uri = Uri.parse(intent.getStringExtra(EXTRA_CONTENT_URI));
Log.v(TAG, uri.toString());
ContentValues values = new ContentValues(1);
values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_SENT);
SqliteWrapper.update(context, context.getContentResolver(), uri, values,
null, null);
String filePath = intent.getStringExtra(EXTRA_FILE_PATH);
Log.v(TAG, filePath);
new File(filePath).delete();
}
}
@@ -0,0 +1,78 @@
/*
* Copyright (C) 2015 Jacob Klinker
*
* 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.klinker.android.send_message
import android.app.Activity
import android.content.*
import android.net.Uri
import android.provider.Telephony
import android.util.Log
import com.google.android.mms.MmsException
import com.google.android.mms.util_alt.SqliteWrapper
import java.io.File
open class MmsSentReceiver : BroadcastReceiver() {
companion object {
private val TAG = "MmsSentReceiver"
const val MMS_SENT = "com.klinker.android.messaging.MMS_SENT"
const val EXTRA_CONTENT_URI = "content_uri"
const val EXTRA_FILE_PATH = "file_path"
}
override fun onReceive(context: Context, intent: Intent) {
Log.v(TAG, "MMS sending result: " + resultCode)
val uri = Uri.parse(intent.getStringExtra(EXTRA_CONTENT_URI))
Log.v(TAG, uri.toString())
if (resultCode == Activity.RESULT_OK) {
Log.v(TAG, "MMS has finished sending, marking it as so in the database")
val values = ContentValues(1)
values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_SENT)
SqliteWrapper.update(context, context.contentResolver, uri, values, null, null)
} else {
Log.v(TAG, "MMS has failed to send, marking it as so in the database")
try {
val messageId = ContentUris.parseId(uri)
val values = ContentValues(1)
values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_FAILED)
SqliteWrapper.update(context, context.contentResolver, Telephony.Mms.CONTENT_URI, values,
"${Telephony.Mms._ID} = ?", arrayOf(messageId.toString()))
// TODO this query isn't able to find any results
// Need to figure out why the message isn't appearing in the PendingMessages Uri,
// so that we can properly assign the error type
val errorTypeValues = ContentValues(1)
errorTypeValues.put(Telephony.MmsSms.PendingMessages.ERROR_TYPE, Telephony.MmsSms.ERR_TYPE_GENERIC_PERMANENT)
SqliteWrapper.update(context, context.contentResolver, Telephony.MmsSms.PendingMessages.CONTENT_URI,
errorTypeValues, "${Telephony.MmsSms.PendingMessages.MSG_ID} = ?", arrayOf(messageId.toString()))
} catch (e: MmsException) {
e.printStackTrace()
}
}
val filePath = intent.getStringExtra(EXTRA_FILE_PATH)
Log.v(TAG, filePath)
File(filePath).delete()
}
}
@@ -81,12 +81,17 @@ public class Transaction {
public String SMS_DELIVERED = ".SMS_DELIVERED";
public static String NOTIFY_SMS_FAILURE = ".NOTIFY_SMS_FAILURE";
public static final String MMS_UPDATED = "com.moez.QKSMS.MMS_UPDATED";
public static final String MMS_ERROR = "com.klinker.android.send_message.MMS_ERROR";
public static final String REFRESH = "com.klinker.android.send_message.REFRESH";
public static final String MMS_PROGRESS = "com.klinker.android.send_message.MMS_PROGRESS";
public static final String NOTIFY_OF_DELIVERY = "com.klinker.android.send_message.NOTIFY_DELIVERY";
public static final String NOTIFY_OF_MMS = "com.klinker.android.messaging.NEW_MMS_DOWNLOADED";
public static final long DEFAULT_EXPIRY_TIME = 7 * 24 * 60 * 60;
public static final int DEFAULT_PRIORITY = PduHeaders.PRIORITY_NORMAL;
public static final long NO_THREAD_ID = 0;
/**
@@ -371,7 +376,71 @@ public class Transaction {
}
Log.v(TAG, "sending mms");
sendMmsThroughSystem(context, subject, data, addresses);
try {
final String fileName = "send." + String.valueOf(Math.abs(new Random().nextLong())) + ".dat";
File mSendFile = new File(context.getCacheDir(), fileName);
SendReq sendReq = buildPdu(context, addresses, subject, data);
PduPersister persister = PduPersister.getPduPersister(context);
Uri messageUri = persister.persist(sendReq, Uri.parse("content://mms/outbox"), true, true, null);
Intent sentIntent = new Intent(MmsSentReceiver.MMS_SENT);
BroadcastUtils.addClassName(context, sentIntent, MmsSentReceiver.MMS_SENT);
sentIntent.putExtra(MmsSentReceiver.EXTRA_CONTENT_URI, messageUri.toString());
sentIntent.putExtra(MmsSentReceiver.EXTRA_FILE_PATH, mSendFile.getPath());
final PendingIntent sentPI = PendingIntent.getBroadcast(
context, 0, sentIntent, PendingIntent.FLAG_CANCEL_CURRENT);
Intent updatedIntent = new Intent(MMS_UPDATED);
updatedIntent.putExtra("uri", messageUri.toString());
BroadcastUtils.addClassName(context, updatedIntent, MMS_UPDATED);
context.sendBroadcast(updatedIntent);
Uri writerUri = (new Uri.Builder())
.authority(context.getPackageName() + ".MmsFileProvider")
.path(fileName)
.scheme(ContentResolver.SCHEME_CONTENT)
.build();
FileOutputStream writer = null;
Uri contentUri = null;
try {
writer = new FileOutputStream(mSendFile);
writer.write(new PduComposer(context, sendReq).make());
contentUri = writerUri;
} catch (final IOException e) {
Log.e(TAG, "Error writing send file", e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
}
}
}
Bundle configOverrides = new Bundle();
configOverrides.putBoolean(SmsManager.MMS_CONFIG_GROUP_MMS_ENABLED, true);
String httpParams = MmsConfig.getHttpParams();
if (!TextUtils.isEmpty(httpParams)) {
configOverrides.putString(SmsManager.MMS_CONFIG_HTTP_PARAMS, httpParams);
}
configOverrides.putInt(SmsManager.MMS_CONFIG_MAX_MESSAGE_SIZE, MmsConfig.getMaxMessageSize());
if (contentUri != null) {
SmsManagerFactory.INSTANCE.createSmsManager(settings).sendMultimediaMessage(context,
contentUri, null, configOverrides, sentPI);
} else {
Log.e(TAG, "Error writing sending Mms");
try {
sentPI.send(SmsManager.MMS_ERROR_IO_ERROR);
} catch (PendingIntent.CanceledException ex) {
Log.e(TAG, "Mms pending intent cancelled?", ex);
}
}
} catch (Exception e) {
Log.e(TAG, "error using system sending method", e);
}
}
public static MessageInfo getBytes(Context context, boolean saveMessage, String[] recipients, MMSPart[] parts,
@@ -494,75 +563,7 @@ public class Transaction {
return info;
}
public static final long DEFAULT_EXPIRY_TIME = 7 * 24 * 60 * 60;
public static final int DEFAULT_PRIORITY = PduHeaders.PRIORITY_NORMAL;
private static void sendMmsThroughSystem(Context context, String subject, List<MMSPart> parts, String[] addresses) {
try {
final String fileName = "send." + String.valueOf(Math.abs(new Random().nextLong())) + ".dat";
File mSendFile = new File(context.getCacheDir(), fileName);
SendReq sendReq = buildPdu(context, addresses, subject, parts);
PduPersister persister = PduPersister.getPduPersister(context);
Uri messageUri = persister.persist(sendReq, Uri.parse("content://mms/outbox"),
true, true, null);
Intent intent = new Intent(MmsSentReceiver.MMS_SENT);
BroadcastUtils.addClassName(context, intent, MmsSentReceiver.MMS_SENT);
intent.putExtra(MmsSentReceiver.EXTRA_CONTENT_URI, messageUri.toString());
intent.putExtra(MmsSentReceiver.EXTRA_FILE_PATH, mSendFile.getPath());
final PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Uri writerUri = (new Uri.Builder())
.authority(context.getPackageName() + ".MmsFileProvider")
.path(fileName)
.scheme(ContentResolver.SCHEME_CONTENT)
.build();
FileOutputStream writer = null;
Uri contentUri = null;
try {
writer = new FileOutputStream(mSendFile);
writer.write(new PduComposer(context, sendReq).make());
contentUri = writerUri;
} catch (final IOException e) {
Log.e(TAG, "Error writing send file", e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
}
}
}
Bundle configOverrides = new Bundle();
configOverrides.putBoolean(SmsManager.MMS_CONFIG_GROUP_MMS_ENABLED, true);
String httpParams = MmsConfig.getHttpParams();
if (!TextUtils.isEmpty(httpParams)) {
configOverrides.putString(SmsManager.MMS_CONFIG_HTTP_PARAMS, httpParams);
}
configOverrides.putInt(SmsManager.MMS_CONFIG_MAX_MESSAGE_SIZE, MmsConfig.getMaxMessageSize());
if (contentUri != null) {
SmsManagerFactory.INSTANCE.createSmsManager(settings).sendMultimediaMessage(context,
contentUri, null, configOverrides, pendingIntent);
} else {
Log.e(TAG, "Error writing sending Mms");
try {
pendingIntent.send(SmsManager.MMS_ERROR_IO_ERROR);
} catch (PendingIntent.CanceledException ex) {
Log.e(TAG, "Mms pending intent cancelled?", ex);
}
}
} catch (Exception e) {
Log.e(TAG, "error using system sending method", e);
}
}
private static SendReq buildPdu(Context context, String[] recipients, String subject,
List<MMSPart> parts) {
private static SendReq buildPdu(Context context, String[] recipients, String subject, List<MMSPart> parts) {
final SendReq req = new SendReq();
// From, per spec
final String lineNumber = Utils.getMyPhoneNumber(context);