Added a database for incomming SMS, persistent notification, and MMS changes

pull/42/head
untidylamp 5 years ago
parent 012093a20d
commit ea130cece2

@ -0,0 +1,29 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
</code_scheme>
</component>

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

@ -1,3 +0,0 @@
<component name="CopyrightManager">
<settings default="" />
</component>

@ -5,26 +5,31 @@
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<list size="7">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<list size="6">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

@ -2,7 +2,7 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/SmsMatrix.iml" filepath="$PROJECT_DIR$/SmsMatrix.iml" />
<module fileurl="file://$PROJECT_DIR$/SmsMatrix-using.iml" filepath="$PROJECT_DIR$/SmsMatrix-using.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -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', {

@ -4,8 +4,14 @@
package="eu.droogers.smsmatrix">
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.READ_MMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.SEND_MMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
@ -28,6 +34,10 @@
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>

@ -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;
}
}

@ -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 )";
}
}

@ -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);
}
}

@ -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;
}
}

@ -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 {

@ -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<Void>());
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<Event>()
);
String.valueOf(transaction),
room.getRoomId(),
"m.room.message",
json,
new SimpleApiCallback<Event>(){
@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<Void>());
}
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<Event>());
session.getRoomsApiClient().sendMessage(String.valueOf(transaction), room.getRoomId(), msg, new SimpleApiCallback<Event>(){
@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<NotSendMesage> 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();

@ -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<String, String> 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<String, String>(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);
}
}
//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
if (this.mms == null) {
this.mms = new MMSMonitor(this , getApplicationContext());
this.mms.startMMSMonitoring();
}
//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();
}

@ -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) {
}
}

@ -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<String, String> 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<String, String>(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);
//}
}
}

@ -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);
}
}

@ -134,12 +134,33 @@
android:hint="30"
android:inputType="number" />
<CheckBox
android:id="@+id/notification_check_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Persistent Notification" />
<CheckBox
android:id="@+id/mms_check_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="MMS Support (expermental)" />
<Button
android:id="@+id/button_save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Save" />
android:text="Save and Start" />
<Button
android:id="@+id/stop_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Stop Service" />
</LinearLayout>
</ScrollView>
Loading…
Cancel
Save