diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser new file mode 100644 index 0000000..10c1a5d Binary files /dev/null and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 96cc43e..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index ba7052b..e0d5b93 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,26 +5,31 @@ - + diff --git a/.idea/modules.xml b/.idea/modules.xml index 827b8fe..d107048 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 7eb3280..5d03b45 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -27,6 +27,8 @@ android { dependencies { implementation 'com.android.support:appcompat-v7:26.0.0' + + implementation "com.android.support:support-compat:26.0.0" compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 96900c5..d712e47 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,8 +4,14 @@ package="eu.droogers.smsmatrix"> + + + + + + + + + + diff --git a/app/src/main/java/eu/droogers/smsmatrix/DataManager.java b/app/src/main/java/eu/droogers/smsmatrix/DataManager.java new file mode 100644 index 0000000..f2265d5 --- /dev/null +++ b/app/src/main/java/eu/droogers/smsmatrix/DataManager.java @@ -0,0 +1,308 @@ +package eu.droogers.smsmatrix; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteDatabase; +import android.util.Log; + +import static eu.droogers.smsmatrix.DatabaseContract.SmsEntry; +import static eu.droogers.smsmatrix.DatabaseContract.MmsEntry; + +public class DataManager { + + private static DataManager ourInsance = null; + private static final String LOG_TAG = "UntidyLamp.DataManager"; + public static final String[] ALLColumns = new String[] { "*" }; + public static final String unread = "locked=0 AND read=0"; + public static final String mmsTrIdError = "locked=1 AND read=0 AND error_code=1 AND mms_id=0"; + //final String[] whatColumns = {SmsEntry.COLUMN_ADDRESS}; + public static final int TYPE_RECIEVED = 2; //2 is recieved (1 is sent) + public static final int NOT_READ = 0; //messages has not been read yet + public static final int IS_READ = 1; //message has been read + public static final int NO_STATUS = -1; //No status yet + public static final int NOT_LOCKED = 0; //its not locked + public static final int LOCKED = 1; //its locked + public static final int ERROR_NO = 0; //no error yet + public static final int ERROR_onUnexpectedError = 1; + public static final int ERROR_onMatrixError = 2; + public static final int ERROR_onNetworkError = 3; + + public static final int MMS_TR_ID_ERROR = 1; // cant find tr_id from onRecieve in mmssms.db + + public static DataManager getInstance() { + if(ourInsance == null) { + ourInsance = new DataManager(); + } + return ourInsance; + } + + public static int dumpSmses(OpenHelper dbHelper) { + Log.i(LOG_TAG, "dumpSmses"); + SQLiteDatabase db = dbHelper.getReadableDatabase(); + Cursor smsQueryCursor = db.query(DatabaseContract.SmsEntry.TABLE_NAME, ALLColumns, null, null, null, null, null); + Log.i(LOG_TAG, "Heres what's in the cursor " + DatabaseUtils.dumpCursorToString(smsQueryCursor) ); + int smsesCount = smsQueryCursor.getCount(); + smsQueryCursor.close(); + Log.i(LOG_TAG, "dumpSmses is done"); + return smsesCount; + } + + + public static boolean markSmsRead(OpenHelper dbHelper, int smsId) { + Log.i(LOG_TAG, "markSmsRead called"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(SmsEntry.COLUMN_READ, IS_READ); + try { + db.update(DatabaseContract.SmsEntry.TABLE_NAME, values, "_id=" + smsId, null ); + db.close(); + return true; + } catch (Exception e) { + Log.e(LOG_TAG, "markSmsRead failed " + e ); + db.close(); + return false; + } + } + + public static boolean lockSms(OpenHelper dbHelper, int smsId) { + Log.i(LOG_TAG, "lockSms called"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(SmsEntry.COLUMN_LOCKED, LOCKED); + try { + db.update(DatabaseContract.SmsEntry.TABLE_NAME, values, "_id=" + smsId, null ); + db.close(); + return true; + } catch (Exception e) { + Log.e(LOG_TAG, "lockSms failed " + e ); + db.close(); + return false; + } + } + + public static boolean unlockSms(OpenHelper dbHelper, int smsId) { + Log.i(LOG_TAG, "unlockSms called"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(SmsEntry.COLUMN_LOCKED, NOT_LOCKED); + try { + db.update(DatabaseContract.SmsEntry.TABLE_NAME, values, "_id=" + smsId, null ); + db.close(); + return true; + } catch (Exception e) { + Log.e(LOG_TAG, "unlockSms failed " + e ); + db.close(); + return false; + } + } + + public static boolean errorSms(OpenHelper dbHelper, int smsId, int error) { + Log.i(LOG_TAG, "errorSms called"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(SmsEntry.COLUMN_ERROR_CODE, error); + try { + db.update(DatabaseContract.SmsEntry.TABLE_NAME, values, "_id=" + smsId, null ); + db.close(); + return true; + } catch (Exception e) { + Log.e(LOG_TAG, "errorSms failed " + e ); + db.close(); + return false; + } + } + + + public static int dumpMmses(OpenHelper dbHelper) { + Log.i(LOG_TAG, "dumpMmses"); + SQLiteDatabase db = dbHelper.getReadableDatabase(); + Cursor mmsQueryCursor = db.query(DatabaseContract.MmsEntry.TABLE_NAME, ALLColumns, null, null, null, null, null); + Log.i(LOG_TAG, "Heres what's in the cursor " + DatabaseUtils.dumpCursorToString(mmsQueryCursor) ); + int mmsesCount = mmsQueryCursor.getCount(); + mmsQueryCursor.close(); + db.close(); + Log.i(LOG_TAG, "dumpMmses is done"); + return mmsesCount; + } + + + public static boolean markMmsRead(OpenHelper dbHelper, int mmsId) { + Log.i(LOG_TAG, "markMmsRead called"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(MmsEntry.COLUMN_READ, IS_READ); + try { + db.update(DatabaseContract.MmsEntry.TABLE_NAME, values, "_id=" + mmsId, null ); + db.close(); + return true; + } catch (Exception e) { + Log.e(LOG_TAG, "markMmsRead failed " + e ); + db.close(); + return false; + } + + } + + public static boolean lockMms(OpenHelper dbHelper, int mmsId) { + Log.i(LOG_TAG, "lockMms called"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(MmsEntry.COLUMN_LOCKED, LOCKED); + try { + db.update(DatabaseContract.MmsEntry.TABLE_NAME, values, "_id=" + mmsId, null ); + db.close(); + return true; + } catch (Exception e) { + Log.e(LOG_TAG, "lockMms failed " + e ); + db.close(); + return false; + } + } + + public static boolean unlockMms(OpenHelper dbHelper, int mmsId) { + Log.i(LOG_TAG, "unlockMms called"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(MmsEntry.COLUMN_LOCKED, NOT_LOCKED); + try { + db.update(DatabaseContract.MmsEntry.TABLE_NAME, values, "_id=" + mmsId, null ); + db.close(); + return true; + } catch (Exception e) { + Log.e(LOG_TAG, "unlockMms failed " + e ); + db.close(); + return false; + } + } + + public static boolean errorMms(OpenHelper dbHelper, int mmsId, int error) { + Log.i(LOG_TAG, "errorMms called"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(MmsEntry.COLUMN_ERROR_CODE, error); + try { + db.update(DatabaseContract.MmsEntry.TABLE_NAME, values, "_id=" + mmsId, null ); + db.close(); + return true; + } catch (Exception e) { + Log.e(LOG_TAG, "errorMms failed " + e ); + db.close(); + return false; + } + } + + public static int countSmses(OpenHelper dbHelper) { + Log.i(LOG_TAG, "countSmses"); + SQLiteDatabase db = dbHelper.getReadableDatabase(); + Cursor countSmsesCursor = db.query(DatabaseContract.SmsEntry.TABLE_NAME, ALLColumns, null, null, null, null, null); + int smsesCount = countSmsesCursor.getCount(); + countSmsesCursor.close(); + db.close(); + Log.i(LOG_TAG, "countSmses is done"); + return smsesCount; + } + + public static int countMmses(OpenHelper dbHelper) { + Log.i(LOG_TAG, "countMmses"); + SQLiteDatabase db = dbHelper.getReadableDatabase(); + Cursor countMmsesCursor = db.query(DatabaseContract.MmsEntry.TABLE_NAME, ALLColumns, null, null, null, null, null); + int mmsesCount = countMmsesCursor.getCount(); + countMmsesCursor.close(); + db.close(); + Log.i(LOG_TAG, "countMmses is done"); + return mmsesCount; + } + + public static long importSms(OpenHelper dbHelper, String address, long date, long dateSent, int read, int type, int status, String body, int locked, int errorCode) { + Log.i(LOG_TAG, "importSms"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(DatabaseContract.SmsEntry.COLUMN_ADDRESS, address); + values.put(DatabaseContract.SmsEntry.COLUMN_DATE, date); + values.put(DatabaseContract.SmsEntry.COLUMN_DATE_SENT, dateSent); + values.put(DatabaseContract.SmsEntry.COLUMN_READ, read); + values.put(DatabaseContract.SmsEntry.COLUMN_STATUS, status); + values.put(DatabaseContract.SmsEntry.COLUMN_TYPE, type); + values.put(DatabaseContract.SmsEntry.COLUMN_BODY, body); + values.put(DatabaseContract.SmsEntry.COLUMN_LOCKED, locked); + values.put(DatabaseContract.SmsEntry.COLUMN_ERROR_CODE, errorCode); + try { + long smsImportRowId = db.insert(DatabaseContract.SmsEntry.TABLE_NAME, null, values); + Log.i(LOG_TAG, "smsImportRowId " + smsImportRowId ); + db.close(); + return smsImportRowId; + } catch (Exception e) { + Log.e(LOG_TAG, "importSms failed " + e ); + db.close(); + return -1; + } + } + + public static void updateLongSmsBody (OpenHelper dbHelper, long id, String body ){ + + Log.i(LOG_TAG, "updateLongSmsBody"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(DatabaseContract.SmsEntry.COLUMN_BODY, body); + + try { + Log.i(LOG_TAG, " try updateLongSmsBody _id=" + id ); + db.update(DatabaseContract.SmsEntry.TABLE_NAME, values, "_id=" + id, null ); + } catch (Exception e) { + Log.e(LOG_TAG, "updateLongSmsBody failed " + e ); + } + db.close(); + } + + + public static long importMms(OpenHelper dbHelper, String tr_id, String address, long date, long dateSent, int read, int type, int mmsId, int status, String body, int locked, int errorCode) { + Log.i(LOG_TAG, "importMms"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(DatabaseContract.MmsEntry.COLUMN_TR_ID, tr_id); + values.put(DatabaseContract.MmsEntry.COLUMN_ADDRESS, address); + values.put(DatabaseContract.MmsEntry.COLUMN_DATE, date); + values.put(DatabaseContract.MmsEntry.COLUMN_DATE_SENT, dateSent); + values.put(DatabaseContract.MmsEntry.COLUMN_READ, read); + values.put(DatabaseContract.MmsEntry.COLUMN_STATUS, status); + values.put(DatabaseContract.MmsEntry.COLUMN_TYPE, type); + values.put(DatabaseContract.MmsEntry.COLUMN_MMS_ID, mmsId); + values.put(DatabaseContract.MmsEntry.COLUMN_BODY, body); + values.put(DatabaseContract.MmsEntry.COLUMN_LOCKED, locked); + values.put(DatabaseContract.MmsEntry.COLUMN_ERROR_CODE, errorCode); + try { + long mmsImportRowId = db.insert(DatabaseContract.MmsEntry.TABLE_NAME, null, values); + Log.i(LOG_TAG, "smsImportRowId " + mmsImportRowId ); + db.close(); + return mmsImportRowId; + } catch (Exception e) { + db.close(); + return -1; + } + } + + public static void updateFailedMms (OpenHelper dbHelper, int id, int mmsId, String body, int locked, int errorCode ){ + Log.i(LOG_TAG, "updateFailedMms"); + SQLiteDatabase db = dbHelper.getWritableDatabase(); + ContentValues values = new ContentValues(); + values.put(DatabaseContract.MmsEntry.COLUMN_MMS_ID, mmsId); + values.put(DatabaseContract.MmsEntry.COLUMN_BODY, body); + values.put(DatabaseContract.MmsEntry.COLUMN_LOCKED, locked); + values.put(DatabaseContract.MmsEntry.COLUMN_ERROR_CODE, errorCode); + + try { + Log.i(LOG_TAG, " try updateFailedMms _id=" + id ); + db.update(DatabaseContract.MmsEntry.TABLE_NAME, values, "_id=" + id, null ); + } catch (Exception e) { + Log.e(LOG_TAG, "updateFailedMms _id="+ id + " failed: " + e ); + } + db.close(); + } + + public static boolean deleteAll (OpenHelper dbHelper) { + return false; + } + +} diff --git a/app/src/main/java/eu/droogers/smsmatrix/DatabaseContract.java b/app/src/main/java/eu/droogers/smsmatrix/DatabaseContract.java new file mode 100644 index 0000000..bb482eb --- /dev/null +++ b/app/src/main/java/eu/droogers/smsmatrix/DatabaseContract.java @@ -0,0 +1,68 @@ +package eu.droogers.smsmatrix; + +import android.provider.BaseColumns; + +public final class DatabaseContract { + private DatabaseContract () {} + + public static final class SmsEntry implements BaseColumns { + public static final String TABLE_NAME = "sms"; + public static final String COLUMN_ADDRESS = "address"; + public static final String COLUMN_DATE = "date"; + public static final String COLUMN_DATE_SENT = "date_sent"; + public static final String COLUMN_READ = "read"; + public static final String COLUMN_STATUS = "status"; + public static final String COLUMN_TYPE = "type"; + public static final String COLUMN_BODY = "body"; + public static final String COLUMN_LOCKED = "locked"; + public static final String COLUMN_ERROR_CODE = "error_code"; + + public static final String SQL_CREATE_TABLE = + "CREATE TABLE " + TABLE_NAME + " (" + + _ID + " INTEGER PRIMARY KEY, " + + COLUMN_ADDRESS + " TEXT NOT NULL, " + + COLUMN_DATE + " INTEGER NOT NULL, " + + COLUMN_DATE_SENT + " INTEGER NOT NULL, " + + COLUMN_READ + " INTEGER NOT NULL, " + + COLUMN_STATUS + " INTEGER NOT NULL, " + + COLUMN_TYPE + " INTEGER NOT NULL, " + + COLUMN_BODY + " TEXT NOT NULL, " + + COLUMN_LOCKED + " INTEGER, " + + COLUMN_ERROR_CODE + " INTEGER )"; + + + } + + public static final class MmsEntry implements BaseColumns { + public static final String TABLE_NAME = "mms"; + public static final String COLUMN_TR_ID = "tr_id"; + public static final String COLUMN_ADDRESS = "address"; + public static final String COLUMN_DATE = "date"; + public static final String COLUMN_DATE_SENT = "date_sent"; + public static final String COLUMN_READ = "read"; + public static final String COLUMN_STATUS = "status"; + public static final String COLUMN_TYPE = "type"; + public static final String COLUMN_MMS_ID = "mms_id"; + public static final String COLUMN_BODY = "body"; + public static final String COLUMN_LOCKED = "locked"; + public static final String COLUMN_ERROR_CODE = "error_code"; + + public static final String SQL_CREATE_TABLE = + "CREATE TABLE " + TABLE_NAME + " (" + + _ID + " INTEGER PRIMARY KEY, " + + COLUMN_TR_ID + " TEXT NOT NULL, " + + COLUMN_ADDRESS + " TEXT NOT NULL, " + + COLUMN_DATE + " INTEGER NOT NULL, " + + COLUMN_DATE_SENT + " INTEGER NOT NULL, " + + COLUMN_READ + " INTEGER NOT NULL, " + + COLUMN_STATUS + " INTEGER NOT NULL, " + + COLUMN_TYPE + " INTEGER NOT NULL, " + + COLUMN_MMS_ID + " INTEGER NOT NULL, " + + COLUMN_BODY + " TEXT, " + + COLUMN_LOCKED + " INTEGER, " + + COLUMN_ERROR_CODE + " INTEGER )"; + } + + + +} diff --git a/app/src/main/java/eu/droogers/smsmatrix/DatabaseDataWorker.java b/app/src/main/java/eu/droogers/smsmatrix/DatabaseDataWorker.java new file mode 100644 index 0000000..b4ccbcb --- /dev/null +++ b/app/src/main/java/eu/droogers/smsmatrix/DatabaseDataWorker.java @@ -0,0 +1,50 @@ +package eu.droogers.smsmatrix; + +import android.content.ContentValues; +import android.database.sqlite.SQLiteDatabase; +import android.provider.ContactsContract; + + +public class DatabaseDataWorker { + private SQLiteDatabase mDb; + public DatabaseDataWorker(SQLiteDatabase db) { + mDb = db; + } + + + + private void insertSms(int address, int date, int dateSent, int read, int type, int status, String body, int locked, int errorCode) { + ContentValues values = new ContentValues(); + values.put(DatabaseContract.SmsEntry.COLUMN_ADDRESS, address); + values.put(DatabaseContract.SmsEntry.COLUMN_DATE, date); + values.put(DatabaseContract.SmsEntry.COLUMN_DATE_SENT, dateSent); + values.put(DatabaseContract.SmsEntry.COLUMN_READ, read); + values.put(DatabaseContract.SmsEntry.COLUMN_STATUS, status); + values.put(DatabaseContract.SmsEntry.COLUMN_TYPE, type); + values.put(DatabaseContract.SmsEntry.COLUMN_BODY, body); + values.put(DatabaseContract.SmsEntry.COLUMN_LOCKED, locked); + values.put(DatabaseContract.SmsEntry.COLUMN_ERROR_CODE, errorCode); + + long newRowId = mDb.insert(DatabaseContract.SmsEntry.TABLE_NAME, null, values); + } + + private void insertMms(String tr_id, int address, int date, int dateSent, int read, int type, int mmsId, int status, String body, int locked, int errorCode) { + ContentValues values = new ContentValues(); + values.put(DatabaseContract.MmsEntry.COLUMN_TR_ID, tr_id); + values.put(DatabaseContract.MmsEntry.COLUMN_ADDRESS, address); + values.put(DatabaseContract.MmsEntry.COLUMN_DATE, date); + values.put(DatabaseContract.MmsEntry.COLUMN_DATE_SENT, dateSent); + values.put(DatabaseContract.MmsEntry.COLUMN_READ, read); + values.put(DatabaseContract.MmsEntry.COLUMN_STATUS, status); + values.put(DatabaseContract.MmsEntry.COLUMN_TYPE, type); + values.put(DatabaseContract.MmsEntry.COLUMN_MMS_ID, mmsId); + values.put(DatabaseContract.MmsEntry.COLUMN_BODY, body); + values.put(DatabaseContract.MmsEntry.COLUMN_LOCKED, locked); + values.put(DatabaseContract.MmsEntry.COLUMN_ERROR_CODE, errorCode); + + long newRowId = mDb.insert(DatabaseContract.MmsEntry.TABLE_NAME, null, values); + } + + + +} diff --git a/app/src/main/java/eu/droogers/smsmatrix/MMSMonitor.java b/app/src/main/java/eu/droogers/smsmatrix/MMSMonitor.java deleted file mode 100644 index 76c9764..0000000 --- a/app/src/main/java/eu/droogers/smsmatrix/MMSMonitor.java +++ /dev/null @@ -1,302 +0,0 @@ -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 8c2334e..f5d5187 100644 --- a/app/src/main/java/eu/droogers/smsmatrix/MainActivity.java +++ b/app/src/main/java/eu/droogers/smsmatrix/MainActivity.java @@ -2,6 +2,7 @@ package eu.droogers.smsmatrix; import android.Manifest; import android.app.Activity; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -10,6 +11,7 @@ import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; +import android.widget.CheckBox; import android.widget.EditText; import android.support.v4.app.ActivityCompat; @@ -20,6 +22,7 @@ import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.READ_PHONE_STATE; import static android.Manifest.permission.READ_SMS; import static android.Manifest.permission.RECEIVE_SMS; +import static android.Manifest.permission.RECEIVE_MMS; import static android.Manifest.permission.SEND_SMS; import static android.content.ContentValues.TAG; @@ -34,7 +37,7 @@ public class MainActivity extends Activity { private EditText syncDelay; private EditText syncTimeout; private static final String[] PERMISSIONS_REQUIRED = new String[]{ - READ_SMS, SEND_SMS, RECEIVE_SMS, READ_PHONE_STATE, READ_CONTACTS, READ_EXTERNAL_STORAGE + READ_SMS, SEND_SMS, RECEIVE_SMS, RECEIVE_MMS, READ_PHONE_STATE, READ_CONTACTS, READ_EXTERNAL_STORAGE }; private static final int PERMISSION_REQUEST_CODE = 200; @@ -51,6 +54,8 @@ public class MainActivity extends Activity { hsUrl = (EditText) findViewById(R.id.editText_hsUrl); syncDelay = (EditText) findViewById(R.id.editText_syncDelay); syncTimeout = (EditText) findViewById(R.id.editText_syncTimeout); + final CheckBox notificationCheckBox = (CheckBox) findViewById(R.id.notification_check_box); + final CheckBox mmsCheckBox = (CheckBox) findViewById(R.id.mms_check_box); botUsername.setText(sp.getString("botUsername", "")); botPassword.setText(sp.getString("botPassword", "")); @@ -59,6 +64,8 @@ public class MainActivity extends Activity { hsUrl.setText(sp.getString("hsUrl", "")); syncDelay.setText(sp.getString("syncDelay", "12")); syncTimeout.setText(sp.getString("syncTimeout", "30")); + notificationCheckBox.setChecked(sp.getBoolean("notificationCheckBoxStatus", false)); + mmsCheckBox.setChecked(sp.getBoolean("mmsCheckBoxStatus", false)); Button saveButton = (Button) findViewById(R.id.button_save); @@ -76,6 +83,8 @@ public class MainActivity extends Activity { editor.putString("hsUrl", hsUrl.getText().toString()); editor.putString("syncDelay", syncDelay.getText().toString()); editor.putString("syncTimeout", syncTimeout.getText().toString()); + editor.putBoolean("notificationCheckBoxStatus", notificationCheckBox.isChecked()); + editor.putBoolean("mmsCheckBoxStatus", mmsCheckBox.isChecked()); editor.apply(); Log.e(TAG, "onClick: " + botUsername.getText().toString() ); @@ -84,6 +93,23 @@ public class MainActivity extends Activity { } }); + + + + Button stopButton = (Button) findViewById(R.id.stop_button); + stopButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View testButtonView) { + if (!checkPermissions()) { + askPermissions(); + } else { + + Intent intnet = new Intent(getApplicationContext(), eu.droogers.smsmatrix.MatrixService.class); + stopService(intnet); + } + } + }); + if (!checkPermissions()) { askPermissions(); } else { diff --git a/app/src/main/java/eu/droogers/smsmatrix/Matrix.java b/app/src/main/java/eu/droogers/smsmatrix/Matrix.java index b251858..4e69d93 100644 --- a/app/src/main/java/eu/droogers/smsmatrix/Matrix.java +++ b/app/src/main/java/eu/droogers/smsmatrix/Matrix.java @@ -28,6 +28,7 @@ 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.MatrixError; import org.matrix.androidsdk.rest.model.Message; import org.matrix.androidsdk.rest.model.login.Credentials; @@ -90,6 +91,12 @@ public class Matrix { super.onSuccess(credentials); onLogin(credentials); } + + @Override + public void onNetworkError(Exception e) { + //show in notification + super.onNetworkError(e); + } }); } @@ -155,7 +162,7 @@ public class Matrix { } } - public void sendMessage(final String phoneNumber, final String body, final String type) { + public void sendMessage(final String phoneNumber, final String body, final String type, final int databaseId) { if (session != null && session.isAlive()) { Room room = getRoomByPhonenumber(phoneNumber); if (room == null) { @@ -168,17 +175,23 @@ public class Matrix { session.getRoomsApiClient().updateTopic(info, phoneNumber, new SimpleApiCallback()); changeDisplayname(info, getContactName(phoneNumber, context)); Room room = store.getRoom(info); - SendMesageToRoom(room, body, type); + SendMesageToRoom(room, body, type, databaseId); } }); } } else { changeDisplayname(room.getRoomId(), getContactName(phoneNumber, context)); - SendMesageToRoom(room, body, type); + SendMesageToRoom(room, body, type, databaseId); } } else { + if (databaseId > 0){ + OpenHelper dbHelper = new OpenHelper(context); + DataManager.unlockSms(dbHelper, databaseId); + DataManager.errorSms(dbHelper, databaseId, DataManager.ERROR_onNetworkError); + dbHelper.close(); + } Log.e(tag, "Error with sending message"); - notSendMesages.add(new NotSendMesage(phoneNumber, body, type)); + //notSendMesages.add(new NotSendMesage(phoneNumber, body, type)); } } @@ -187,7 +200,8 @@ public class Matrix { final byte[] body, final String type, final String fileName, - final String contentType + final String contentType, + final int databaseId ) { String uploadID = String.valueOf(transaction); transaction++; @@ -209,14 +223,36 @@ public class Matrix { info.addProperty("mimetype", contentType); json.add("info", info); session.getRoomsApiClient().sendEventToRoom( - String.valueOf(transaction), - room.getRoomId(), - "m.room.message", - json, - new SimpleApiCallback() - ); + String.valueOf(transaction), + room.getRoomId(), + "m.room.message", + json, + new SimpleApiCallback(){ + @Override + public void onSuccess(Event info) { + if (databaseId > 0) { + Log.i(TAG, "sendFile onSuccess, Marking _id=" + databaseId + " as read"); + OpenHelper dbHelper = new OpenHelper(context); + DataManager.markMmsRead(dbHelper, databaseId); + DataManager.unlockMms(dbHelper, databaseId); + dbHelper.close(); + } else { + //Case of MMS or other thing. maybe I need to add this into the MMS database to see if text made it. + Log.i(TAG, "sendFile onSuccess, databaseId is 0 - not marking as read"); + } + } + }); transaction++; } + + @Override + public void onUploadError(String uploadId, int serverResponseCode, String serverErrorMessage) { + OpenHelper dbHelper = new OpenHelper(context); + DataManager.errorMms(dbHelper, databaseId, DataManager.ERROR_onUnexpectedError); + DataManager.unlockMms(dbHelper, databaseId); + dbHelper.close(); + super.onUploadError(uploadId, serverResponseCode, serverErrorMessage); + } } ); } @@ -228,11 +264,59 @@ public class Matrix { session.getRoomsApiClient().sendStateEvent(roomId, "m.room.member", session.getMyUserId(), params, new SimpleApiCallback()); } - public void SendMesageToRoom(Room room, String body, String type) { + public void SendMesageToRoom(Room room, String body, String type, final int databaseId) { + Log.i(TAG, "TTTHHHHHIIIISSS SendMesageToRoomSendMesageToRoom" ); Message msg = new Message(); msg.body = body; msg.msgtype = type; - session.getRoomsApiClient().sendMessage(String.valueOf(transaction), room.getRoomId(), msg, new SimpleApiCallback()); + session.getRoomsApiClient().sendMessage(String.valueOf(transaction), room.getRoomId(), msg, new SimpleApiCallback(){ + @Override + public void onSuccess(Event info) { + if (databaseId > 0) { + Log.i(TAG, "SendMessageToRoom onSuccess, Marking _id=" + databaseId + " as read"); + OpenHelper dbHelper = new OpenHelper(context); + DataManager.markSmsRead(dbHelper, databaseId); + DataManager.unlockSms(dbHelper, databaseId); + dbHelper.close(); + } else { + //Case of text in MMS message. + Log.i(TAG, "SendMessageToRoom onSuccess, databaseId is 0 - not marking as read"); + } + } + + @Override + public void onUnexpectedError(Exception e) { + if ( databaseId > 0 ) { + OpenHelper dbHelper = new OpenHelper(context); + DataManager.unlockSms(dbHelper, databaseId); + DataManager.errorSms(dbHelper, databaseId, DataManager.ERROR_onUnexpectedError); + dbHelper.close(); + } + super.onUnexpectedError(e); + } + + @Override + public void onMatrixError(MatrixError e) { + if ( databaseId > 0 ){ + OpenHelper dbHelper = new OpenHelper(context); + DataManager.unlockSms(dbHelper, databaseId); + DataManager.errorSms(dbHelper, databaseId, DataManager.ERROR_onMatrixError); + dbHelper.close(); + } + super.onMatrixError(e); + } + + @Override + public void onNetworkError(Exception e) { + if ( databaseId > 0 ){ + OpenHelper dbHelper = new OpenHelper(context); + DataManager.unlockSms(dbHelper, databaseId); + DataManager.errorSms(dbHelper, databaseId, DataManager.ERROR_onNetworkError); + dbHelper.close(); + } + super.onNetworkError(e); + } + }); transaction++; } @@ -286,7 +370,7 @@ public class Matrix { public void sendMessageList(List messages) { for (NotSendMesage ms : messages) { - sendMessage(ms.getPhone(), ms.getBody(), ms.getType()); + sendMessage(ms.getPhone(), ms.getBody(), ms.getType(), 0); } } @@ -327,6 +411,7 @@ public class Matrix { } public void destroy() { + Log.e(TAG, "marix.java destry called"); session.stopEventStream(); dh.removeListener(evLis); store.close(); diff --git a/app/src/main/java/eu/droogers/smsmatrix/MatrixService.java b/app/src/main/java/eu/droogers/smsmatrix/MatrixService.java index 9fbd89a..de1764b 100644 --- a/app/src/main/java/eu/droogers/smsmatrix/MatrixService.java +++ b/app/src/main/java/eu/droogers/smsmatrix/MatrixService.java @@ -1,14 +1,31 @@ package eu.droogers.smsmatrix; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.Service; -import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; import android.os.IBinder; +import android.support.v4.app.NotificationCompat; +import android.telephony.SmsMessage; import android.util.Log; import android.widget.Toast; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + /** * Created by gerben on 7-10-17. */ @@ -23,7 +40,17 @@ public class MatrixService extends Service { private String hsUrl; private String syncDelay; private String syncTimeout; - private MMSMonitor mms; + private boolean notificationCheckBoxStatus; + private boolean mmsCheckBoxStatus; + + private OpenHelper mDbOpenHelper; + private String onReceiveType = "nothing"; + private int app_id = 0; + + public static NotificationManager notificationManager = null; + public final static int PERSISTENT_NOTIFICATION_ID = 001; + public final static String NOTIFICATION_CHANNEL_ID = "smsmatrix"; + public static NotificationCompat.Builder mBuilder = null; @Override public void onCreate() { @@ -40,10 +67,15 @@ public class MatrixService extends Service { hsUrl = sp.getString("hsUrl", ""); syncDelay = sp.getString("syncDelay", "12"); syncTimeout = sp.getString("syncTimeout", "60"); + notificationCheckBoxStatus = sp.getBoolean("notificationCheckBoxStatus", false); + mmsCheckBoxStatus = sp.getBoolean("mmsCheckBoxStatus", false); if (mx == null && !botUsername.isEmpty() && !botPassword.isEmpty() && !username.isEmpty() && !device.isEmpty() && !hsUrl.isEmpty() && !syncDelay.isEmpty() && !syncTimeout.isEmpty()) { mx = new Matrix(getApplication(), hsUrl, botUsername, botPassword, username, device, syncDelay, syncTimeout); Log.e(TAG, "onStartCommand: " + hsUrl ); + if (notificationCheckBoxStatus){ + persistentNotification(); + } Toast.makeText(this, "service starting:", Toast.LENGTH_SHORT).show(); } else if (mx == null) { Toast.makeText(this, "Missing Information", Toast.LENGTH_SHORT).show(); @@ -51,36 +83,404 @@ public class MatrixService extends Service { Log.e(TAG, "onStartCommand: Service"); - String phone = intent.getStringExtra("SendSms_phone"); - String type = intent.getStringExtra("SendSms_type"); - if (phone != null) { - System.out.println(phone); - if (type.equals(Matrix.MESSAGE_TYPE_TEXT) || type.equals(Matrix.MESSAGE_TYPE_NOTICE)) - { - String body = intent.getStringExtra("SendSms_body"); - mx.sendMessage(phone, body, type); - } else if (type.equals(Matrix.MESSAGE_TYPE_IMAGE) || type.equals(Matrix.MESSAGE_TYPE_VIDEO)) { - 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); - } - } + //From ReceiverListener + onReceiveType = intent.getStringExtra("onReceiveType"); + + //Recieved a new SMS + if (onReceiveType != null && onReceiveType.equals("sms")) { + Log.i(TAG, "SMS "); + try { + mDbOpenHelper = new OpenHelper(this); + } catch (Exception e) { + Log.e(TAG, "error " + e); + } + + try { + Map msg = null; + SmsMessage[] msgs = null; + Bundle bundle = intent.getExtras(); + long sms_id = 0; + + if (bundle != null && bundle.containsKey("pdus")) { + Object[] pdus = (Object[]) bundle.get("pdus"); + + if (pdus != null) { + int nbrOfpdus = pdus.length; + msg = new HashMap(nbrOfpdus); + msgs = new SmsMessage[nbrOfpdus]; + + // Send long SMS of same sender in one message + for (int i = 0; i < nbrOfpdus; i++) { + msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]); + String originatinAddress = msgs[i].getOriginatingAddress(); + + // Check if index with number exists + if (!msg.containsKey(originatinAddress)) { + // Index with number doesn't exist (First message from that person) + //date get NOW date when oncrecieved is called + //long date = Instant.now().toEpochMilli(); + long date = 0; + //date_sent + long date_sent = msgs[i].getTimestampMillis(); + msg.put(msgs[i].getOriginatingAddress(), msgs[i].getMessageBody()); + String fromAddress = msgs[i].getOriginatingAddress(); + String fromBody = msgs[i].getMessageBody(); + sms_id = DataManager.importSms(mDbOpenHelper, + fromAddress, + date, + date_sent, + DataManager.NOT_READ, + DataManager.TYPE_RECIEVED, + DataManager.NO_STATUS, + fromBody, + DataManager.NOT_LOCKED, + DataManager.ERROR_NO); + } else { + //Make sure we know where to put the rest of the long sms data + if (sms_id > 0) { + // Number is there and we have the ID for the first imported long sms. + String previousparts = msg.get(originatinAddress); + String msgString = previousparts + msgs[i].getMessageBody(); + msg.put(originatinAddress, msgString); + + DataManager.updateLongSmsBody(mDbOpenHelper, + sms_id, + msgString); + + } else { + Log.e(TAG, "Problem adding Log SMS to database"); + } + } + } + //start sms stuff + Log.i(TAG, "SMSes done "); + } + } + } catch (Exception e) { + Log.e(TAG, "error " + e); + } - if (this.mms == null) { - this.mms = new MMSMonitor(this , getApplicationContext()); - this.mms.startMMSMonitoring(); } + //Recieved a new SMS END + + //Recieved a new MMS + if (onReceiveType != null && mmsCheckBoxStatus && onReceiveType.equals("mms")) { + Log.i(TAG, "MMS - MMS"); + try { + mDbOpenHelper = new OpenHelper(this); + } catch (Exception e) { + Log.e(TAG, "MMS - OpenHelper error " + e); + } + + //I dont know how to download MMSC from cell provider. so we will do soemthing with mmssms.sb + Bundle bundle = intent.getExtras(); + if (bundle != null && mDbOpenHelper != null) { + byte[] buffer = bundle.getByteArray("data"); + String bufferString = new String(buffer); + Log.i(TAG, "MMS - bufferString: " + bufferString); + + //Get Phone Number (between + and /TYPE + int mmsIndex = bufferString.indexOf("/TYPE"); + int mmsIndexPlus = bufferString.indexOf("+"); + String address = bufferString.substring(mmsIndexPlus, mmsIndex); + //Got phone number, Remove +1 + address = address.replace("+1", ""); + Log.i(TAG, "MMS - buffer address: " + address); + + //Get MMSCURL TR ID (first char string in buffer) + //try to match this with tr_id in mmssms.db + String tr_id = ""; + for (char ch: bufferString.toCharArray()) { + if (Character.isLetterOrDigit(ch) || ch == '_' || ch == '-') { + tr_id += ch; + } else if ( !tr_id.isEmpty() ){ + Log.i(TAG, "MMS - tr_id " + tr_id); + break; + } + } + + //I have no idea how to download the MMSC - we'll query the mmssms.db + //If you can, please fix this or make it better. + Log.i(TAG, "MMS - address " + address); + Log.i(TAG, "MMS - tr_id " + tr_id); + + DataManager.importMms( + mDbOpenHelper, + tr_id, + address, + 0, + 0, + DataManager.NOT_READ, + DataManager.TYPE_RECIEVED, + 0, + DataManager.NO_STATUS, + "", + DataManager.NOT_LOCKED, + DataManager.ERROR_NO); + + //there is a new MMS - Lets sleep to let the default messenger download the MMS + Log.e(TAG, "Sleep to let android download mms "); + try { TimeUnit.SECONDS.sleep(9); } catch (Exception e) {} + + } else { + Log.e(TAG, "MMS - Error with MMS bundle or Database"); + } + + } else if (!mmsCheckBoxStatus) { + Log.i(TAG, "MMS - MMS not enabled"); + } + //Recieved a new MMS END + + + //Ran each time service is started. + //Checks for unread messages in database and send them + if (mx != null ) { + //Check Database everytime something calls this and try to send all unread messages + + // SMS and MMS + OpenHelper dbHelper = new OpenHelper(this); + + + //SMS Start + Log.i(TAG, "checking for SMSes"); + Log.i(TAG, "unreadSmses called"); + SQLiteDatabase unreadSmsesDb = dbHelper.getReadableDatabase(); + String[] notLocked = new String[] { "locked" }; + + + Cursor unreadSms = unreadSmsesDb.query( + DatabaseContract.SmsEntry.TABLE_NAME, + DataManager.ALLColumns, + DataManager.unread, + null, + null, + null, + null); + + + if (unreadSms.moveToFirst()) { + //Found unread SMS + do { + Log.i(TAG, "sending unread messages"); + String body = unreadSms.getString(unreadSms.getColumnIndex("body")); + String address = unreadSms.getString(unreadSms.getColumnIndex("address")); + int smsId = unreadSms.getInt(unreadSms.getColumnIndex("_id")); + //locking SMS + Log.i(TAG, "Locking unread messages"); + DataManager.lockSms(dbHelper, smsId); + //trying to send SMS + Log.i(TAG, "sending unread messages"); + mx.sendMessage(address, body, Matrix.MESSAGE_TYPE_TEXT, smsId); + } while (unreadSms.moveToNext()); + } else { + Log.i(TAG, "No unread SMSes in Database"); + } + unreadSms.close(); + unreadSmsesDb.close(); + // SMS done + + + // MMS Start + if (mmsCheckBoxStatus) { + Log.i(TAG, "Checking for MMSes"); + SQLiteDatabase appDatabase = dbHelper.getReadableDatabase(); + Cursor appDatabaseCursor = appDatabase.query( + DatabaseContract.MmsEntry.TABLE_NAME, + DataManager.ALLColumns, + DataManager.unread, + null, + null, + null, + null); + //Log.i(TAG, "appDatabaseCursor cursor " + DatabaseUtils.dumpCursorToString(appDatabaseCursor) ); + + while (appDatabaseCursor.moveToNext()) { + String appTr_id = appDatabaseCursor.getString(appDatabaseCursor.getColumnIndex("tr_id")); + int app_id = appDatabaseCursor.getInt(appDatabaseCursor.getColumnIndex("_id")); + DataManager.lockMms(dbHelper, app_id); + String address = appDatabaseCursor.getString(appDatabaseCursor.getColumnIndex("address")); + + + + Log.i(TAG, "Found tr_id="+ appTr_id + " in app database marked as unread (not sent)."); + Uri mmsInboxDatabase = Uri.parse("content://mms/inbox"); + + //Match tr_id in app database(that I got from MMS onRecieve) + //to tr_id in the mmssms.db inbox(the pdu table) to get the _id + Cursor mmsInboxDatabaseCursor = getContentResolver().query( + mmsInboxDatabase, + null, + "tr_id='" + appTr_id + "'", + null, + null); + + if (mmsInboxDatabaseCursor.moveToFirst()) { + //there should only be one tr_id match here. + //Log.i(TAG, "Second (only one, want mid cursor " + DatabaseUtils.dumpCursorToString(mmsInboxDatabaseCursor) ); + int mid = mmsInboxDatabaseCursor.getInt(mmsInboxDatabaseCursor.getColumnIndex("_id")); + mmsInboxDatabaseCursor.close(); + + + //the _id from mmssms.db content://mms/inbox(pdu table) will be matched to mid in mmssms.db part + + + String selectionPart = "mid=" + String.valueOf(mid) + " AND NOT ct=\'application/smil\'"; + Uri uri = Uri.parse("content://mms/part"); + Cursor mmsPartCursor = getContentResolver().query(uri, null, selectionPart, null, null ); + Log.i(TAG, "THIRDDDDD cursor " + DatabaseUtils.dumpCursorToString(mmsPartCursor) ); + + //The part table will have 2+ entries with the same mid. + //The first is information about the rest - application/smil - I ignore this + //The second++ is each picture set to us + //The Last (if provided) is the text message along with all the pictures - text/plain + //So an MMS with 2 pictures with text will have 4 parts. information, picture, picture, text. + while (mmsPartCursor.moveToNext()) { + String type = mmsPartCursor.getString(mmsPartCursor.getColumnIndex("ct")); + Log.i(TAG, "typetype: " + type ); + + if (type.equals("text/plain")){ + String text = mmsPartCursor.getString(mmsPartCursor.getColumnIndex("text")); + Log.i(TAG, "MMS message with text: " + text ); + mx.sendMessage(address, text, Matrix.MESSAGE_TYPE_TEXT, 0); + } else { + String name = mmsPartCursor.getString(mmsPartCursor.getColumnIndex("name")); + Log.i(TAG, "MMS message picture: " + name ); + byte[] mediaData = null; + String fileName = ""; + + fileName = mmsPartCursor.getString(mmsPartCursor.getColumnIndex("name")); + Log.e(TAG, "mmsPartCursor - fileName " + fileName); + + mediaData = readMMSPart(mmsPartCursor.getString(mmsPartCursor.getColumnIndex("_id"))); + Log.e(TAG, "mmsPartCursor - mediaData " + mediaData); + + String contentType = mmsPartCursor.getString(mmsPartCursor.getColumnIndex("ct")); + Log.e(TAG, "mmsPartCursor - contentType " + contentType); + + if (isImageType(contentType)) { + mx.sendFile(address, mediaData, Matrix.MESSAGE_TYPE_IMAGE, fileName, contentType, app_id); + } else if (isVideoType(contentType)) { + mx.sendFile(address, mediaData, Matrix.MESSAGE_TYPE_VIDEO, fileName, contentType, app_id); + } + + } + } + } else { + DataManager.unlockMms(dbHelper, app_id); + + Log.e(TAG, "I cant find tr_id="+appTr_id+" in the MMS Inbox. perhaps the MMS has not been downloaded yet"); + mmsInboxDatabaseCursor.close(); + } + + } + + Log.i(TAG, "Unread MMSes have been processes."); + } else { + Log.i(TAG, "MMS not enabled"); + } + // MMS Done + + + + + } + //Ran each time service is started END return START_NOT_STICKY; } + + public void persistentNotification() { + notificationManager = getSystemService(NotificationManager.class); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + + + CharSequence name = "Persistent"; + String description = "Sms Matrix Service is running"; + int importance = NotificationManager.IMPORTANCE_DEFAULT; + NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance); + channel.setDescription(description); + notificationManager.createNotificationChannel(channel); + } + + mBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) + .setSmallIcon(R.mipmap.ic_launcher_round) + .setContentTitle("SmsMatrix") + .setContentText("Matrix service running") + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setOngoing(true); + notificationManager.notify(PERSISTENT_NOTIFICATION_ID, mBuilder.build()); + } + + 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 = 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(); + + } 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; + } + @Override public void onDestroy() { + if (notificationCheckBoxStatus) { + try { + notificationManager.cancel(PERSISTENT_NOTIFICATION_ID); + } catch (Exception e) {} + } mx.destroy(); - this.mms.stopMMSMonitoring(); - this.mms = null; super.onDestroy(); } diff --git a/app/src/main/java/eu/droogers/smsmatrix/OpenHelper.java b/app/src/main/java/eu/droogers/smsmatrix/OpenHelper.java new file mode 100644 index 0000000..4304c3c --- /dev/null +++ b/app/src/main/java/eu/droogers/smsmatrix/OpenHelper.java @@ -0,0 +1,25 @@ +package eu.droogers.smsmatrix; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +public class OpenHelper extends SQLiteOpenHelper { + + public static final String DATABASE_NAME = "SmsMatrix.db"; + public static final int DATABASE_VERSION = 1; + public OpenHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(DatabaseContract.SmsEntry.SQL_CREATE_TABLE); + db.execSQL(DatabaseContract.MmsEntry.SQL_CREATE_TABLE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + } +} diff --git a/app/src/main/java/eu/droogers/smsmatrix/ReceiverListener.java b/app/src/main/java/eu/droogers/smsmatrix/ReceiverListener.java index cf1e6c0..b2d3bb0 100644 --- a/app/src/main/java/eu/droogers/smsmatrix/ReceiverListener.java +++ b/app/src/main/java/eu/droogers/smsmatrix/ReceiverListener.java @@ -1,6 +1,7 @@ package eu.droogers.smsmatrix; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -16,54 +17,34 @@ import java.util.Map; public class ReceiverListener extends BroadcastReceiver { private static final String TAG = "ReceiverListener"; + private static final String ACTION_MMS_RECEIVED = "android.provider.Telephony.WAP_PUSH_RECEIVED"; + public static final String MMS_DATA_TYPE = "application/vnd.wap.mms-message"; + private OpenHelper mDbOpenHelper; + + + + @Override public void onReceive(Context context, Intent intent) { + mDbOpenHelper = new OpenHelper(context); if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){ - handleIncomingSMS(context, intent); + Log.d(TAG, "got SMS"); + Intent newIntent = new Intent(intent); + newIntent.setComponent(new ComponentName(context, eu.droogers.smsmatrix.MatrixService.class)); + newIntent.putExtra("onReceiveType", "sms"); + context.startService(newIntent); + } else if (intent.getAction().equals(ACTION_MMS_RECEIVED) && intent.getType().equals(MMS_DATA_TYPE)) { + Log.d(TAG, "got MMS"); + Intent newIntent = new Intent(intent); + newIntent.setComponent(new ComponentName(context, eu.droogers.smsmatrix.MatrixService.class)); + newIntent.putExtra("onReceiveType", "mms"); + context.startService(newIntent); } else if (intent.getAction().equals("android.intent.action.PHONE_STATE")) { handleIncomingCall(context, intent); } } - private void handleIncomingSMS(Context context, Intent intent) { - Map msg = null; - SmsMessage[] msgs = null; - Bundle bundle = intent.getExtras(); - - if (bundle != null && bundle.containsKey("pdus")) { - Object[] pdus = (Object[]) bundle.get("pdus"); - - if (pdus != null) { - int nbrOfpdus = pdus.length; - msg = new HashMap(nbrOfpdus); - msgs = new SmsMessage[nbrOfpdus]; - - // Send long SMS of same sender in one message - for (int i = 0; i < nbrOfpdus; i++) { - msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]); - - String originatinAddress = msgs[i].getOriginatingAddress(); - - // Check if index with number exists - if (!msg.containsKey(originatinAddress)) { - // Index with number doesn't exist - msg.put(msgs[i].getOriginatingAddress(), msgs[i].getMessageBody()); - - } else { - // Number is there. - String previousparts = msg.get(originatinAddress); - String msgString = previousparts + msgs[i].getMessageBody(); - msg.put(originatinAddress, msgString); - } - } - } - } - for (String originatinAddress : msg.keySet()) { - Utilities.sendMatrix(context, msg.get(originatinAddress), originatinAddress, Matrix.MESSAGE_TYPE_TEXT); - } - } - private void handleIncomingCall(Context context, Intent intent) { String cal_state = intent.getExtras().getString(TelephonyManager.EXTRA_STATE); String cal_from = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER); @@ -79,6 +60,14 @@ public class ReceiverListener extends BroadcastReceiver { body += " is calling"; break; } - Utilities.sendMatrix(context, body, cal_from, Matrix.MESSAGE_TYPE_NOTICE); + //sendMatrix(context, body, cal_from, Matrix.MESSAGE_TYPE_NOTICE); + //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); + //} } + } diff --git a/app/src/main/java/eu/droogers/smsmatrix/Utilities.java b/app/src/main/java/eu/droogers/smsmatrix/Utilities.java deleted file mode 100644 index cd2b27e..0000000 --- a/app/src/main/java/eu/droogers/smsmatrix/Utilities.java +++ /dev/null @@ -1,24 +0,0 @@ -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/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b386f52..339f2d8 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -134,12 +134,33 @@ android:hint="30" android:inputType="number" /> + + + +