version:2.2.0

bugfixes:微信通话不需要标签
update:增加合规弹窗
This commit is contained in:
2025-06-26 18:18:12 +08:00
parent 784ca8a8f8
commit 219f0bd351
25 changed files with 861 additions and 51 deletions

View File

@@ -18,8 +18,8 @@ android {
minSdkVersion 24
targetSdkVersion 29
versionCode 219
versionName "2.1.9"
versionCode 220
versionName "2.2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -138,6 +138,7 @@ dependencies {
// Java language implementation
implementation "androidx.fragment:fragment:1.4.1"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.browser:browser:1.7.0'
implementation 'androidx.preference:preference:1.1.1'
testImplementation 'junit:junit:4.12'
@@ -190,6 +191,7 @@ dependencies {
// implementation 'com.baidu.lbsyun:BaiduMapSDK_Location:9.1.8'
//MMKV
implementation 'com.tencent:mmkv-static:1.2.14'
// implementation 'com.tencent.tbs.tbssdk:sdk:43993'
//bugly
implementation 'com.tencent.bugly:crashreport:4.1.9.2'
/*xCrash */

View File

@@ -280,6 +280,11 @@
android:name=".activity.service.ServiceActivity"
android:launchMode="singleTask"
android:theme="@style/activity_styles" />
<activity
android:name=".activity.privacy.PrivacyActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/AppThemeFitsSystem" />
<!-- Intent received used to install shortcuts from other applications -->
<receiver

View File

@@ -2,22 +2,25 @@ package com.vscool.os.activity.callwechat;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import com.google.android.accessibility.selecttospeak.SelectToSpeakService;
import com.hjq.toast.Toaster;
import com.tencent.mmkv.MMKV;
import com.vscool.os.R;
import com.vscool.os.base.mvvm.BaseMvvmActivity;
import com.vscool.os.bean.Contact;
import com.vscool.os.config.CommonConfig;
import com.vscool.os.databinding.ActivityWechatCallBinding;
import com.vscool.os.utils.AccessibilityUtils;
import com.vscool.os.utils.ApkUtils;
public class CallWechatActivity extends BaseMvvmActivity<CallWechatViewModel, ActivityWechatCallBinding> {
private static final String TAG = "CallWechatActivity";
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
private Contact mContact;
// private static final int REQUEST_CODE_SCREEN_CAPTURE = 1874;
@@ -64,7 +67,7 @@ public class CallWechatActivity extends BaseMvvmActivity<CallWechatViewModel, Ac
if (contact != null) {
mContact = contact;
mViewDataBinding.setContact(contact);
mViewDataBinding.setTag(!TextUtils.isEmpty(contact.getTag()));
// mViewDataBinding.setTag(!TextUtils.isEmpty(contact.getTag()));
}
}
}
@@ -100,6 +103,12 @@ public class CallWechatActivity extends BaseMvvmActivity<CallWechatViewModel, Ac
return accessibility;
}
private boolean isWeChatAutoCall() {
boolean wxAutoVideo = mMMKV.decodeInt(CommonConfig.WECHAT_AUTO_CALL_KEY, 0) == 1;
Log.e(TAG, "isWeChatAutoCall: " + wxAutoVideo);
return wxAutoVideo;
}
public class BtnClick {
public void callPhone(View view) {
Intent dialIntent = new Intent(Intent.ACTION_CALL);
@@ -111,13 +120,14 @@ public class CallWechatActivity extends BaseMvvmActivity<CallWechatViewModel, Ac
}
public void callWechatVideo(View view) {
if (TextUtils.isEmpty(mContact.getTag())) {
Toaster.show("没有设置标签,无法拨打微信视频");
finish();
return;
}
if (checkSettings()) {
// 1. 获取 MediaProjectionManager 实例
// if (TextUtils.isEmpty(mContact.getTag())) {
// Toaster.show("没有设置标签,无法拨打微信视频");
// finish();
// return;
// }
if (isWeChatAutoCall()) {
if (checkSettings()) {
// 1. 获取 MediaProjectionManager 实例
// MediaProjectionManager projectionManager = (MediaProjectionManager)
// getSystemService(Context.MEDIA_PROJECTION_SERVICE);
// Intent captureIntent = projectionManager.createScreenCaptureIntent();
@@ -128,30 +138,39 @@ public class CallWechatActivity extends BaseMvvmActivity<CallWechatViewModel, Ac
// intent.putExtra("extra_screen_capture_allowed", true);
// startActivityForResult(intent, REQUEST_CODE_SCREEN_CAPTURE);
Intent intent = new Intent(CallWechatActivity.this, SelectToSpeakService.class);
intent.putExtra("WechatInfo", mContact);
intent.putExtra("call_type", SelectToSpeakService.TYPE_VIDEO);
Intent intent = new Intent(CallWechatActivity.this, SelectToSpeakService.class);
intent.putExtra("WechatInfo", mContact);
intent.putExtra("call_type", SelectToSpeakService.TYPE_VIDEO);
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// startForegroundService(intent);
// } else {
startService(intent);
startService(intent);
// }
finish();
}
} else {
ApkUtils.openPackage(CallWechatActivity.this, "com.tencent.mm");
finish();
}
}
public void callWechatVoice(View view) {
if (TextUtils.isEmpty(mContact.getTag())) {
Toaster.show("没有设置标签,无法拨打微信语音");
finish();
return;
}
if (checkSettings()) {
Intent intent = new Intent(CallWechatActivity.this, SelectToSpeakService.class);
intent.putExtra("WechatInfo", mContact);
intent.putExtra("call_type", SelectToSpeakService.TYPE_VOICE);
startService(intent);
// if (TextUtils.isEmpty(mContact.getTag())) {
// Toaster.show("没有设置标签,无法拨打微信语音");
// finish();
// return;
// }
if (isWeChatAutoCall()) {
if (checkSettings()) {
Intent intent = new Intent(CallWechatActivity.this, SelectToSpeakService.class);
intent.putExtra("WechatInfo", mContact);
intent.putExtra("call_type", SelectToSpeakService.TYPE_VOICE);
startService(intent);
finish();
}
} else {
ApkUtils.openPackage(CallWechatActivity.this, "com.tencent.mm");
finish();
}
}

View File

@@ -0,0 +1,99 @@
package com.vscool.os.activity.privacy;
import android.content.Intent;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.vscool.os.R;
import com.vscool.os.base.mvvm.BaseMvvmActivity;
import com.vscool.os.databinding.ActivityPrivacyBinding;
public class PrivacyActivity extends BaseMvvmActivity<PrivacyViewModel, ActivityPrivacyBinding> {
private static final String TAG = "PrivacyActivity";
@Override
public boolean setNightMode() {
return true;
}
@Override
public boolean setfitWindow() {
return true;
}
@Override
protected int getLayoutId() {
return R.layout.activity_privacy;
}
@Override
protected void initDataBinding() {
mViewModel.setCtx(this);
mViewModel.setVDBinding(mViewDataBinding);
mViewModel.setLifecycle(getLifecycleSubject());
mViewDataBinding.setClick(new BtnClick());
}
@Override
protected void initView() {
WebSettings settings = mViewDataBinding.webView.getSettings();
// settings.setUseWideViewPort(true);
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccess(true);
settings.setAllowContentAccess(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
mViewDataBinding.webView.setWebViewClient(new WebViewClient());
mViewDataBinding.webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
if (newProgress == 100) {
mViewDataBinding.progressBar.setVisibility(View.GONE);
} else {
mViewDataBinding.progressBar.setVisibility(View.VISIBLE);
mViewDataBinding.progressBar.setMax(100);
mViewDataBinding.progressBar.setProgress(newProgress);
}
}
});
Intent intent = getIntent();
int contentType = intent.getIntExtra("ContentType", 1);
switch (contentType) {
default:
case 1:
mViewDataBinding.tvTitle.setText("用户协议");
mViewDataBinding.webView.loadUrl("https://www.uiuios.com/agreement.html?section=1-1&status=1&projectId=10");
break;
case 2:
mViewDataBinding.tvTitle.setText("隐私政策");
mViewDataBinding.webView.loadUrl("https://www.uiuios.com/agreement.html?section=1-2&status=1&projectId=10");
break;
case 3:
mViewDataBinding.tvTitle.setText("SDK共享清单");
mViewDataBinding.webView.loadUrl("https://www.uiuios.com/agreement.html?section=1-3&status=1&projectId=10");
break;
case 4:
mViewDataBinding.tvTitle.setText("微信一键视频、语音通话功能用户须知");
mViewDataBinding.webView.loadUrl("https://www.uiuios.com/agreement.html?section=3-6&status=1&projectId=10");
break;
}
}
@Override
protected void initData() {
}
public class BtnClick {
public void exit(View view) {
finish();
}
}
}

View File

@@ -0,0 +1,19 @@
package com.vscool.os.activity.privacy;
import com.trello.rxlifecycle4.android.ActivityEvent;
import com.vscool.os.base.mvvm.BaseViewModel;
import com.vscool.os.databinding.ActivityPrivacyBinding;
public class PrivacyViewModel extends BaseViewModel<ActivityPrivacyBinding, ActivityEvent> {
@Override
public ActivityPrivacyBinding getVDBinding() {
return binding;
}
@Override
public void onDestroy() {
}
}

View File

@@ -33,6 +33,7 @@ import com.vscool.os.config.CommonConfig;
import com.vscool.os.databinding.ActivitySettingBinding;
import com.vscool.os.dialog.CustomDialog;
import com.vscool.os.dialog.PermissionsDialog;
import com.vscool.os.fragment.dialog.PrivacyPolicyFragment;
import com.vscool.os.service.main.MainService;
import com.vscool.os.utils.AccessibilityUtils;
import com.vscool.os.utils.ApkUtils;
@@ -96,12 +97,18 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
setVoiceBroadcast(on);
}
});
mViewDataBinding.tbAuto.setOnToggleChanged(new ToggleButton.OnToggleChanged() {
mViewDataBinding.tbAutoAnswer.setOnToggleChanged(new ToggleButton.OnToggleChanged() {
@Override
public void onToggle(boolean on) {
setAutoAccept(on);
}
});
mViewDataBinding.tbAutoCall.setOnToggleChanged(new ToggleButton.OnToggleChanged() {
@Override
public void onToggle(boolean on) {
setWechatAutoCall(on);
}
});
mViewDataBinding.tbDialer.setOnToggleChanged(new ToggleButton.OnToggleChanged() {
@Override
public void onToggle(boolean on) {
@@ -229,7 +236,7 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
boolean autoAccept = mMMKV.decodeBool(CommonConfig.WECHAT_CALL_AUTO_ACCEPT, false);
Log.e(TAG, "initView: autoAccept = " + autoAccept);
mViewDataBinding.tbAuto.setToggleStatu(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);
@@ -248,6 +255,10 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
}
}
boolean wxAutoVideo = mMMKV.decodeInt(CommonConfig.WECHAT_AUTO_CALL_KEY, 0) == 1;
Log.e(TAG, "initView: wxAutoVideo = " + autoAccept);
mViewDataBinding.tbAutoCall.setToggleStatu(wxAutoVideo);
boolean dialTone = mMMKV.decodeBool(CommonConfig.DISABLE_DIAL_TONE_MODIFY, true);
Log.e(TAG, "initView: dialTone = " + dialTone);
mViewDataBinding.tbDialer.setToggleStatu(dialTone);
@@ -374,18 +385,35 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
public void setAutoAccept(boolean on) {
if (on) {
boolean floatWindowEnable = Settings.Global.getInt(getContentResolver(), CommonConfig.HOVER_HOME, CommonConfig.HOVER_HOME_STATUS) == 1;
boolean permission = FloatingWindowUtils.checkFloatPermission(SettingActivity.this);
if (floatWindowEnable && permission) {
Toast.makeText(SettingActivity.this, "由于系统限制,请先关闭悬浮窗功能,开启自动接听后再打开悬浮窗", Toast.LENGTH_LONG).show();
showFloatWindowDialog();
} else {
showAutoAcceptDialog();
new PrivacyPolicyFragment(new PrivacyPolicyFragment.DialogFragmentCallback() {
@Override
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) {
Toast.makeText(SettingActivity.this, "由于系统限制,请先关闭悬浮窗功能,开启自动接听后再打开悬浮窗", Toast.LENGTH_LONG).show();
showFloatWindowDialog();
} else {
showAutoAcceptDialog();
}
}
@Override
public void onNegative() {
Toaster.show("请先阅读并同意用户须知");
mMMKV.encode(CommonConfig.WECHAT_CALL_AUTO_ACCEPT, 0);
mViewDataBinding.tbAutoCall.setToggleStatu(false);
}
@Override
public void onDismiss() {
setStatus();
}
}).show(getSupportFragmentManager(), PrivacyPolicyFragment.class.getSimpleName());
}
} else {
mMMKV.encode(CommonConfig.WECHAT_CALL_AUTO_ACCEPT, 0);
mViewDataBinding.tbAuto.setToggleStatu(false);
mViewDataBinding.tbAutoAnswer.setToggleStatu(false);
}
// if (AccessibilityUtils.isAccessibilitySettingsOn(SettingActivity.this)) {
@@ -397,7 +425,7 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
// boolean floatWindowEnable = Settings.Global.getInt(getContentResolver(), CommonConfig.HOVER_HOME, CommonConfig.HOVER_HOME_STATUS) == 1;
// if (floatWindowEnable) {
// Toaster.showLong("由于系统限制,请先关闭 主页按钮 功能,开启自动接听后再打开");
// mViewDataBinding.tbAuto.setToggleOff();
// mViewDataBinding.tbAutoAnswer.setToggleOff();
// } else {
// Toast.makeText(SettingActivity.this, "请在无障碍服务中打开 - 亲情桌面快捷服务", Toast.LENGTH_LONG).show();
// startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
@@ -405,9 +433,35 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
// }
}
private PermissionsDialog mFloatWindowDialog;
private void setWechatAutoCall(boolean on) {
if (on) {
new PrivacyPolicyFragment(new PrivacyPolicyFragment.DialogFragmentCallback() {
@Override
public void onPositive() {
mMMKV.encode(CommonConfig.WECHAT_AUTO_CALL_KEY, 1);
mViewDataBinding.tbAutoCall.setToggleStatu(true);
}
@Override
public void onNegative() {
Toaster.show("请先阅读并同意用户须知");
mMMKV.encode(CommonConfig.WECHAT_AUTO_CALL_KEY, 0);
mViewDataBinding.tbAutoCall.setToggleStatu(false);
}
@Override
public void onDismiss() {
setStatus();
}
}).show(getSupportFragmentManager(), PrivacyPolicyFragment.class.getSimpleName());
} else {
mMMKV.encode(CommonConfig.WECHAT_AUTO_CALL_KEY, 0);
mViewDataBinding.tbAutoCall.setToggleStatu(false);
}
}
private void showFloatWindowDialog() {
if (mFloatWindowDialog != null) {
mFloatWindowDialog.dismiss();
@@ -429,7 +483,7 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
@Override
public void onDenied() {
mFloatWindowDialog.dismiss();
mViewDataBinding.tbAuto.setToggleStatu(false);
mViewDataBinding.tbAutoAnswer.setToggleStatu(false);
}
});
mFloatWindowDialog.show();
@@ -445,9 +499,9 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
mAutoAcceptDialog = new PermissionsDialog(SettingActivity.this);
mAutoAcceptDialog.setTitle("功能说明");
if (AccessibilityUtils.isAccessibilitySettingsOn(SettingActivity.this)) {
mAutoAcceptDialog.setContent("微信视频和语通话全屏通知情况下,开启自动接听。");
mAutoAcceptDialog.setContent("微信视频和语通话全屏通知情况下,开启自动接听。");
} else {
mAutoAcceptDialog.setContent("微信视频和语通话全屏通知情况下,开启自动接听。微信自动接听功能需要获取无障碍权限,点击确定将会跳转到系统设置页面");
mAutoAcceptDialog.setContent("微信视频和语通话全屏通知情况下,开启自动接听。微信自动接听功能需要获取无障碍权限,点击确定将会跳转到系统设置页面");
}
mAutoAcceptDialog.setDeniedtext("取消");
mAutoAcceptDialog.setGrantedtext("确定");
@@ -469,7 +523,7 @@ public class SettingActivity extends BaseMvvmActivity<SettingViewModel, Activity
public void onDenied() {
mAutoAcceptDialog.dismiss();
mMMKV.encode(CommonConfig.WECHAT_CALL_AUTO_ACCEPT, 0);
mViewDataBinding.tbAuto.setToggleStatu(false);
mViewDataBinding.tbAutoAnswer.setToggleStatu(false);
}
});
mAutoAcceptDialog.show();

