diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2c9166f..96900c5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="eu.droogers.smsmatrix">
+
diff --git a/app/src/main/java/eu/droogers/smsmatrix/MMSMonitor.java b/app/src/main/java/eu/droogers/smsmatrix/MMSMonitor.java
new file mode 100644
index 0000000..76c9764
--- /dev/null
+++ b/app/src/main/java/eu/droogers/smsmatrix/MMSMonitor.java
@@ -0,0 +1,302 @@
+package eu.droogers.smsmatrix;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Telephony;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class MMSMonitor {
+ private MatrixService mainActivity;
+ private ContentResolver contentResolver = null;
+ private Context mainContext;
+ private Handler mmshandler = null;
+ private ContentObserver mmsObserver = null;
+ public boolean monitorStatus = false;
+ private int mmsCount = 0;
+ private static final String TAG = "MMSMonitor";
+
+ public MMSMonitor(final MatrixService mainActivity, final Context mainContext) {
+ this.mainActivity = mainActivity;
+ contentResolver = mainActivity.getContentResolver();
+ this.mainContext = mainContext;
+ mmshandler = new MMSHandler();
+ mmsObserver = new MMSObserver(mmshandler);
+ Log.i(TAG, "***** Start MMS Monitor *****");
+ }
+
+
+ public void startMMSMonitoring() {
+ try {
+ monitorStatus = false;
+ if (!monitorStatus) {
+ contentResolver.registerContentObserver(
+ Uri.parse("content://mms"),
+ true,
+ mmsObserver
+ );
+
+ // Save the count of MMS messages on start-up.
+ Uri uriMMSURI = Uri.parse("content://mms-sms");
+ Cursor mmsCur = mainActivity.getContentResolver().query(
+ uriMMSURI,
+ null,
+ Telephony.Mms.MESSAGE_BOX + " = " + Telephony.Mms.MESSAGE_BOX_INBOX,
+ null,
+ Telephony.Mms._ID
+ );
+ if (mmsCur != null && mmsCur.getCount() > 0) {
+ mmsCount = mmsCur.getCount();
+ Log.d(TAG, "Init MMSCount = " + mmsCount);
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ }
+ }
+
+
+ public void stopMMSMonitoring() {
+ try {
+ monitorStatus = false;
+ if (!monitorStatus){
+ contentResolver.unregisterContentObserver(mmsObserver);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ }
+ }
+
+
+ class MMSHandler extends Handler {
+ public void handleMessage(final Message msg) {
+ //Log.i(TAG, "Handler");
+ }
+ }
+
+
+ class MMSObserver extends ContentObserver {
+ private Handler mms_handle = null;
+ public MMSObserver(final Handler mmshandle) {
+ super(mmshandle);
+ mms_handle = mmshandle;
+ }
+
+ public void onChange(final boolean bSelfChange) {
+ super.onChange(bSelfChange);
+ Log.i(TAG, "Onchange");
+
+ try {
+ monitorStatus = true;
+
+ // Send message to Activity.
+ Message msg = new Message();
+ mms_handle.sendMessage(msg);
+
+ // Get the MMS count.
+ Uri uriMMSURI = Uri.parse("content://mms/");
+ Cursor mmsCur = mainActivity.getContentResolver().query(
+ uriMMSURI,
+ null,
+ Telephony.Mms.MESSAGE_BOX + " = " + Telephony.Mms.MESSAGE_BOX_INBOX,
+ null,
+ Telephony.Mms._ID
+ );
+
+ int currMMSCount = 0;
+ if (mmsCur != null && mmsCur.getCount() > 0) {
+ currMMSCount = mmsCur.getCount();
+ }
+
+ // Proceed if there is a new message.
+ if (currMMSCount > mmsCount) {
+ mmsCount = currMMSCount;
+ mmsCur.moveToLast();
+
+ // Get the message id and subject.
+ String subject = mmsCur.getString(mmsCur.getColumnIndex(Telephony.Mms.SUBJECT));
+ int id = Integer.parseInt(mmsCur.getString(mmsCur.getColumnIndex(Telephony.Mms._ID)));
+ Log.d(TAG, "_id = " + id);
+ Log.d(TAG, "Subject = " + subject);
+
+ byte[] mediaData = null;
+ String message = "";
+ String address = "";
+ String fileName = "";
+ String fileType = "";
+ String messageType = "";
+
+ // Get parts.
+ Uri uriMMSPart = Uri.parse("content://mms/part");
+ Cursor curPart = mainActivity.getContentResolver().query(
+ uriMMSPart,
+ null,
+ Telephony.Mms.Part.MSG_ID + " = " + id,
+ null,
+ Telephony.Mms.Part._ID
+ );
+ Log.d(TAG, "Parts records length = " + curPart.getCount());
+ curPart.moveToLast();
+ do {
+ String contentType = curPart.getString(curPart.getColumnIndex(Telephony.Mms.Part.CONTENT_TYPE));
+ String partId = curPart.getString(curPart.getColumnIndex(Telephony.Mms.Part._ID));
+ fileName = curPart.getString(curPart.getColumnIndex(Telephony.Mms.Part.NAME));
+ Log.d(TAG, "partId = " + partId);
+ Log.d(TAG, "Part mime type = " + contentType);
+
+ if (contentType.equalsIgnoreCase("text/plain"))
+ {
+ // Get the message.
+
+ Log.i(TAG,"==== Get the message start ====");
+ messageType = Matrix.MESSAGE_TYPE_TEXT;
+ byte[] messageData = readMMSPart(partId);
+ if (messageData != null && messageData.length > 0) {
+ message = new String(messageData);
+ }
+
+ if (message.isEmpty()) {
+ Cursor curPart1 = mainActivity.getContentResolver().query(
+ uriMMSPart,
+ null,
+ Telephony.Mms.Part.MSG_ID + " = " + id + " and "+ Telephony.Mms.Part._ID + " = " + partId,
+ null,
+ Telephony.Mms.Part._ID
+ );
+ for (int i = 0; i < curPart1.getColumnCount(); i++)
+ {
+ Log.d(TAG,"Column Name : " + curPart1.getColumnName(i));
+ }
+ curPart1.moveToLast();
+ message = curPart1.getString(13);
+ }
+ Log.d(TAG,"Txt Message = " + message);
+ } else if (isImageType(contentType) || isVideoType(contentType)) {
+ // Get the media.
+
+ if (isImageType(contentType)) {
+ messageType = Matrix.MESSAGE_TYPE_IMAGE;
+ } else if (isVideoType(contentType)) {
+ messageType = Matrix.MESSAGE_TYPE_VIDEO;
+ }
+ Log.i(TAG, "==== Get the media start ====");
+ fileType = contentType;
+ mediaData = readMMSPart(partId);
+ Log.i(TAG, "Media data length == " + mediaData.length);
+ }
+ } while (curPart.moveToPrevious());
+
+
+
+ // Get the sender's address.
+ Uri uriMMSAddr = Uri.parse("content://mms/" + id + "/addr");
+ Cursor addrCur = mainActivity.getContentResolver().query(
+ uriMMSAddr,
+ null,
+ Telephony.Mms.Addr.TYPE + " = 137", // PduHeaders.FROM
+ null,
+ Telephony.Mms.Addr._ID
+ );
+ if (addrCur != null) {
+ addrCur.moveToLast();
+ do{
+ Log.d(TAG, "addrCur records length = " + addrCur.getCount());
+ if (addrCur.getCount() > 0) {
+ address = addrCur.getString(addrCur.getColumnIndex(Telephony.Mms.Addr.ADDRESS));
+ }
+ Log.d(TAG, "address = " + address);
+
+ if (!message.isEmpty()) {
+ Utilities.sendMatrix(mainActivity, message, address, messageType);
+ }
+ if (mediaData != null) {
+ Utilities.sendMatrix(
+ mainActivity,
+ mediaData,
+ address,
+ messageType,
+ fileName,
+ fileType
+ );
+ }
+ } while (addrCur.moveToPrevious());
+ }
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ }
+ }
+ }
+
+
+ private byte[] readMMSPart(String partId) {
+ byte[] partData = null;
+ Uri partURI = Uri.parse("content://mms/part/" + partId);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ InputStream is = null;
+
+ try {
+
+ Log.i(TAG,"Entered into readMMSPart try.");
+ ContentResolver mContentResolver = mainActivity.getContentResolver();
+ is = mContentResolver.openInputStream(partURI);
+
+ byte[] buffer = new byte[256];
+ int len = is.read(buffer);
+ while (len >= 0) {
+ baos.write(buffer, 0, len);
+ len = is.read(buffer);
+ }
+ partData = baos.toByteArray();
+ //Log.i(TAG, "Text Msg :: " + new String(partData));
+
+ } catch (IOException e) {
+ Log.e(TAG, "Exception == Failed to load part data");
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Exception :: Failed to close stream");
+ }
+ }
+ }
+ return partData;
+ }
+
+
+ private boolean isImageType(String mime) {
+ boolean result = false;
+ if (mime.equalsIgnoreCase("image/jpg")
+ || mime.equalsIgnoreCase("image/jpeg")
+ || mime.equalsIgnoreCase("image/png")
+ || mime.equalsIgnoreCase("image/gif")
+ || mime.equalsIgnoreCase("image/bmp")) {
+ result = true;
+ }
+ return result;
+ }
+
+
+ private boolean isVideoType(String mime) {
+ boolean result = false;
+ if (mime.equalsIgnoreCase("video/3gpp")
+ || mime.equalsIgnoreCase("video/3gpp2")
+ || mime.equalsIgnoreCase("video/avi")
+ || mime.equalsIgnoreCase("video/mp4")
+ || mime.equalsIgnoreCase("video/mpeg")
+ || mime.equalsIgnoreCase("video/webm")) {
+ result = true;
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/eu/droogers/smsmatrix/MainActivity.java b/app/src/main/java/eu/droogers/smsmatrix/MainActivity.java
index 5923873..8f1ff99 100644
--- a/app/src/main/java/eu/droogers/smsmatrix/MainActivity.java
+++ b/app/src/main/java/eu/droogers/smsmatrix/MainActivity.java
@@ -72,6 +72,7 @@ public class MainActivity extends Activity {
}
private void checkPermissions() {
+ askPermission(Manifest.permission.READ_SMS);
askPermission(Manifest.permission.SEND_SMS);
askPermission(Manifest.permission.READ_PHONE_STATE);
askPermission(Manifest.permission.READ_CONTACTS);
diff --git a/app/src/main/java/eu/droogers/smsmatrix/Matrix.java b/app/src/main/java/eu/droogers/smsmatrix/Matrix.java
index e7c252b..93481fc 100644
--- a/app/src/main/java/eu/droogers/smsmatrix/Matrix.java
+++ b/app/src/main/java/eu/droogers/smsmatrix/Matrix.java
@@ -1,11 +1,13 @@
package eu.droogers.smsmatrix;
import android.content.Context;
+import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.telephony.SmsManager;
import android.util.Log;
+import android.widget.Toast;
import com.google.gson.JsonElement;
@@ -22,12 +24,14 @@ import org.matrix.androidsdk.data.store.IMXStoreListener;
import org.matrix.androidsdk.data.store.MXFileStore;
import org.matrix.androidsdk.data.store.MXMemoryStore;
import org.matrix.androidsdk.listeners.IMXEventListener;
+import org.matrix.androidsdk.listeners.MXMediaUploadListener;
import org.matrix.androidsdk.rest.callback.SimpleApiCallback;
import org.matrix.androidsdk.rest.client.LoginRestClient;
import org.matrix.androidsdk.rest.model.Event;
import org.matrix.androidsdk.rest.model.Message;
import org.matrix.androidsdk.rest.model.login.Credentials;
+import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -58,6 +62,12 @@ public class Matrix {
private String realUserid;
+ // Message type constants.
+ public static final String MESSAGE_TYPE_TEXT = "m.text";
+ public static final String MESSAGE_TYPE_IMAGE = "m.image";
+ public static final String MESSAGE_TYPE_VIDEO = "m.video";
+ public static final String MESSAGE_TYPE_NOTICE = "m.notice";
+
public Matrix(final Context context, String url, String botUsername, String botPassword, String username, String device, String syncDelay, String syncTimeout) {
this.context = context;
hsConfig = new HomeServerConnectionConfig(Uri.parse(url));
@@ -172,6 +182,45 @@ public class Matrix {
}
}
+ public void sendFile(
+ final String phoneNumber,
+ final byte[] body,
+ final String type,
+ final String fileName,
+ final String contentType
+ ) {
+ String uploadID = String.valueOf(transaction);
+ transaction++;
+ session.getMediasCache().uploadContent(
+ new ByteArrayInputStream(body),
+ fileName,
+ contentType,
+ uploadID,
+ new MXMediaUploadListener()
+ {
+ @Override
+ public void onUploadComplete(final String uploadId, final String contentUri) {
+ Room room = getRoomByPhonenumber(phoneNumber);
+ JsonObject json = new JsonObject();
+ json.addProperty("body", fileName);
+ json.addProperty("msgtype", type);
+ json.addProperty("url", contentUri);
+ JsonObject info = new JsonObject();
+ info.addProperty("mimetype", contentType);
+ json.add("info", info);
+ session.getRoomsApiClient().sendEventToRoom(
+ String.valueOf(transaction),
+ room.getRoomId(),
+ "m.room.message",
+ json,
+ new SimpleApiCallback()
+ );
+ transaction++;
+ }
+ }
+ );
+ }
+
private void changeDisplayname(String roomId, String displayname) {
Map params = new HashMap<>();
params.put("displayname", displayname);
@@ -203,10 +252,17 @@ public class Matrix {
public void sendEvent(Event event) {
if (event.sender.equals(realUserid)) {
Room room = store.getRoom(event.roomId);
- JsonElement json = event.getContent();
- String body = json.getAsJsonObject().get("body").getAsString();
SmsManager smsManager = SmsManager.getDefault();
- smsManager.sendTextMessage(room.getTopic(), null, body, null, null);
+ JsonObject json = event.getContent().getAsJsonObject();
+
+ if (json.get("msgtype").getAsString().equals(MESSAGE_TYPE_TEXT)) {
+ String body = json.get("body").getAsString();
+ smsManager.sendTextMessage(room.getTopic(), null, body, null, null);
+ } else {
+ String url = session.getContentManager().getDownloadableUrl(json.get("url").getAsString());
+ smsManager.sendTextMessage(room.getTopic(), null, url, null, null);
+ }
+
room.markAllAsRead(new SimpleApiCallback());
}
}
diff --git a/app/src/main/java/eu/droogers/smsmatrix/MatrixService.java b/app/src/main/java/eu/droogers/smsmatrix/MatrixService.java
index c8443c0..f08aa0c 100644
--- a/app/src/main/java/eu/droogers/smsmatrix/MatrixService.java
+++ b/app/src/main/java/eu/droogers/smsmatrix/MatrixService.java
@@ -23,6 +23,7 @@ public class MatrixService extends Service {
private String hsUrl;
private String syncDelay;
private String syncTimeout;
+ private MMSMonitor mms;
@Override
public void onCreate() {
@@ -49,11 +50,25 @@ public class MatrixService extends Service {
Log.e(TAG, "onStartCommand: Service");
String phone = intent.getStringExtra("SendSms_phone");
- String body = intent.getStringExtra("SendSms_body");
String type = intent.getStringExtra("SendSms_type");
if (phone != null) {
- mx.sendMessage(phone, body, type);
+ if (type.equals(Matrix.MESSAGE_TYPE_TEXT))
+ {
+ String body = intent.getStringExtra("SendSms_body");
+ mx.sendMessage(phone, body, type);
+ } else {
+ byte[] body = intent.getByteArrayExtra("SendSms_body");
+ String fileName = intent.getStringExtra("SendSms_fileName");
+ String contentType = intent.getStringExtra("SendSms_contentType");
+ mx.sendFile(phone, body, type, fileName, contentType);
+ }
}
+
+ if (this.mms == null) {
+ this.mms = new MMSMonitor(this , getApplicationContext());
+ this.mms.startMMSMonitoring();
+ }
+
return START_NOT_STICKY;
}
@@ -61,6 +76,8 @@ public class MatrixService extends Service {
@Override
public void onDestroy() {
mx.destroy();
+ this.mms.stopMMSMonitoring();
+ this.mms = null;
super.onDestroy();
}
diff --git a/app/src/main/java/eu/droogers/smsmatrix/ReceiverListener.java b/app/src/main/java/eu/droogers/smsmatrix/ReceiverListener.java
index caada80..db19e36 100644
--- a/app/src/main/java/eu/droogers/smsmatrix/ReceiverListener.java
+++ b/app/src/main/java/eu/droogers/smsmatrix/ReceiverListener.java
@@ -36,7 +36,7 @@ public class ReceiverListener extends BroadcastReceiver {
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
msg_from = msgs[i].getOriginatingAddress();
String msgBody = msgs[i].getMessageBody();
- sendMatrix(context, msgBody, msg_from, "m.text");
+ Utilities.sendMatrix(context, msgBody, msg_from, Matrix.MESSAGE_TYPE_TEXT);
}
}catch(Exception e){
Log.d("Exception caught",e.getMessage());
@@ -59,14 +59,6 @@ public class ReceiverListener extends BroadcastReceiver {
body += " is calling";
break;
}
- sendMatrix(context, body, cal_from, "m.notice");
- }
-
- private void sendMatrix(Context context, String body, String phone, String type) {
- Intent intent = new Intent(context, MatrixService.class);
- intent.putExtra("SendSms_phone", phone);
- intent.putExtra("SendSms_body", body);
- intent.putExtra("SendSms_type", type);
- context.startService(intent);
+ Utilities.sendMatrix(context, body, cal_from, Matrix.MESSAGE_TYPE_NOTICE);
}
}
diff --git a/app/src/main/java/eu/droogers/smsmatrix/Utilities.java b/app/src/main/java/eu/droogers/smsmatrix/Utilities.java
new file mode 100644
index 0000000..cd2b27e
--- /dev/null
+++ b/app/src/main/java/eu/droogers/smsmatrix/Utilities.java
@@ -0,0 +1,24 @@
+package eu.droogers.smsmatrix;
+
+import android.content.Context;
+import android.content.Intent;
+
+public class Utilities {
+ public static void sendMatrix(Context context, String body, String phone, String type) {
+ Intent intent = new Intent(context, MatrixService.class);
+ intent.putExtra("SendSms_phone", phone);
+ intent.putExtra("SendSms_body", body);
+ intent.putExtra("SendSms_type", type);
+ context.startService(intent);
+ }
+
+ public static void sendMatrix(Context context, byte[] body, String phone, String type, String fileName, String contentType) {
+ Intent intent = new Intent(context, MatrixService.class);
+ intent.putExtra("SendSms_phone", phone);
+ intent.putExtra("SendSms_body", body);
+ intent.putExtra("SendSms_type", type);
+ intent.putExtra("SendSms_fileName", fileName);
+ intent.putExtra("SendSms_contentType", contentType);
+ context.startService(intent);
+ }
+}
diff --git a/build.gradle b/build.gradle
index a47fa4b..7e01a0a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,6 +3,7 @@
buildscript {
repositories {
jcenter()
+ google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
@@ -15,6 +16,7 @@ buildscript {
allprojects {
repositories {
jcenter()
+ google()
}
}