package com.android.mms.transaction;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.database.sqlite.SqliteWrapper;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.provider.Telephony;
import android.telephony.SmsManager;
import android.text.TextUtils;
import com.android.mms.MmsConfig;
import com.klinker.android.logger.Log;
import com.klinker.android.send_message.BroadcastUtils;
import com.klinker.android.send_message.MmsReceivedReceiver;
import java.io.File;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* In order to avoid downloading duplicate MMS.
* We should manage to call SMSManager.downloadMultimediaMessage().
*/
public class DownloadManager {
private static final String TAG = "DownloadManager";
private static DownloadManager ourInstance = new DownloadManager();
private static final ConcurrentHashMap<String, MmsDownloadReceiver> mMap = new ConcurrentHashMap<>();
public static DownloadManager getInstance() {
return ourInstance;
}
private DownloadManager() {
}
public void downloadMultimediaMessage(final Context context, final String location, Uri uri, boolean byPush) {
if (location == null || mMap.get(location) != null) {
return;
}
// TransactionService can keep uri and location in memory while SmsManager download Mms.
if (!isNotificationExist(context, location)) {
return;
}
MmsDownloadReceiver receiver = new MmsDownloadReceiver();
mMap.put(location, receiver);
// Use unique action in order to avoid cancellation of notifying download result.
context.getApplicationContext().registerReceiver(receiver, new IntentFilter(receiver.mAction));
Log.v(TAG, "receiving with system method");
final String fileName = "download." + String.valueOf(Math.abs(new Random().nextLong())) + ".dat";
File mDownloadFile = new File(context.getCacheDir(), fileName);
Uri contentUri = (new Uri.Builder())
.authority(context.getPackageName() + ".MmsFileProvider")
.path(fileName)
.scheme(ContentResolver.SCHEME_CONTENT)
.build();
Intent download = new Intent(receiver.mAction);
download.putExtra(MmsReceivedReceiver.EXTRA_FILE_PATH, mDownloadFile.getPath());
download.putExtra(MmsReceivedReceiver.EXTRA_LOCATION_URL, location);
download.putExtra(MmsReceivedReceiver.EXTRA_TRIGGER_PUSH, byPush);
download.putExtra(MmsReceivedReceiver.EXTRA_URI, uri);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, 0, download, PendingIntent.FLAG_CANCEL_CURRENT);
Bundle configOverrides = new Bundle();
String httpParams = MmsConfig.getHttpParams();
if (!TextUtils.isEmpty(httpParams)) {
configOverrides.putString(SmsManager.MMS_CONFIG_HTTP_PARAMS, httpParams);
}
grantUriPermission(context, contentUri);
SmsManager.getDefault().downloadMultimediaMessage(context,
location, contentUri, configOverrides, pendingIntent);
}
private void grantUriPermission(Context context, Uri contentUri) {
context.grantUriPermission(context.getPackageName() + ".MmsFileProvider",
contentUri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
private static class MmsDownloadReceiver extends BroadcastReceiver {
private static final String ACTION_PREFIX = "com.android.mms.transaction.DownloadManager$MmsDownloadReceiver.";
private final String mAction;
MmsDownloadReceiver() {
mAction = ACTION_PREFIX + UUID.randomUUID().toString();
}
@Override
public void onReceive(Context context, Intent intent) {
context.unregisterReceiver(this);
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MMS DownloadReceiver");
wakeLock.acquire(60 * 1000);
Intent newIntent = (Intent) intent.clone();
newIntent.setAction(MmsReceivedReceiver.MMS_RECEIVED);
BroadcastUtils.sendExplicitBroadcast(context, newIntent, MmsReceivedReceiver.MMS_RECEIVED);
}
}
public static void finishDownload(String location) {
if (location != null) {
mMap.remove(location);
}
}
private static boolean isNotificationExist(Context context, String location) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return true;
}
String selection = Telephony.Mms.CONTENT_LOCATION + " = ?";
String[] selectionArgs = new String[] { location };
Cursor c = SqliteWrapper.query(
context, context.getContentResolver(),
Telephony.Mms.CONTENT_URI, new String[] { Telephony.Mms._ID },
selection, selectionArgs, null);
if (c != null) {
try {
if (c.getCount() > 0) {
return true;
}
} finally {
c.close();
}
}
return false;
}
}