View File

@@ -46,6 +46,7 @@ public class BaseApplication extends Application {
Log.e(TAG, "mmkv root: " + rootDir);
JgyUtils.init(this);
JgyUtils.getInstance().hookWebView();
// 初始化 Toast 框架
Toaster.init(this);

View File

@@ -103,6 +103,10 @@ public class CommonConfig {
public static final String VOICE_BROADCAST = "voice_broadcast_key";
/*微信语音自动接听*/
public static final String WECHAT_CALL_AUTO_ACCEPT = "wechat_call_auto_accept";
/*微信语音自动免提*/
public static final String WECHAT_AUTO_HNADS_FREE = "wechat_auto_hands_free";
/*是否为微信自动拨打电话*/
public static final String WECHAT_AUTO_CALL_KEY = "wechat_auto_call_video";
/*本地设置的*/
/*悬浮窗*/

View File

@@ -0,0 +1,182 @@
package com.vscool.os.fragment.dialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.CompoundButton;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.vscool.os.R;
import com.vscool.os.activity.privacy.PrivacyActivity;
import com.vscool.os.databinding.FragmentPrivacyPolicyBinding;
public class PrivacyPolicyFragment extends DialogFragment {
private static final String TAG = "PrivacyPolicyFragment";
private FragmentPrivacyPolicyBinding mBinding;
private View rootView;
private Context mContext;
public interface DialogFragmentCallback {
void onPositive();
void onNegative();
void onDismiss();
}
private DialogFragmentCallback mDismissCallback;
public PrivacyPolicyFragment(DialogFragmentCallback dialogFragmentCallback) {
this.mDismissCallback = dialogFragmentCallback;
// Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
// Inflate the layout for this fragment
Log.e(TAG, "onCreateView: ");
mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_privacy_policy, container, false);
mBinding.setClick(new BtnClick());
rootView = mBinding.getRoot();
mContext = rootView.getContext();
initView();
return rootView;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
return super.onCreateDialog(savedInstanceState);
}
private void initView() {
mBinding.tvConfirm.setEnabled(false);
mBinding.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mBinding.tvConfirm.setEnabled(true);
} else {
mBinding.tvConfirm.setEnabled(false);
}
}
});
SpannableString spannableString = new SpannableString(mContext.getResources().getString(R.string.user_notice));
spannableString.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
// String url = "https://www.uiuios.com/agreement.html?section=1-1&status=1";
// CustomTabsIntent intent = new CustomTabsIntent.Builder().build();
// try {
// intent.launchUrl(mContext, Uri.parse(url));
// } catch (Exception e) {
// Log.e(TAG, "onClick: " + e.getMessage());
// }
Intent intent = new Intent(mContext, PrivacyActivity.class);
intent.putExtra("ContentType", 4);
mContext.startActivity(intent);
}
}, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new ForegroundColorSpan(Color.BLUE), 0, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mBinding.tvUserNotice.setText(spannableString);
mBinding.tvUserNotice.setMovementMethod(LinkMovementMethod.getInstance());
}
@Override
public void onStart() {
super.onStart();
if (getDialog() != null) {
Window window = getDialog().getWindow();
if (window == null) return;
WindowManager.LayoutParams params = window.getAttributes();
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(params);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
getDialog().setCancelable(true);
getDialog().setCanceledOnTouchOutside(true);
}
}
@Override
public void show(FragmentManager manager, String tag) {
DialogFragment fragment = (DialogFragment) manager.findFragmentByTag(tag);
if (fragment != null && fragment.isAdded()
&& fragment.getDialog() != null && fragment.getDialog().isShowing()) {
return;
}
try {
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss();
} catch (Exception e) {
Log.e(TAG, "show: " + e.getMessage());
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
if (mDismissCallback != null) {
mDismissCallback.onDismiss();
}
}
public class BtnClick {
public void onPositiveClick(View view) {
if (mBinding.checkBox.isChecked()) {
if (mDismissCallback != null) {
mDismissCallback.onPositive();
}
dismiss();
} else {
if (mDismissCallback != null) {
mDismissCallback.onNegative();
}
}
}
public void onRead(View view) {
mBinding.checkBox.setChecked(!mBinding.checkBox.isChecked());
}
}
}

