From e5a1a87344c21aa6664665e530f43acf8acc95c9 Mon Sep 17 00:00:00 2001 From: Rifat Hossain Date: Sat, 8 Jun 2024 18:22:31 +0600 Subject: [PATCH] v0.1 completion --- .gitignore | 15 ++ .idea/.gitignore | 3 + .idea/.name | 1 + .idea/compiler.xml | 6 + .idea/deploymentTargetDropDown.xml | 10 + .idea/gradle.xml | 19 ++ .idea/jarRepositories.xml | 25 ++ .idea/migrations.xml | 10 + .idea/misc.xml | 20 ++ .idea/vcs.xml | 6 + app/.gitignore | 1 + app/build.gradle | 57 ++++ app/google-services.json | 39 +++ app/proguard-rules.pro | 21 ++ .../remotesms/ExampleInstrumentedTest.java | 26 ++ app/src/main/AndroidManifest.xml | 35 +++ app/src/main/AndroidManifest.xml.orig | 62 +++++ .../com/appetize/remotesms/AddDevice.java | 247 ++++++++++++++++++ .../com/appetize/remotesms/DeviceAdapter.java | 36 +++ .../java/com/appetize/remotesms/Home.java | 51 ++++ .../com/appetize/remotesms/MainActivity.java | 77 ++++++ .../com/appetize/remotesms/NetworkUtil.java | 41 +++ .../java/com/appetize/remotesms/Rule.java | 17 ++ .../main/java/com/appetize/remotesms/SMS.java | 19 ++ .../java/com/appetize/remotesms/Setting.java | 15 ++ .../java/com/appetize/remotesms/dbDao.java | 34 +++ .../java/com/appetize/remotesms/dbMain.java | 28 ++ .../com/appetize/remotesms/dbViewmodel.java | 57 ++++ .../com/appetize/remotesms/fgService.java | 205 +++++++++++++++ app/src/main/res/anim/blink_anim.xml | 8 + app/src/main/res/anim/bounce.xml | 12 + app/src/main/res/anim/btn_bounce.xml | 16 ++ app/src/main/res/anim/fadein.xml | 10 + app/src/main/res/anim/fadeout.xml | 10 + app/src/main/res/anim/lefttoright.xml | 6 + app/src/main/res/anim/mixed_anim.xml | 28 ++ app/src/main/res/anim/righttoleft.xml | 7 + app/src/main/res/anim/rotate.xml | 11 + app/src/main/res/anim/sample_anim.xml | 9 + app/src/main/res/anim/slide_in_left.xml | 8 + app/src/main/res/anim/slide_in_right.xml | 7 + app/src/main/res/anim/slide_out_left.xml | 8 + app/src/main/res/anim/slide_out_right.xml | 8 + app/src/main/res/anim/zoomin.xml | 16 ++ app/src/main/res/anim/zoomout.xml | 15 ++ .../drawable-v24/ic_launcher_foreground.xml | 30 +++ app/src/main/res/drawable/avatar.png | Bin 0 -> 22606 bytes .../main/res/drawable/ic_baseline_add_24.xml | 10 + .../res/drawable/ic_baseline_check_24.xml | 10 + .../res/drawable/ic_launcher_background.xml | 170 ++++++++++++ .../main/res/layout/activity_add_device.xml | 141 ++++++++++ app/src/main/res/layout/activity_home.xml | 30 +++ app/src/main/res/layout/activity_main.xml | 48 ++++ app/src/main/res/layout/block.xml | 31 +++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3593 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5339 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2636 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3388 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4926 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7472 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7909 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 11873 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10652 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 16570 bytes app/src/main/res/values-night/themes.xml | 16 ++ app/src/main/res/values/colors.xml | 10 + app/src/main/res/values/strings.xml | 15 ++ app/src/main/res/values/themes.xml | 16 ++ .../appetize/remotesms/ExampleUnitTest.java | 17 ++ build.gradle | 24 ++ gradle.properties | 19 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 ++++++++++++ gradlew.bat | 84 ++++++ settings.gradle | 2 + 78 files changed, 2223 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/.name create mode 100644 .idea/compiler.xml create mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/migrations.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/google-services.json create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/appetize/remotesms/ExampleInstrumentedTest.java create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/AndroidManifest.xml.orig create mode 100644 app/src/main/java/com/appetize/remotesms/AddDevice.java create mode 100644 app/src/main/java/com/appetize/remotesms/DeviceAdapter.java create mode 100644 app/src/main/java/com/appetize/remotesms/Home.java create mode 100644 app/src/main/java/com/appetize/remotesms/MainActivity.java create mode 100644 app/src/main/java/com/appetize/remotesms/NetworkUtil.java create mode 100644 app/src/main/java/com/appetize/remotesms/Rule.java create mode 100644 app/src/main/java/com/appetize/remotesms/SMS.java create mode 100644 app/src/main/java/com/appetize/remotesms/Setting.java create mode 100644 app/src/main/java/com/appetize/remotesms/dbDao.java create mode 100644 app/src/main/java/com/appetize/remotesms/dbMain.java create mode 100644 app/src/main/java/com/appetize/remotesms/dbViewmodel.java create mode 100644 app/src/main/java/com/appetize/remotesms/fgService.java create mode 100644 app/src/main/res/anim/blink_anim.xml create mode 100644 app/src/main/res/anim/bounce.xml create mode 100644 app/src/main/res/anim/btn_bounce.xml create mode 100644 app/src/main/res/anim/fadein.xml create mode 100644 app/src/main/res/anim/fadeout.xml create mode 100644 app/src/main/res/anim/lefttoright.xml create mode 100644 app/src/main/res/anim/mixed_anim.xml create mode 100644 app/src/main/res/anim/righttoleft.xml create mode 100644 app/src/main/res/anim/rotate.xml create mode 100644 app/src/main/res/anim/sample_anim.xml create mode 100644 app/src/main/res/anim/slide_in_left.xml create mode 100644 app/src/main/res/anim/slide_in_right.xml create mode 100644 app/src/main/res/anim/slide_out_left.xml create mode 100644 app/src/main/res/anim/slide_out_right.xml create mode 100644 app/src/main/res/anim/zoomin.xml create mode 100644 app/src/main/res/anim/zoomout.xml create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/avatar.png create mode 100644 app/src/main/res/drawable/ic_baseline_add_24.xml create mode 100644 app/src/main/res/drawable/ic_baseline_check_24.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/layout/activity_add_device.xml create mode 100644 app/src/main/res/layout/activity_home.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/block.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values-night/themes.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 app/src/test/java/com/appetize/remotesms/ExampleUnitTest.java create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle 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 0000000000000000000000000000000000000000..cc8e60790170a5f1b13bd9cce05066699f802715 GIT binary patch literal 22606 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 NbTth%%5UBe{SSRgWgh?l literal 0 HcmV?d00001 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 @@ + + + + + + + + + + + + + + + +