version:2.2.1
bugfixes:优化自动拨号和权限问题 update:
This commit is contained in:
@@ -18,8 +18,8 @@ android {
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 29
|
||||
|
||||
versionCode 220
|
||||
versionName "2.2.0"
|
||||
versionCode 221
|
||||
versionName "2.2.1"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
@@ -31,9 +30,17 @@ import com.vscool.os.utils.ForegroundAppUtil;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.rxjava3.annotations.NonNull;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.core.ObservableEmitter;
|
||||
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
|
||||
import io.reactivex.rxjava3.functions.Consumer;
|
||||
|
||||
/**
|
||||
* 通过微信标签最高支持8.0.49,8.0.50 获取不到数据
|
||||
* 8.0.54 可以获取
|
||||
* 通过 {@link AccessibilityService#getWindows}和修改accessibility-service 配置能遍历屏幕元素
|
||||
*/
|
||||
public class SelectToSpeakService extends AccessibilityService {
|
||||
@@ -63,7 +70,7 @@ public class SelectToSpeakService extends AccessibilityService {
|
||||
public static final int TYPE_VOICE = 0;
|
||||
public static final int TYPE_VIDEO = 1;
|
||||
|
||||
private static final int WAIT_TIME = 1200;
|
||||
private static final int WAIT_TIME = 1300;
|
||||
|
||||
private int mCallType = TYPE_VOICE;
|
||||
|
||||
@@ -72,17 +79,12 @@ public class SelectToSpeakService extends AccessibilityService {
|
||||
private String mName = "";//微信昵称
|
||||
private String mTagName = "";//微信联系人标签名
|
||||
private boolean mAutoAccept = false;
|
||||
private boolean finished = true;
|
||||
|
||||
private Handler handler = null;
|
||||
private AccessibilityEvent input = null;
|
||||
private Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
_onAccessibilityEvent(input);
|
||||
finished = true;
|
||||
}
|
||||
};
|
||||
public interface AccessibilityEventCallback {
|
||||
void onAccessibilityEventCallback(AccessibilityEvent accessibilityEvent);
|
||||
}
|
||||
|
||||
private AccessibilityEventCallback mAccessibilityEventCallback;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
@@ -90,10 +92,27 @@ public class SelectToSpeakService extends AccessibilityService {
|
||||
Log.e(TAG, "onCreate: ");
|
||||
registerSettingReceiver();
|
||||
mAutoAccept = mMMKV.decodeBool(CommonConfig.WECHAT_CALL_AUTO_ACCEPT, false);
|
||||
handler = new Handler();
|
||||
analysisAccessibilityEvent();
|
||||
}
|
||||
|
||||
private void analysisAccessibilityEvent() {
|
||||
Observable.create(new ObservableOnSubscribe<AccessibilityEvent>() {
|
||||
@Override
|
||||
public void subscribe(@NonNull ObservableEmitter<AccessibilityEvent> emitter) throws Throwable {
|
||||
mAccessibilityEventCallback = emitter::onNext;
|
||||
}
|
||||
}).throttleLast(WAIT_TIME, TimeUnit.MILLISECONDS)
|
||||
.subscribe(new Consumer<AccessibilityEvent>() {
|
||||
@Override
|
||||
public void accept(AccessibilityEvent accessibilityEvent) throws Throwable {
|
||||
Log.e(TAG, "analysisAccessibilityEvent accept: ");
|
||||
_onAccessibilityEvent(accessibilityEvent);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Log.e(TAG, "onStartCommand: ");
|
||||
@@ -127,14 +146,7 @@ public class SelectToSpeakService extends AccessibilityService {
|
||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
||||
Log.v(TAG, "onAccessibilityEvent: event = " + event.toString());
|
||||
checkClassName(event);
|
||||
if (finished) {
|
||||
finished = false;
|
||||
} else {
|
||||
Log.v(TAG, "bounce");
|
||||
handler.removeCallbacks(runnable);
|
||||
}
|
||||
input = event;
|
||||
handler.postDelayed(runnable, WAIT_TIME);
|
||||
mAccessibilityEventCallback.onAccessibilityEventCallback(event);
|
||||
}
|
||||
|
||||
private void checkClassName(AccessibilityEvent event) {
|
||||
@@ -421,8 +433,7 @@ public class SelectToSpeakService extends AccessibilityService {
|
||||
clickNode(nodeInfo);
|
||||
mCurrentStep = nextStep;
|
||||
} else {
|
||||
Toaster.show("没有找到控件");
|
||||
mCurrentStep = Step.WAITING;
|
||||
Toaster.show("没有找到搜索按钮");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,12 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
|
||||
@Override
|
||||
public void onToggle(boolean on) {
|
||||
if (on) {
|
||||
showFloatingWindow();
|
||||
boolean permission = checkFloatPermission(SettingActivity.this);
|
||||
if (permission) {
|
||||
showFloatingWindow();
|
||||
} else {
|
||||
showFloatWindowDialog();
|
||||
}
|
||||
} else {
|
||||
hideFloatingWindow();
|
||||
}
|
||||
@@ -221,28 +226,40 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
Log.e(TAG, "onResume: ");
|
||||
setStatus();
|
||||
mViewModel.getSystemSettings();
|
||||
}
|
||||
|
||||
private void setStatus() {
|
||||
boolean showFloatWindow = Settings.Global.getInt(getContentResolver(), CommonConfig.HOVER_HOME, CommonConfig.HOVER_HOME_STATUS) == 1;
|
||||
Log.e(TAG, "initView: showFloatWindow = " + showFloatWindow);
|
||||
Log.e(TAG, "setStatus: showFloatWindow = " + showFloatWindow);
|
||||
mViewDataBinding.tbFloat.setToggleStatu(showFloatWindow);
|
||||
if (showFloatWindow) {
|
||||
boolean permission = checkFloatPermission(SettingActivity.this);
|
||||
if (permission) {
|
||||
showFloatingWindow();
|
||||
} else {
|
||||
showFloatWindowDialog();
|
||||
}
|
||||
} else {
|
||||
hideFloatingWindow();
|
||||
}
|
||||
|
||||
boolean voiceBroadcast = mMMKV.decodeBool(CommonConfig.VOICE_BROADCAST, false);
|
||||
Log.e(TAG, "initView: voiceBroadcast = " + voiceBroadcast);
|
||||
Log.e(TAG, "setStatus: voiceBroadcast = " + voiceBroadcast);
|
||||
mViewDataBinding.tbSms.setToggleStatu(voiceBroadcast);
|
||||
|
||||
boolean autoAccept = mMMKV.decodeBool(CommonConfig.WECHAT_CALL_AUTO_ACCEPT, false);
|
||||
Log.e(TAG, "initView: autoAccept = " + autoAccept);
|
||||
Log.e(TAG, "setStatus: autoAccept = " + autoAccept);
|
||||
mViewDataBinding.tbAutoAnswer.setToggleStatu(autoAccept);
|
||||
if (autoAccept) {
|
||||
boolean floatWindowEnable = Settings.Global.getInt(getContentResolver(), CommonConfig.HOVER_HOME, CommonConfig.HOVER_HOME_STATUS) == 1;
|
||||
boolean permission = FloatingWindowUtils.checkFloatPermission(SettingActivity.this);
|
||||
if (floatWindowEnable && permission) {
|
||||
boolean accessibility = AccessibilityUtils.isAccessibilitySettingsOn(SettingActivity.this);
|
||||
if (floatWindowEnable && permission && !accessibility) {
|
||||
Toast.makeText(SettingActivity.this, "由于系统限制,请先关闭悬浮窗功能,开启自动接听后再打开悬浮窗", Toast.LENGTH_LONG).show();
|
||||
showFloatWindowDialog();
|
||||
showFloatHideDialog();
|
||||
} else {
|
||||
if (AccessibilityUtils.isAccessibilitySettingsOn(SettingActivity.this)) {
|
||||
mMMKV.encode(CommonConfig.WECHAT_CALL_AUTO_ACCEPT, 1);
|
||||
@@ -256,32 +273,32 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
|
||||
}
|
||||
|
||||
boolean wxAutoVideo = mMMKV.decodeInt(CommonConfig.WECHAT_AUTO_CALL_KEY, 0) == 1;
|
||||
Log.e(TAG, "initView: wxAutoVideo = " + autoAccept);
|
||||
Log.e(TAG, "setStatus: wxAutoVideo = " + autoAccept);
|
||||
mViewDataBinding.tbAutoCall.setToggleStatu(wxAutoVideo);
|
||||
|
||||
boolean dialTone = mMMKV.decodeBool(CommonConfig.DISABLE_DIAL_TONE_MODIFY, true);
|
||||
Log.e(TAG, "initView: dialTone = " + dialTone);
|
||||
Log.e(TAG, "setStatus: dialTone = " + dialTone);
|
||||
mViewDataBinding.tbDialer.setToggleStatu(dialTone);
|
||||
|
||||
int code = Settings.System.getInt(getContentResolver(), CommonConfig.ACTION_STATUS_BAR_STATE, 0);
|
||||
boolean statusBar = code == 1;
|
||||
Log.e(TAG, "initView: statusBar = " + statusBar);
|
||||
Log.e(TAG, "setStatus: statusBar = " + statusBar);
|
||||
mViewDataBinding.tbStatu.setToggleStatu(statusBar);
|
||||
|
||||
boolean hourlyTime = mMMKV.decodeBool(CommonConfig.HOURLY_TIME_SIGNAL_KEY, false);
|
||||
Log.e(TAG, "initView: hourlyTime = " + hourlyTime);
|
||||
Log.e(TAG, "setStatus: hourlyTime = " + hourlyTime);
|
||||
mViewDataBinding.tbHourly.setToggleStatu(hourlyTime);
|
||||
|
||||
boolean disableKey = mMMKV.decodeBool(CommonConfig.DISABLE_VOLUME_KEY, false);
|
||||
Log.e(TAG, "initView: disableKey = " + disableKey);
|
||||
Log.e(TAG, "setStatus: disableKey = " + disableKey);
|
||||
mViewDataBinding.tbVolume.setToggleStatu(!disableKey);
|
||||
|
||||
boolean contactModify = mMMKV.decodeBool(CommonConfig.DISABLE_CONTACT_MODIFY, false);
|
||||
Log.e(TAG, "initView: contactModify = " + contactModify);
|
||||
Log.e(TAG, "setStatus: contactModify = " + contactModify);
|
||||
mViewDataBinding.tbContact.setToggleStatu(!contactModify);
|
||||
|
||||
int clockModify = mMMKV.decodeInt(CommonConfig.ALARM_CLOCK_CTRL, 1);
|
||||
Log.e(TAG, "initView: clockModify = " + clockModify);
|
||||
Log.e(TAG, "setStatus: clockModify = " + clockModify);
|
||||
mViewDataBinding.tbClock.setToggleStatu(clockModify == 1);
|
||||
}
|
||||
|
||||
@@ -390,9 +407,10 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
|
||||
public void onPositive() {
|
||||
boolean floatWindowEnable = Settings.Global.getInt(getContentResolver(), CommonConfig.HOVER_HOME, CommonConfig.HOVER_HOME_STATUS) == 1;
|
||||
boolean permission = FloatingWindowUtils.checkFloatPermission(SettingActivity.this);
|
||||
if (floatWindowEnable && permission) {
|
||||
boolean accessibility = AccessibilityUtils.isAccessibilitySettingsOn(SettingActivity.this);
|
||||
if (floatWindowEnable && permission && !accessibility) {
|
||||
Toast.makeText(SettingActivity.this, "由于系统限制,请先关闭悬浮窗功能,开启自动接听后再打开悬浮窗", Toast.LENGTH_LONG).show();
|
||||
showFloatWindowDialog();
|
||||
showFloatHideDialog();
|
||||
} else {
|
||||
showAutoAcceptDialog();
|
||||
}
|
||||
@@ -433,7 +451,6 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
|
||||
// }
|
||||
}
|
||||
|
||||
private PermissionsDialog mFloatWindowDialog;
|
||||
|
||||
private void setWechatAutoCall(boolean on) {
|
||||
if (on) {
|
||||
@@ -462,6 +479,37 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
|
||||
}
|
||||
}
|
||||
|
||||
private PermissionsDialog mFloatWindowHideDialog;
|
||||
|
||||
private void showFloatHideDialog() {
|
||||
if (mFloatWindowHideDialog != null) {
|
||||
mFloatWindowHideDialog.dismiss();
|
||||
mFloatWindowHideDialog = null;
|
||||
}
|
||||
mFloatWindowHideDialog = new PermissionsDialog(SettingActivity.this);
|
||||
mFloatWindowHideDialog.setTitle("功能说明");
|
||||
mFloatWindowHideDialog.setContent("由于系统限制,请先关闭悬浮窗功能,开启自动接听后再打开悬浮窗");
|
||||
mFloatWindowHideDialog.setDeniedtext("取消");
|
||||
mFloatWindowHideDialog.setGrantedtext("确定");
|
||||
mFloatWindowHideDialog.setPermissionsCallback(new PermissionsDialog.PermissionsCallback() {
|
||||
@Override
|
||||
public void onGranted() {
|
||||
mFloatWindowHideDialog.dismiss();
|
||||
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDenied() {
|
||||
mFloatWindowHideDialog.dismiss();
|
||||
mViewDataBinding.tbAutoAnswer.setToggleStatu(false);
|
||||
}
|
||||
});
|
||||
mFloatWindowHideDialog.show();
|
||||
}
|
||||
|
||||
private PermissionsDialog mFloatWindowDialog;
|
||||
|
||||
private void showFloatWindowDialog() {
|
||||
if (mFloatWindowDialog != null) {
|
||||
mFloatWindowDialog.dismiss();
|
||||
@@ -469,21 +517,29 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
|
||||
}
|
||||
mFloatWindowDialog = new PermissionsDialog(SettingActivity.this);
|
||||
mFloatWindowDialog.setTitle("功能说明");
|
||||
mFloatWindowDialog.setContent("由于系统限制,请先关闭悬浮窗功能,开启自动接听后再打开悬浮窗");
|
||||
mFloatWindowDialog.setContent("您已开启悬浮窗功能,程序需要授予悬浮窗权限才能使用此功能,是否同意授权");
|
||||
mFloatWindowDialog.setDeniedtext("取消");
|
||||
mFloatWindowDialog.setGrantedtext("确定");
|
||||
mFloatWindowDialog.setPermissionsCallback(new PermissionsDialog.PermissionsCallback() {
|
||||
@Override
|
||||
public void onGranted() {
|
||||
mFloatWindowDialog.dismiss();
|
||||
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
|
||||
startActivity(intent);
|
||||
// 在Activity或Fragment中请求权限
|
||||
if (!Settings.canDrawOverlays(SettingActivity.this)) {
|
||||
Toast.makeText(SettingActivity.this, "请先打开悬浮窗权限", Toast.LENGTH_LONG).show();
|
||||
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
||||
Uri.parse("package:" + getPackageName()));
|
||||
startActivityForResult(intent, REQUEST_CODE_DRAW_OVER_OTHER_APPS_PERMISSION);
|
||||
} else {
|
||||
showFloatingWindow();
|
||||
mFloatWindowDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDenied() {
|
||||
mFloatWindowDialog.dismiss();
|
||||
mViewDataBinding.tbAutoAnswer.setToggleStatu(false);
|
||||
mViewDataBinding.tbFloat.setToggleStatu(false);
|
||||
Settings.Global.putInt(getContentResolver(), CommonConfig.HOVER_HOME, 0);
|
||||
}
|
||||
});
|
||||
mFloatWindowDialog.show();
|
||||
@@ -510,10 +566,11 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
|
||||
public void onGranted() {
|
||||
mAutoAcceptDialog.dismiss();
|
||||
if (AccessibilityUtils.isAccessibilitySettingsOn(SettingActivity.this)) {
|
||||
mMMKV.encode(CommonConfig.WECHAT_CALL_AUTO_ACCEPT, 1);
|
||||
Intent intent = new Intent(SelectToSpeakService.SETTING_AUTOMATIC_ANSWER_ACTION);
|
||||
intent.putExtra("auto_answer", true);
|
||||
sendBroadcast(intent);
|
||||
mMMKV.encode(CommonConfig.WECHAT_CALL_AUTO_ACCEPT, 1);
|
||||
mViewDataBinding.tbAutoAnswer.setToggleStatu(true);
|
||||
} else {
|
||||
AccessibilityUtils.openAccessibilitySettings(SettingActivity.this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user