View File

@@ -10,6 +10,10 @@ import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class JgyUtils {
private static String TAG = "JgyUtils";
@@ -99,5 +103,45 @@ public class JgyUtils {
return false;
}
private String chromium_pkg = "org.chromium.browser";
public void hookWebView() {
// if (!ApkUtils.isAvailable(mContext, chromium_pkg)) {
// return;
// }
int sdkInt = Build.VERSION.SDK_INT;
try {
Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
Field field = factoryClass.getDeclaredField("sProviderInstance");
field.setAccessible(true);
Object sProviderInstance = field.get(null);
if (sProviderInstance != null) {
Log.d(TAG, "sProviderInstance isn't null");
return;
}
Method getProviderClassMethod;
if (sdkInt > 22) { // above 22
getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
} else if (sdkInt == 22) { // method name is a little different
getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
} else { // no security check below 22
Log.i(TAG, "Don't need to Hook WebView");
return;
}
getProviderClassMethod.setAccessible(true);
Class<?> providerClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
Constructor<?> declaredConstructor = delegateClass.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
sProviderInstance = providerClass
.getDeclaredMethod("create", delegateClass)
.invoke(providerClass, declaredConstructor.newInstance());
Log.d("sProviderInstance", sProviderInstance.toString());
field.set("sProviderInstance", sProviderInstance);
Log.d(TAG, "Hook done!");
} catch (Throwable e) {
Log.e(TAG, "hook WebView Failed", e);
}
}
}

View File

@@ -138,7 +138,9 @@ public class ToggleButton extends View {
paint.setStrokeCap(Paint.Cap.ROUND);
springSystem = SpringSystem.create();
spring = springSystem.createSpring();
spring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(50, 7));
//张力tension摩擦力friction
//增大张力会使弹簧更快地向目标值运动,减小摩擦力会减少弹簧运动过程中的阻力,从而使回弹更加迅速和有力。
spring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(80, 10));
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
@@ -342,7 +344,7 @@ public class ToggleButton extends View {
/**
* @param on = =
*/
public void onToggle(boolean on);
void onToggle(boolean on);
}
public void setOnToggleChanged(OnToggleChanged onToggleChanged) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#CDE0FF"
android:pathData="M512,512m-448,0a448,448 0,1 0,896 0,448 448,0 1,0 -896,0Z" />
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#0362ff"
android:pathData="M511.6,63.6c-246.9,0 -448,201.2 -448,448 0,247.3 201.2,448 448,448s448,-200.7 448,-448c0,-246.9 -200.7,-448 -448,-448zM771.5,382.1L474.6,699.3c-7,7.3 -16.5,12.1 -27.4,12.1 -10.5,0 -20.5,-4.7 -27.4,-12.1L252,520c-7,-7.3 -11.5,-17.8 -11.5,-29.4 0,-23.1 17.5,-41.4 38.9,-41.4 10.5,0 20.5,4.7 27.4,12.1l140.7,149.9 270,-287.8c7,-7.3 16.5,-12.1 27.4,-12.1 21.5,0 38.9,18.3 38.9,41.4 -0.8,11.6 -5.3,22.1 -12.3,29.4zM771.5,382.1" />
</vector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:state_checked="false" android:drawable="@drawable/ic_negative" />
<item android:state_enabled="true" android:state_checked="true" android:drawable="@drawable/ic_positive" />
</selector>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充的颜色:这里设置背景透明 -->
<solid android:color="#FFFFFF" />
<!-- 边框的颜色 :不能和窗口背景色一样 -->
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners
android:bottomLeftRadius="12dp"
android:bottomRightRadius="12dp"
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />
<!-- paddingButton里面的文字与Button边界的间隔 -->
<!-- <padding-->
<!-- android:bottom="10dp"-->
<!-- android:left="10dp"-->
<!-- android:right="10dp"-->
<!-- android:top="10dp" />-->
</shape>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充的颜色:这里设置背景透明 -->
<solid android:color="#CDE0FF" />
<!-- 边框的颜色 :不能和窗口背景色一样 -->
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners
android:bottomLeftRadius="12dp"
android:bottomRightRadius="12dp"
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />
<!-- paddingButton里面的文字与Button边界的间隔 -->
<padding
android:bottom="8dp"
android:top="8dp" />
</shape>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充的颜色:这里设置背景透明 -->
<solid android:color="#0362FF" />
<!-- 边框的颜色 :不能和窗口背景色一样 -->
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners
android:bottomLeftRadius="12dp"
android:bottomRightRadius="12dp"
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />
<!-- paddingButton里面的文字与Button边界的间隔 -->
<padding
android:bottom="8dp"
android:top="8dp" />
</shape>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 没有焦点时的背景颜色 -->
<item android:drawable="@drawable/privacy_policy_positive_bg" android:state_enabled="true" />
<!-- &lt;!&ndash; 非触摸模式下获得焦点并单击时的背景颜色 &ndash;&gt;-->
<!-- <item android:drawable="@drawable/privacy_policy_positive_bg" android:state_focused="true" android:state_pressed="true" />-->
<!-- &lt;!&ndash; 触摸模式下单击时的背景颜色 &ndash;&gt;-->
<!-- <item android:drawable="@drawable/privacy_policy_positive_bg" android:state_focused="false" android:state_pressed="true" />-->
<!-- &lt;!&ndash; 选中时的背景颜色 &ndash;&gt;-->
<!-- <item android:drawable="@drawable/privacy_policy_positive_bg" android:state_selected="true" />-->
<!-- &lt;!&ndash; 获得焦点时的背景 颜色 &ndash;&gt;-->
<!-- <item android:drawable="@drawable/privacy_policy_positive_bg" android:state_focused="true" />-->
<item android:drawable="@drawable/privacy_policy_negative_bg" android:state_enabled="false" />
</selector>

View File

@@ -0,0 +1,26 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="2dp" />
<gradient
android:angle="270"
android:centerColor="#E3E3E3"
android:endColor="#E6E6E6"
android:startColor="#C8C8C8" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="2dp" />
<gradient
android:centerColor="#2196F3"
android:endColor="#2196F3"
android:startColor="#2099FA" />
</shape>
</clip>
</item>
</layer-list>

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".activity.privacy.PrivacyActivity">
<data>
<variable
name="click"
type="com.vscool.os.activity.privacy.PrivacyActivity.BtnClick" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_bar"
android:layout_width="match_parent"
android:layout_height="48dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/imageView3"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:adjustViewBounds="true"
android:onClick="@{click::exit}"
android:scaleType="centerCrop"
android:src="@drawable/icon_back_black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:maxLines="1"
android:text="隐私协议"
android:textColor="@color/black"
android:textSize="22sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView3"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="4dp"
android:progressDrawable="@drawable/progress_background"
app:layout_constraintTop_toBottomOf="@id/cl_bar" />
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/progressBar" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -185,7 +185,40 @@
app:layout_constraintTop_toTopOf="parent" />
<com.vscool.os.view.ToggleButton
android:id="@+id/tb_auto"
android:id="@+id/tb_auto_answer"
android:layout_width="48dp"
android:layout_height="24dp"
android:layout_marginEnd="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/lightGray"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="72dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:maxLines="1"
android:text="微信自动拨打视频"
android:textColor="@color/black"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.vscool.os.view.ToggleButton
android:id="@+id/tb_auto_call"
android:layout_width="48dp"
android:layout_height="24dp"
android:layout_marginEnd="16dp"

View File

@@ -215,8 +215,7 @@
android:layout_gravity="center"
android:layout_marginTop="16dp"
android:background="@drawable/icon_wechat_call_video"
android:onClick="@{click::callWechatVideo}"
android:visibility="@{tag==true?View.VISIBLE:View.GONE}">
android:onClick="@{click::callWechatVideo}">
<TextView
android:layout_width="wrap_content"
@@ -241,8 +240,7 @@
android:layout_gravity="center"
android:layout_marginTop="16dp"
android:background="@drawable/icon_wechat_call_voice"
android:onClick="@{click::callWechatVoice}"
android:visibility="@{tag==true?View.VISIBLE:View.GONE}">
android:onClick="@{click::callWechatVoice}">
<TextView
android:layout_width="wrap_content"

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".fragment.dialog.PrivacyPolicyFragment">
<data>
<variable
name="click"
type="com.vscool.os.fragment.dialog.PrivacyPolicyFragment.BtnClick" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="330dp"
android:layout_height="wrap_content"
android:background="@drawable/privacy_policy_card_bg"
android:maxHeight="500dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:maxLines="1"
android:singleLine="true"
android:text="功能开启提醒"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toTopOf="@+id/constraintLayout7"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title">
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="@string/wechat_auto_call_hint"
android:textColor="@color/black"
android:textSize="17sp" />
</ScrollView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout7"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:id="@+id/linearLayout5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{click::onRead}">
<CheckBox
android:id="@+id/checkBox"
android:layout_width="20dp"
android:layout_height="20dp"
android:button="@drawable/policy_checkbox_bg"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_user_notice"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:singleLine="true"
android:text="@string/user_notice"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/checkBox"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_weight="1"
android:background="@drawable/privacy_policy_positive_selector"
android:enabled="false"
android:gravity="center"
android:maxLines="1"
android:onClick="@{click::onPositiveClick}"
android:singleLine="true"
android:text="我已知晓并需要启动此功能"
android:textColor="@color/white"
android:textSize="17sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/tv_content"
app:layout_constraintTop_toBottomOf="@+id/tv_content" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -16,6 +16,9 @@
<string name="title_activity_settings">Settings</string>
<string name="clear_app_size">已清理%d个应用</string>
<string name="wechat_auto_call_hint">您当前要开启微信自动拨打视频、语音、自动接听等功能,此功能需要开启系统的无障碍服务才能实现。用户在开启前需要明确知晓其风险,请详细查看协议内容,用户同意后方可使用此功能。</string>
<string name="user_notice">《微信一键视频、语音通话功能用户须知》</string>
<!-- Preference Titles -->
<string name="messages_header">Messages</string>
<string name="sync_header">Sync</string>