diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..9b4a4ed --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Remote SMS \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..0c0c338 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..0897082 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a5f05cd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0609234 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..c3780a0 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,57 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion 30 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.appetize.remotesms" + minSdk 26 + targetSdk 26 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +apply plugin: 'com.android.application' +apply plugin: 'com.google.gms.google-services' + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.3.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.2' + implementation 'com.google.firebase:firebase-database:19.2.1' + + def core_version = "1.6.0" + + implementation "androidx.core:core:$core_version" + testImplementation 'junit:junit:4.+' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + + //room + def room_version = "2.2.0" + implementation "androidx.room:room-runtime:$room_version" + annotationProcessor "androidx.room:room-compiler:$room_version" + + //telegram api + implementation 'com.github.pengrad:java-telegram-bot-api:7.4.0' + + implementation("com.squareup.okhttp3:okhttp:4.12.0") +} \ No newline at end of file diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..d86d566 --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,39 @@ +{ + "project_info": { + "project_number": "330167566800", + "project_id": "remote-sms-8bd49", + "storage_bucket": "remote-sms-8bd49.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:330167566800:android:c3cdf5e9b1fe2c16dff9d5", + "android_client_info": { + "package_name": "com.appetize.remotesms" + } + }, + "oauth_client": [ + { + "client_id": "330167566800-qtisjrr3200jgqscf9cupuv9v0cafc6t.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCdQhkLZrzAufM9aufxIXEE9BysI2X8kfM" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "330167566800-qtisjrr3200jgqscf9cupuv9v0cafc6t.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/appetize/remotesms/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/appetize/remotesms/ExampleInstrumentedTest.java new file mode 100644 index 0000000..75e93cd --- /dev/null +++ b/app/src/androidTest/java/com/appetize/remotesms/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.appetize.remotesms; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.appetize.remotesms", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..71f86ca --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml.orig b/app/src/main/AndroidManifest.xml.orig new file mode 100644 index 0000000..cc19753 --- /dev/null +++ b/app/src/main/AndroidManifest.xml.orig @@ -0,0 +1,62 @@ + + + + + + +<<<<<<< HEAD + +======= + + +>>>>>>> ffc10bc47fc096361f163e2dd464765400da1ef3 + + + + + + + + + + + + + + +<<<<<<< HEAD + + + +======= + + + +>>>>>>> ffc10bc47fc096361f163e2dd464765400da1ef3 + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/appetize/remotesms/AddDevice.java b/app/src/main/java/com/appetize/remotesms/AddDevice.java new file mode 100644 index 0000000..8fbd609 --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/AddDevice.java @@ -0,0 +1,247 @@ +package com.appetize.remotesms; + +import android.content.pm.PackageManager; +import android.graphics.drawable.Animatable; +import android.os.Bundle; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.util.Log; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import com.pengrad.telegrambot.Callback; +import com.pengrad.telegrambot.TelegramBot; +import com.pengrad.telegrambot.model.Message; +import com.pengrad.telegrambot.model.Update; +import com.pengrad.telegrambot.request.GetUpdates; +import com.pengrad.telegrambot.request.SendMessage; +import com.pengrad.telegrambot.response.GetUpdatesResponse; +import com.pengrad.telegrambot.response.SendResponse; + +import java.io.IOException; +import java.util.List; +import java.util.Random; + +public class AddDevice extends AppCompatActivity { + private int page_no; + private long chat_id; + private final String code = randCode(4, 4); + FrameLayout p1; + FrameLayout p2; + Button btn_nxt; + Button btn_back; + SubscriptionManager subscriptionManager; + CheckBox[] boxes; + TelegramBot bot; + List sims; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_add_device); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + page_no = 0; + p1 = (FrameLayout) findViewById(R.id.p1); + p2 = (FrameLayout) findViewById(R.id.p2); + btn_nxt = (Button) findViewById(R.id.btn_nxt); + btn_back = (Button) findViewById(R.id.btn_back); + + ((TextView) findViewById(R.id.conn_code)).setText(code); + bot = new TelegramBot(this.getString(R.string.bot_token)); + + subscriptionManager = SubscriptionManager.from(this); + if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + sims = subscriptionManager.getActiveSubscriptionInfoList(); + Log.d("subscription", "onCreate: "+ sims.get(0).getSubscriptionId()); + LinearLayout ll = findViewById(R.id.ll_sims); + new Thread(new Runnable() { + @Override + public void run() { + boxes = new CheckBox[sims.size()]; + for(int i = 0; i < sims.size(); i++){ + boxes[i] = new CheckBox(AddDevice.this); + boxes[i].setText("SIM " + sims.get(i).getNumber()); + int finalI = i; + runOnUiThread(new Runnable() { + @Override + public void run() { + ll.addView(boxes[finalI]); + } + }); + } + } + }).start(); + } + + public void back(View view) { + switch (page_no){ + case 0: + finish(); + break; + case 1: + page_no = 0; + p1.setVisibility(View.VISIBLE); + Animation a1 = AnimationUtils.loadAnimation(this, R.anim.slide_in_left); + p1.startAnimation(a1); + + Animation a2 = AnimationUtils.loadAnimation(this,R.anim.slide_out_right); + a2.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + + } + + @Override + public void onAnimationEnd(Animation animation) { + p2.setVisibility(View.INVISIBLE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + p2.startAnimation(a2); + ((Button)findViewById(R.id.btn_nxt)).setText(R.string.next); + ((Button)findViewById(R.id.btn_back)).setText(R.string.cancel); + break; + } + } + + public void nxt(View view) { + switch (page_no){ + case 0: + page_no=1; + Animation a1 = AnimationUtils.loadAnimation(this, R.anim.slide_out_left); + a1.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + + } + + @Override + public void onAnimationEnd(Animation animation) { + p1.setVisibility(View.INVISIBLE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + p1.startAnimation(a1); + + p2.setVisibility(View.VISIBLE); + Animation a2 = AnimationUtils.loadAnimation(this,R.anim.slide_in_right); + p2.startAnimation(a2); + btn_nxt.setText(R.string.finish); + btn_back.setText(R.string.back); + break; + case 1: + StringBuilder backsims = new StringBuilder(); + for(int i=0; i < boxes.length; i++){ + if(boxes[i].isChecked()){ + if(!backsims.toString().isEmpty()) + backsims.append('#'); + backsims.append(sims.get(i).getSubscriptionId()); + } + } + dbViewmodel dbv = new dbViewmodel(this); + Rule rule = new Rule(); + rule.name = ((TextView)findViewById(R.id.txt_blk_name)).getText().toString(); + rule.sims = backsims.toString(); + rule.chat_id = chat_id; + dbv.add_rule(rule); + SendMessage request = new SendMessage(chat_id, "Congratulations!\nYour Telegram account is now verified as a SMS receiver account of your target device. From now on, all the incoming SMSs will be forwarded here to you. ;)"); + bot.execute(request); + finish(); + break; + } + } + static String randCode(int length, int section){ + StringBuilder buffer = new StringBuilder((length*section)+section-1); + for(int i = 1; i<=section; i++){ + for(int j=0;j() { + @Override + public void onResponse(GetUpdates request, GetUpdatesResponse response) { + List updates = response.updates(); + boolean verified = false; + for (Update update : updates){ + if(update.message().text().equals(code)){ + verified = true; + runOnUiThread(new Runnable() { + @Override + public void run() { + updateChatID(update.message().chat().id()); + Toast.makeText(AddDevice.this, "Verified", Toast.LENGTH_LONG).show(); + } + }); + } + } + if(!verified){ + runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(AddDevice.this, "Could not verify", Toast.LENGTH_SHORT).show(); + } + }); + } + } + + @Override + public void onFailure(GetUpdates request, IOException e) { + runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(AddDevice.this, "Could not verify", Toast.LENGTH_SHORT).show(); + } + }); + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appetize/remotesms/DeviceAdapter.java b/app/src/main/java/com/appetize/remotesms/DeviceAdapter.java new file mode 100644 index 0000000..5b825c9 --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/DeviceAdapter.java @@ -0,0 +1,36 @@ +package com.appetize.remotesms; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; + +public class DeviceAdapter extends ArrayAdapter { + List devices; + Context context; + int resource; + public DeviceAdapter(@NonNull Context context, int resource, @NonNull List objects) { + super(context, resource, objects); + this.context = context; + this.resource = resource; + this.devices = objects; + } + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + LayoutInflater inflater = LayoutInflater.from(context); + View view = inflater.inflate(R.layout.block,null); + Rule q = devices.get(position); + ((TextView)view.findViewById(R.id.blk_name)).setText(q.name); + ((TextView)view.findViewById(R.id.blk_sims)).setText(String.valueOf(q.sims)); + return view; + } +} diff --git a/app/src/main/java/com/appetize/remotesms/Home.java b/app/src/main/java/com/appetize/remotesms/Home.java new file mode 100644 index 0000000..c9542d1 --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/Home.java @@ -0,0 +1,51 @@ +package com.appetize.remotesms; + +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.ListView; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.Observer; + +import com.appetize.remotesms.fgService; + +import java.util.ArrayList; +import java.util.List; + +public class Home extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_home); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + + dbViewmodel dbv = new dbViewmodel(this); + dbv.get_rules().observe(this, new Observer>() { + @Override + public void onChanged(List rules) { + DeviceAdapter deviceAdapter = new DeviceAdapter(Home.this,R.layout.block, rules); + ((ListView) findViewById(R.id.devices)).setAdapter(deviceAdapter); + } + }); + if(!fgService.isServiceRunning){ + Intent intent = new Intent(this,fgService.class); + startForegroundService(intent); + } + } + + public void add_device(View view) { + Intent intent = new Intent(this, AddDevice.class); + startActivity(intent); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appetize/remotesms/MainActivity.java b/app/src/main/java/com/appetize/remotesms/MainActivity.java new file mode 100644 index 0000000..5ea70ac --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/MainActivity.java @@ -0,0 +1,77 @@ +package com.appetize.remotesms; + +import android.Manifest; +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +public class MainActivity extends AppCompatActivity { + + private final int MY_PERMISSION = 5; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + + Button grant = (Button) findViewById(R.id.perm_grant); + + if (!(ContextCompat.checkSelfPermission( + this, Manifest.permission.READ_PHONE_STATE) == + PackageManager.PERMISSION_GRANTED)){ + ((TextView)findViewById(R.id.perm_name)).setText(R.string.read_phone_state); + ((TextView)findViewById(R.id.perm_des)).setText(R.string.read_phone_state_des); + grant.setEnabled(true); + grant.setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick(View v) { + ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.READ_PHONE_STATE},MY_PERMISSION); + } + }); + } else if (!(ContextCompat.checkSelfPermission( + this, Manifest.permission.RECEIVE_SMS) == + PackageManager.PERMISSION_GRANTED)){ + ((TextView)findViewById(R.id.perm_name)).setText(R.string.receive_sms); + ((TextView)findViewById(R.id.perm_des)).setText(R.string.receive_sms_des); + grant.setEnabled(true); + grant.setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick(View v) { + ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.RECEIVE_SMS},MY_PERMISSION); + } + }); + } + else{ + Intent intent = new Intent(this, Home.class); + startActivity(intent); + finish(); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == MY_PERMISSION){ + Intent intent = new Intent(this, MainActivity.class); + startActivity(intent); + finish(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/appetize/remotesms/NetworkUtil.java b/app/src/main/java/com/appetize/remotesms/NetworkUtil.java new file mode 100644 index 0000000..96e52a5 --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/NetworkUtil.java @@ -0,0 +1,41 @@ +package com.appetize.remotesms; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +public class NetworkUtil { + public static final int TYPE_WIFI = 1; + public static final int TYPE_MOBILE = 2; + public static final int TYPE_NOT_CONNECTED = 0; + public static final int NETWORK_STATUS_NOT_CONNECTED = 0; + public static final int NETWORK_STATUS_WIFI = 1; + public static final int NETWORK_STATUS_MOBILE = 2; + + public static int getConnectivityStatus(Context context) { + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + if (null != activeNetwork) { + if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) + return TYPE_WIFI; + + if(activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) + return TYPE_MOBILE; + } + return TYPE_NOT_CONNECTED; + } + + public static int getConnectivityStatusString(Context context) { + int conn = NetworkUtil.getConnectivityStatus(context); + int status = 0; + if (conn == NetworkUtil.TYPE_WIFI) { + status = NETWORK_STATUS_WIFI; + } else if (conn == NetworkUtil.TYPE_MOBILE) { + status = NETWORK_STATUS_MOBILE; + } else if (conn == NetworkUtil.TYPE_NOT_CONNECTED) { + status = NETWORK_STATUS_NOT_CONNECTED; + } + return status; + } +} diff --git a/app/src/main/java/com/appetize/remotesms/Rule.java b/app/src/main/java/com/appetize/remotesms/Rule.java new file mode 100644 index 0000000..6c5a2cb --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/Rule.java @@ -0,0 +1,17 @@ +package com.appetize.remotesms; + +import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.PrimaryKey; + +@Entity +public class Rule { + @PrimaryKey + @NonNull + public long chat_id; + @ColumnInfo(name = "name") + public String name; + @ColumnInfo(name = "sims") + public String sims; +} diff --git a/app/src/main/java/com/appetize/remotesms/SMS.java b/app/src/main/java/com/appetize/remotesms/SMS.java new file mode 100644 index 0000000..85e4e96 --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/SMS.java @@ -0,0 +1,19 @@ +package com.appetize.remotesms; + +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.PrimaryKey; + +@Entity +public class SMS { + @PrimaryKey(autoGenerate = true) + public int id; + @ColumnInfo(name="sender") + public String sender; + @ColumnInfo(name="body") + public String body; + @ColumnInfo(name = "datetime") + public long datetime; + @ColumnInfo(name = "sim") + public int sim_no; +} diff --git a/app/src/main/java/com/appetize/remotesms/Setting.java b/app/src/main/java/com/appetize/remotesms/Setting.java new file mode 100644 index 0000000..4778e94 --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/Setting.java @@ -0,0 +1,15 @@ +package com.appetize.remotesms; + +import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.PrimaryKey; + +@Entity +public class Setting { + @PrimaryKey + @NonNull + public String name; + @ColumnInfo(name = "value") + public String value; +} diff --git a/app/src/main/java/com/appetize/remotesms/dbDao.java b/app/src/main/java/com/appetize/remotesms/dbDao.java new file mode 100644 index 0000000..e205ab4 --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/dbDao.java @@ -0,0 +1,34 @@ +package com.appetize.remotesms; + +import androidx.lifecycle.LiveData; +import androidx.room.Dao; +import androidx.room.Delete; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; + +import java.util.List; + +@Dao +public interface dbDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + void add_rule(Rule rule); + @Insert + void add_sms(SMS sms); + @Insert(onConflict = OnConflictStrategy.REPLACE) + void add_setting(Setting setting); + @Query("SELECT * FROM SMS") + List getSMSList(); + @Query("SELECT * FROM Setting") + List getSettings(); + @Query("SELECT * FROM Rule") + LiveData> getRules(); + @Query("SELECT * FROM Rule") + List getIRules(); + @Delete + void rem_rule(Rule rule); + @Delete + void rem_sms(SMS sms); + @Delete + void rem_setting(Setting setting); +} diff --git a/app/src/main/java/com/appetize/remotesms/dbMain.java b/app/src/main/java/com/appetize/remotesms/dbMain.java new file mode 100644 index 0000000..aa5aa6e --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/dbMain.java @@ -0,0 +1,28 @@ +package com.appetize.remotesms; + +import android.content.Context; + +import androidx.room.Database; +import androidx.room.Room; +import androidx.room.RoomDatabase; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@Database(entities = {Rule.class, Setting.class, SMS.class}, version = 1) +public abstract class dbMain extends RoomDatabase { + public abstract dbDao dao(); + public static volatile dbMain INSTANCE; + private static final int NUMBER_OF_THREADS = 4; + static final ExecutorService databaseWriteExecutor = Executors.newFixedThreadPool(NUMBER_OF_THREADS); + static dbMain getDB(final Context context){ + if (INSTANCE == null){ + synchronized (dbMain.class){ + if (INSTANCE == null){ + INSTANCE = Room.databaseBuilder(context.getApplicationContext(),dbMain.class,"core_database").build(); + } + } + } + return INSTANCE; + } +} diff --git a/app/src/main/java/com/appetize/remotesms/dbViewmodel.java b/app/src/main/java/com/appetize/remotesms/dbViewmodel.java new file mode 100644 index 0000000..c7ff387 --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/dbViewmodel.java @@ -0,0 +1,57 @@ +package com.appetize.remotesms; + +import android.content.Context; +import android.os.AsyncTask; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; + +import java.util.List; + +public class dbViewmodel { + private dbDao dao; + private dbMain db; + public dbViewmodel(@NonNull Context context){ + db = dbMain.getDB(context); + dao = db.dao(); + } + public void add_rule(Rule rule){ + new Thread(new Runnable() { + @Override + public void run() { + dao.add_rule(rule); + } + }).start(); + } + public void add_sms(SMS sms){ + new Thread(new Runnable() { + @Override + public void run() { + dao.add_sms(sms); + } + }).start(); + } + public void add_setting(Setting setting){ + new Thread(new Runnable() { + @Override + public void run() { + dao.add_setting(setting); + } + }).start(); + } + public LiveData> get_rules(){ + return dao.getRules(); + } + public List get_i_rules(){ + return dao.getIRules(); + } + public List get_smsList(){ + return dao.getSMSList(); + } + public List get_settings(){ + return dao.getSettings(); + } + public void rem_SMS(SMS sms){ + dao.rem_sms(sms); + } +} diff --git a/app/src/main/java/com/appetize/remotesms/fgService.java b/app/src/main/java/com/appetize/remotesms/fgService.java new file mode 100644 index 0000000..c7aab25 --- /dev/null +++ b/app/src/main/java/com/appetize/remotesms/fgService.java @@ -0,0 +1,205 @@ +package com.appetize.remotesms; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Build; +import android.os.Bundle; +import android.os.IBinder; +import android.telephony.SmsMessage; +import android.util.Log; + +import androidx.core.app.NotificationCompat; + +import com.pengrad.telegrambot.TelegramBot; +import com.pengrad.telegrambot.model.Message; +import com.pengrad.telegrambot.model.request.ForceReply; +import com.pengrad.telegrambot.model.request.ParseMode; +import com.pengrad.telegrambot.request.SendMessage; +import com.pengrad.telegrambot.response.SendResponse; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +public class fgService extends Service { + private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED"; + private static final String CONNECTIVITY_CHANGE = "android.net.conn.CONNECTIVITY_CHANGE"; + public static boolean isServiceRunning; + private String CHANNEL_ID = "FG_SERVICE_CHANNEL"; + + public fgService() { + isServiceRunning = false; + } + + @Override + public void onCreate() { + super.onCreate(); + createNotificationChannel(); + isServiceRunning = true; + IntentFilter filter = new IntentFilter(); + filter.addAction(SMS_RECEIVED); + filter.addAction(CONNECTIVITY_CHANGE); + registerReceiver(receiver, filter); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Intent notificationIntent = new Intent(this, Home.class); + PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); + Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) + .setContentTitle("Remote SMS service is running") + .setContentText("Monitoring for new SMS") + .setSmallIcon(R.drawable.common_google_signin_btn_icon_dark) + .setContentIntent(pendingIntent) + .setColor(getResources().getColor(R.color.design_default_color_primary)) + .build(); + + startForeground(1, notification); + return START_STICKY; + } + + private void createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + String appName = getString(R.string.app_name); + NotificationChannel serviceChannel = new NotificationChannel(CHANNEL_ID, appName, NotificationManager.IMPORTANCE_DEFAULT); + NotificationManager manager = getSystemService(NotificationManager.class); + manager.createNotificationChannel(serviceChannel); + } + } + + @Override + public void onDestroy() { + isServiceRunning = false; + stopForeground(true); + //Intent broadcastIntent = new Intent(this, SMSReciever.class); + //sendBroadcast(broadcastIntent); + unregisterReceiver(receiver); + super.onDestroy(); + } + + private final BroadcastReceiver receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + dbViewmodel dbv = new dbViewmodel(context); + new Thread(new Runnable() { + @Override + public void run() { + TelegramBot bot = new TelegramBot(getString(R.string.bot_token)); + List rules = dbv.get_i_rules(); + if(intent.getAction().equals(SMS_RECEIVED)) { + Log.d("Foreground", "onReceive: Recieve korsi"); + Bundle bundle = intent.getExtras(); + if(bundle != null){ + Object[] pdus = (Object[]) bundle.get("pdus"); + SmsMessage[] messages = new SmsMessage[pdus.length]; + for(int i=0; i smsList = dbv.get_smsList(); + for (SMS sms : smsList){ + for(Rule rule:rules){ + String[] sims = rule.sims.split("#"); + for(String rsim:sims){ + if(rsim.equals(String.valueOf(sms.sim_no))){ + try { + SendMessage request = new SendMessage(rule.chat_id, "From:\n" + sms.sender + "\n\nBody:\n" + sms.body + "\n\nDatetime:\n" + new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z").format(new Date(sms.datetime))); + SendResponse sendResponse = bot.execute(request); + if (sendResponse.isOk()) { + dbv.rem_SMS(sms); + } + } + catch (Exception e){ + Log.e("Foreground Error", e.getMessage() ); + } + } + } + } + } + } + } + }).start(); + } + int capturedSIM(Bundle bundle){ + String TAG = "SIM ID"; + int simid = -1; + if(bundle.containsKey("subscription")){ + simid = bundle.getInt("subscription"); + Log.d(TAG, "capturedSIM: " + simid + " #subscription"); + } + if(simid >= 0 && simid < 5){ + return simid; + } + else{ + if(bundle.containsKey("simId")){ + simid = bundle.getInt("simId"); + Log.d(TAG, "capturedSIM: " + simid + " #simid"); + } + else if(bundle.containsKey("com.android.phone.extra.slot")){ + simid = bundle.getInt("com.android.phone.extra.slot"); + Log.d(TAG, "capturedSIM: " + simid + " #com.android.phone.extra.slot"); + } + else if(bundle.containsKey("slot")){ + simid = bundle.getInt("slot"); + Log.d(TAG, "capturedSIM: " + simid + " #slolt"); + } + else{ + String keyName = ""; + for(String key: bundle.keySet()){ + if(key.contains("sim")) + keyName = key; + } + simid = bundle.getInt(keyName); + Log.d(TAG, "capturedSIM: " + simid + " #" + keyName); + } + return simid; + } + } + }; +} \ No newline at end of file diff --git a/app/src/main/res/anim/blink_anim.xml b/app/src/main/res/anim/blink_anim.xml new file mode 100644 index 0000000..5cdc674 --- /dev/null +++ b/app/src/main/res/anim/blink_anim.xml @@ -0,0 +1,8 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/anim/bounce.xml b/app/src/main/res/anim/bounce.xml new file mode 100644 index 0000000..17da7cf --- /dev/null +++ b/app/src/main/res/anim/bounce.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/btn_bounce.xml b/app/src/main/res/anim/btn_bounce.xml new file mode 100644 index 0000000..bdc888b --- /dev/null +++ b/app/src/main/res/anim/btn_bounce.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/fadein.xml b/app/src/main/res/anim/fadein.xml new file mode 100644 index 0000000..9d7ee72 --- /dev/null +++ b/app/src/main/res/anim/fadein.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/fadeout.xml b/app/src/main/res/anim/fadeout.xml new file mode 100644 index 0000000..7a8095c --- /dev/null +++ b/app/src/main/res/anim/fadeout.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/lefttoright.xml b/app/src/main/res/anim/lefttoright.xml new file mode 100644 index 0000000..8329877 --- /dev/null +++ b/app/src/main/res/anim/lefttoright.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/anim/mixed_anim.xml b/app/src/main/res/anim/mixed_anim.xml new file mode 100644 index 0000000..930ffac --- /dev/null +++ b/app/src/main/res/anim/mixed_anim.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/righttoleft.xml b/app/src/main/res/anim/righttoleft.xml new file mode 100644 index 0000000..efdc676 --- /dev/null +++ b/app/src/main/res/anim/righttoleft.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/anim/rotate.xml b/app/src/main/res/anim/rotate.xml new file mode 100644 index 0000000..5e0c46d --- /dev/null +++ b/app/src/main/res/anim/rotate.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/sample_anim.xml b/app/src/main/res/anim/sample_anim.xml new file mode 100644 index 0000000..972b3a1 --- /dev/null +++ b/app/src/main/res/anim/sample_anim.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_left.xml b/app/src/main/res/anim/slide_in_left.xml new file mode 100644 index 0000000..92b69f3 --- /dev/null +++ b/app/src/main/res/anim/slide_in_left.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml new file mode 100644 index 0000000..91ecf0b --- /dev/null +++ b/app/src/main/res/anim/slide_in_right.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_left.xml b/app/src/main/res/anim/slide_out_left.xml new file mode 100644 index 0000000..79f5c25 --- /dev/null +++ b/app/src/main/res/anim/slide_out_left.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_right.xml b/app/src/main/res/anim/slide_out_right.xml new file mode 100644 index 0000000..36ab81f --- /dev/null +++ b/app/src/main/res/anim/slide_out_right.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/zoomin.xml b/app/src/main/res/anim/zoomin.xml new file mode 100644 index 0000000..9caa250 --- /dev/null +++ b/app/src/main/res/anim/zoomin.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/zoomout.xml b/app/src/main/res/anim/zoomout.xml new file mode 100644 index 0000000..52dbe8c --- /dev/null +++ b/app/src/main/res/anim/zoomout.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/avatar.png b/app/src/main/res/drawable/avatar.png new file mode 100644 index 0000000..cc8e607 Binary files /dev/null and b/app/src/main/res/drawable/avatar.png differ diff --git a/app/src/main/res/drawable/ic_baseline_add_24.xml b/app/src/main/res/drawable/ic_baseline_add_24.xml new file mode 100644 index 0000000..eb23254 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_add_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_check_24.xml b/app/src/main/res/drawable/ic_baseline_check_24.xml new file mode 100644 index 0000000..0432fa6 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_check_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_add_device.xml b/app/src/main/res/layout/activity_add_device.xml new file mode 100644 index 0000000..e8011b3 --- /dev/null +++ b/app/src/main/res/layout/activity_add_device.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + +