diff --git a/app/build.gradle b/app/build.gradle
index 6f5b3ad..fc3fc8a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -17,8 +17,8 @@ android {
applicationId "com.xxpatx.os"
minSdkVersion 24
targetSdkVersion 29
- versionCode 1066
- versionName "1.6.6"
+ versionCode 1068
+ versionName "1.6.8"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -229,7 +229,7 @@ dependencies {
//MMKV
implementation 'com.tencent:mmkv-static:1.2.14'
//bugly
- implementation 'com.tencent.bugly:crashreport:4.1.9.2'
+ implementation 'com.tencent.bugly:crashreport:4.1.9.3'
/*xCrash */
implementation 'com.iqiyi.xcrash:xcrash-android-lib:3.0.0'
//阿里云推送
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e8b3c3a..cfd0676 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -287,6 +287,11 @@
android:name=".activity.service.ServiceActivity"
android:launchMode="singleTask"
android:theme="@style/activity_styles" />
+
{
+ 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();
+ }
+ }
+}
diff --git a/app/src/main/java/com/xxpatx/os/activity/privacy/PrivacyViewModel.java b/app/src/main/java/com/xxpatx/os/activity/privacy/PrivacyViewModel.java
new file mode 100644
index 0000000..c29fa07
--- /dev/null
+++ b/app/src/main/java/com/xxpatx/os/activity/privacy/PrivacyViewModel.java
@@ -0,0 +1,19 @@
+package com.xxpatx.os.activity.privacy;
+
+import com.trello.rxlifecycle4.android.ActivityEvent;
+import com.xxpatx.os.base.mvvm.BaseViewModel;
+import com.xxpatx.os.databinding.ActivityPrivacyBinding;
+
+public class PrivacyViewModel extends BaseViewModel {
+
+ @Override
+ public ActivityPrivacyBinding getVDBinding() {
+ return binding;
+ }
+
+ @Override
+ public void onDestroy() {
+
+ }
+
+}
diff --git a/app/src/main/java/com/xxpatx/os/activity/setting/SettingActivity.java b/app/src/main/java/com/xxpatx/os/activity/setting/SettingActivity.java
index a6adc16..a808d38 100644
--- a/app/src/main/java/com/xxpatx/os/activity/setting/SettingActivity.java
+++ b/app/src/main/java/com/xxpatx/os/activity/setting/SettingActivity.java
@@ -32,6 +32,7 @@ import com.xxpatx.os.bean.AppInfo;
import com.xxpatx.os.bean.SystemSettings;
import com.xxpatx.os.config.CommonConfig;
import com.xxpatx.os.databinding.ActivitySettingBinding;
+import com.xxpatx.os.fragment.dialog.PrivacyPolicyFragment;
import com.xxpatx.os.service.main.MainService;
import com.xxpatx.os.utils.AccessibilityUtils;
import com.xxpatx.os.utils.ApkUtils;
@@ -277,21 +278,86 @@ public class SettingActivity extends BaseMvvmActivity 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);
+ }
+ }
}
diff --git a/app/src/main/java/com/xxpatx/os/config/CommonConfig.java b/app/src/main/java/com/xxpatx/os/config/CommonConfig.java
index a5654e7..b31b888 100644
--- a/app/src/main/java/com/xxpatx/os/config/CommonConfig.java
+++ b/app/src/main/java/com/xxpatx/os/config/CommonConfig.java
@@ -108,6 +108,11 @@ 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";
+
/*app启动播报*/
public static final String VOICE_SPEAKER_KEY = "voice_speaker";
/*电话白名单*/
diff --git a/app/src/main/java/com/xxpatx/os/fragment/dialog/PrivacyPolicyFragment.java b/app/src/main/java/com/xxpatx/os/fragment/dialog/PrivacyPolicyFragment.java
new file mode 100644
index 0000000..e6b1c31
--- /dev/null
+++ b/app/src/main/java/com/xxpatx/os/fragment/dialog/PrivacyPolicyFragment.java
@@ -0,0 +1,182 @@
+package com.xxpatx.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.xxpatx.os.R;
+import com.xxpatx.os.activity.privacy.PrivacyActivity;
+import com.xxpatx.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());
+ }
+
+ }
+}
diff --git a/app/src/main/java/com/xxpatx/os/service/main/MainSPresenter.java b/app/src/main/java/com/xxpatx/os/service/main/MainSPresenter.java
index 7a6dfca..4fe2835 100644
--- a/app/src/main/java/com/xxpatx/os/service/main/MainSPresenter.java
+++ b/app/src/main/java/com/xxpatx/os/service/main/MainSPresenter.java
@@ -313,12 +313,16 @@ public class MainSPresenter implements MainSContact.Presenter {
if (baseResponse.code == 200) {
ClockSetting clockSetting = baseResponse.data;
String time = clockSetting.getClock();
- List integers = new ArrayList<>();
- List timeLsit = new ArrayList<>(Arrays.asList(time.split(",")));
- for (String s : timeLsit) {
- integers.add(Integer.parseInt(s));
+ if (!TextUtils.isEmpty(time)) {
+ List integers = new ArrayList<>();
+ List timeLsit = new ArrayList<>(Arrays.asList(time.split(",")));
+ for (String s : timeLsit) {
+ integers.add(Integer.parseInt(s));
+ }
+ mMMKV.encode(CommonConfig.TIME_HOUR_LIST_KEY, GsonUtils.toJSONString(integers));
+ } else {
+ mMMKV.encode(CommonConfig.TIME_HOUR_LIST_KEY, "");
}
- mMMKV.encode(CommonConfig.TIME_HOUR_LIST_KEY, GsonUtils.toJSONString(integers));
}
}
diff --git a/app/src/main/res/drawable-hdpi/icon_back_black.png b/app/src/main/res/drawable-hdpi/icon_back_black.png
new file mode 100644
index 0000000..5bd377b
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_back_black.png differ
diff --git a/app/src/main/res/drawable/ic_negative.xml b/app/src/main/res/drawable/ic_negative.xml
new file mode 100644
index 0000000..2a3f38c
--- /dev/null
+++ b/app/src/main/res/drawable/ic_negative.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_positive.xml b/app/src/main/res/drawable/ic_positive.xml
new file mode 100644
index 0000000..557dcdf
--- /dev/null
+++ b/app/src/main/res/drawable/ic_positive.xml
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/policy_checkbox_bg.xml b/app/src/main/res/drawable/policy_checkbox_bg.xml
new file mode 100644
index 0000000..ae1863c
--- /dev/null
+++ b/app/src/main/res/drawable/policy_checkbox_bg.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/privacy_policy_card_bg.xml b/app/src/main/res/drawable/privacy_policy_card_bg.xml
new file mode 100644
index 0000000..fa6a0ce
--- /dev/null
+++ b/app/src/main/res/drawable/privacy_policy_card_bg.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/privacy_policy_negative_bg.xml b/app/src/main/res/drawable/privacy_policy_negative_bg.xml
new file mode 100644
index 0000000..a6b2310
--- /dev/null
+++ b/app/src/main/res/drawable/privacy_policy_negative_bg.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/privacy_policy_positive_bg.xml b/app/src/main/res/drawable/privacy_policy_positive_bg.xml
new file mode 100644
index 0000000..da28637
--- /dev/null
+++ b/app/src/main/res/drawable/privacy_policy_positive_bg.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/privacy_policy_positive_selector.xml b/app/src/main/res/drawable/privacy_policy_positive_selector.xml
new file mode 100644
index 0000000..8604090
--- /dev/null
+++ b/app/src/main/res/drawable/privacy_policy_positive_selector.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/progress_background.xml b/app/src/main/res/drawable/progress_background.xml
new file mode 100644
index 0000000..4f3104c
--- /dev/null
+++ b/app/src/main/res/drawable/progress_background.xml
@@ -0,0 +1,26 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_privacy.xml b/app/src/main/res/layout/activity_privacy.xml
new file mode 100644
index 0000000..8be538e
--- /dev/null
+++ b/app/src/main/res/layout/activity_privacy.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml
index 2f80520..1867dba 100644
--- a/app/src/main/res/layout/activity_setting.xml
+++ b/app/src/main/res/layout/activity_setting.xml
@@ -22,6 +22,10 @@
name="auto_accept"
type="Boolean" />
+
+
@@ -102,7 +106,7 @@
android:onClick="@{click::openFloat}">
+
+
+
+
+
+
+
+
+
+
+
-
+ android:onClick="@{click::callWechatVoice}">
+ android:onClick="@{click::callWechatVideo}">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index eaf4825..75e9000 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -16,6 +16,9 @@
Settings
已清理%d个应用
+ 您当前要开启微信自动拨打视频、语音、自动接听等功能,此功能需要开启系统的无障碍服务才能实现。用户在开启前需要明确知晓其风险,请详细查看协议内容,用户同意后方可使用此功能。
+ 《微信一键视频、语音通话功能用户须知》
+
Messages
Sync
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 4398925..e041b28 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -26,6 +26,15 @@
- @color/gray
+
+