Browse Source

[1001744]增加隐私弹窗

zk 1 year ago
parent
commit
e183b7c7b9

+ 25 - 0
app/src/main/java/com/datarecovery/master/App.java

@@ -1,6 +1,9 @@
 package com.datarecovery.master;
 
+import android.content.Context;
+
 import com.atmob.app.lib.base.BaseApplication;
+import com.atmob.common.runtime.ProcessUtil;
 import com.atmob.user.AtmobUser;
 import com.datarecovery.master.data.consts.Constants;
 
@@ -9,6 +12,23 @@ import dagger.hilt.android.HiltAndroidApp;
 
 @HiltAndroidApp
 public class App extends BaseApplication {
+
+
+    private static App INSTANCE;
+
+
+    public static App getInstance() {
+        return INSTANCE;
+    }
+
+
+    @Override
+    protected void attachBaseContext(Context base) {
+        super.attachBaseContext(base);
+        INSTANCE = this;
+    }
+
+
     @Override
     protected boolean isDebug() {
         return BuildConfig.DEBUG;
@@ -43,4 +63,9 @@ public class App extends BaseApplication {
     public void initAfterGrant(boolean isMainProcess) {
 
     }
+
+    public void initPrivacyRelated() {
+        AtmobUser.recordPolicyGrant(true);
+        initAfterGrant(ProcessUtil.isMainProcess(this));
+    }
 }

+ 102 - 0
app/src/main/java/com/datarecovery/master/dialog/AgreementDialog.java

@@ -0,0 +1,102 @@
+package com.datarecovery.master.dialog;
+
+import android.content.Context;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextPaint;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+
+import com.atmob.app.lib.base.BaseDialog;
+import com.datarecovery.master.R;
+import com.datarecovery.master.data.consts.Constants;
+import com.datarecovery.master.databinding.DialogAgreementBinding;
+import com.datarecovery.master.module.browser.BrowserActivity;
+
+
+@BaseDialog.FullScreen(height = false)
+public class AgreementDialog extends BaseDialog<DialogAgreementBinding> {
+
+
+    private AgreementAction agreementAction;
+
+    public AgreementDialog(@NonNull Context context) {
+        super(context, R.style.Theme_Common_Dialog);
+        setCancelable(false);
+        binding.setIsTwoStep(false);
+        binding.setOnAgreeClickListener(v -> {
+            dismiss();
+            if (agreementAction != null) {
+                agreementAction.onAgree();
+            }
+        });
+        binding.setOnStepOneDisagreeClickListener(v -> {
+            binding.setIsTwoStep(true);
+
+        });
+        binding.setOnStepTwoDisagreeClickListener(v -> {
+            dismiss();
+            if (agreementAction != null) {
+                agreementAction.onDisagree();
+            }
+        });
+        binding.tvOneContent.setMovementMethod(LinkMovementMethod.getInstance());
+        binding.tvOneContent.setText(getAgreementContent(getContext().getString(R.string.agreement_one_step_content)));
+    }
+
+    public SpannableStringBuilder getAgreementContent(String agreeText) {
+        Context context = getContext();
+        String userTermsText = context.getString(R.string.user_terms_text);
+        String privacyPolicyText = context.getString(R.string.privacy_policy_text);
+        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(agreeText);
+        int userTermsTextStart = agreeText.indexOf(userTermsText);
+        int privacyPolicyTextStart = agreeText.indexOf(privacyPolicyText);
+
+        ClickableSpan userTermsClickableSpan = new ClickableSpan() {
+
+            @Override
+            public void updateDrawState(@NonNull TextPaint ds) {
+                ds.setColor(context.getResources().getColor(R.color.colorClickPrimary));
+            }
+
+            @Override
+            public void onClick(@NonNull View widget) {
+                BrowserActivity.start(widget.getContext(), Constants.USER_AGREEMENT);
+            }
+        };
+        ClickableSpan privacyPolicyClickableSpan = new ClickableSpan() {
+
+            @Override
+            public void updateDrawState(@NonNull TextPaint ds) {
+                ds.setColor(context.getResources().getColor(R.color.colorClickPrimary));
+            }
+
+
+            @Override
+            public void onClick(@NonNull View widget) {
+                BrowserActivity.start(widget.getContext(), Constants.PRIVACY_POLICY);
+            }
+        };
+        spannableStringBuilder.setSpan(userTermsClickableSpan, userTermsTextStart,
+                userTermsTextStart + userTermsText.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+        spannableStringBuilder.setSpan(privacyPolicyClickableSpan, privacyPolicyTextStart,
+                privacyPolicyTextStart + privacyPolicyText.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+        return spannableStringBuilder;
+    }
+
+
+    public AgreementDialog setAgreementAction(AgreementAction agreementAction) {
+        this.agreementAction = agreementAction;
+        return this;
+    }
+
+
+    public interface AgreementAction {
+        void onAgree();
+
+        void onDisagree();
+    }
+}

+ 142 - 0
app/src/main/java/com/datarecovery/master/module/browser/BrowserActivity.java

@@ -0,0 +1,142 @@
+package com.datarecovery.master.module.browser;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.webkit.WebChromeClient;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.atmob.app.lib.base.BaseActivity;
+import com.datarecovery.master.databinding.ActivityBrowserBinding;
+import com.gyf.immersionbar.ImmersionBar;
+
+import dagger.hilt.android.AndroidEntryPoint;
+
+@AndroidEntryPoint
+public class BrowserActivity extends BaseActivity<ActivityBrowserBinding> {
+
+    private static final String KEY_URL = "key_browser_url";
+    private BrowserViewModel browserViewModel;
+
+    public static void start(Context context, String url) {
+        Intent intent = new Intent(context, BrowserActivity.class);
+        intent.putExtra(KEY_URL, url);
+        context.startActivity(intent);
+    }
+
+    @Override
+    protected void configImmersion(@NonNull ImmersionBar immersionBar) {
+        immersionBar.statusBarDarkFont(true);
+    }
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        initView();
+        initObserver();
+        checkIntent(getIntent());
+    }
+
+    @Override
+    protected boolean shouldImmersion() {
+        return true;
+    }
+
+    @Override
+    protected void initViewModel() {
+        browserViewModel = getViewModelProvider().get(BrowserViewModel.class);
+        binding.setBrowserViewModel(browserViewModel);
+    }
+
+    private void initView() {
+        addTopStatusBarHeight(binding.browserHeader);
+        initWebView();
+    }
+
+    private void initObserver() {
+        browserViewModel.getOnFinishEvent().observe(this, o -> finish());
+    }
+
+    @SuppressLint("SetJavaScriptEnabled")
+    private void initWebView() {
+        WebSettings settings = binding.browserWebView.getSettings();
+        settings.setUseWideViewPort(true);
+        settings.setLoadWithOverviewMode(true);
+        settings.setJavaScriptEnabled(true);
+        settings.setDomStorageEnabled(true);
+        settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
+        settings.setLoadsImagesAutomatically(true);
+        settings.setMediaPlaybackRequiresUserGesture(true);
+        settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
+        settings.setAllowFileAccess(true);
+        settings.setJavaScriptCanOpenWindowsAutomatically(true);
+        settings.setDefaultTextEncodingName("utf-8");
+        settings.setAllowContentAccess(true);
+        settings.setAllowFileAccessFromFileURLs(true);
+
+        binding.browserWebView.setWebViewClient(new WebViewClient() {
+            @Override
+            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
+                String url = request.getUrl().toString();
+                if (url.startsWith("http://") || url.startsWith("https://")) {
+                    binding.browserWebView.loadUrl(url);
+                    return false;
+                } else {
+                    Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
+                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    startActivity(intent);
+                    return true;
+                }
+            }
+        });
+        binding.browserWebView.setWebChromeClient(new WebChromeClient() {
+            @Override
+            public void onReceivedTitle(WebView view, String title) {
+                super.onReceivedTitle(view, title);
+                browserViewModel.setWebTitle(title);
+            }
+        });
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        checkIntent(intent);
+    }
+
+    private void checkIntent(Intent intent) {
+        String url = intent.getStringExtra(KEY_URL);
+        if (TextUtils.isEmpty(url)) {
+            return;
+        }
+        if (isUrl(url)) {
+            binding.browserWebView.loadUrl(url);
+        } else {
+            try {
+                Uri uri = Uri.parse(url);
+                startActivity(new Intent(Intent.ACTION_VIEW, uri));
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            finish();
+        }
+    }
+
+    public boolean isUrl(String str) {
+        if (TextUtils.isEmpty(str)) {
+            return false;
+        }
+        String upperCaseStr = str.toUpperCase();
+        return upperCaseStr.startsWith("HTTP://") || upperCaseStr.startsWith("HTTPS://");
+    }
+
+}

+ 40 - 0
app/src/main/java/com/datarecovery/master/module/browser/BrowserViewModel.java

@@ -0,0 +1,40 @@
+package com.datarecovery.master.module.browser;
+
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.ViewModel;
+
+
+import com.atmob.app.lib.livedata.SingleLiveEvent;
+
+import javax.inject.Inject;
+
+import dagger.hilt.android.lifecycle.HiltViewModel;
+
+@HiltViewModel
+public class BrowserViewModel extends ViewModel {
+
+    private final SingleLiveEvent<?> onFinishEvent = new SingleLiveEvent<>();
+
+    private final MutableLiveData<String> webTitle = new MutableLiveData<>();
+
+    @Inject
+    public BrowserViewModel() {
+    }
+
+    public LiveData<?> getOnFinishEvent() {
+        return onFinishEvent;
+    }
+
+    public LiveData<String> getWebTitle() {
+        return webTitle;
+    }
+
+    public void onBackClick() {
+        onFinishEvent.call();
+    }
+
+    public void setWebTitle(String webTitle) {
+        this.webTitle.setValue(webTitle);
+    }
+}

+ 21 - 3
app/src/main/java/com/datarecovery/master/module/splash/SplashActivity.java

@@ -10,20 +10,21 @@ import androidx.annotation.Nullable;
 
 import com.atmob.app.lib.base.BaseActivity;
 import com.atmob.user.AtmobUser;
+import com.datarecovery.master.App;
 import com.datarecovery.master.databinding.ActivitySplashBinding;
+import com.datarecovery.master.dialog.AgreementDialog;
 import com.datarecovery.master.module.main.MainActivity;
 import com.gyf.immersionbar.ImmersionBar;
 
 @SuppressLint("CustomSplashScreen")
 public class SplashActivity extends BaseActivity<ActivitySplashBinding> {
 
-
+    private AgreementDialog agreementDialog;
     private final int delayMillis = 3000;
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        AtmobUser.recordPolicyGrant(true);
         checkPolicy();
     }
 
@@ -49,7 +50,24 @@ public class SplashActivity extends BaseActivity<ActivitySplashBinding> {
     }
 
     private void showPolicyDialog() {
-
+        if (agreementDialog == null) {
+            agreementDialog = new AgreementDialog(this);
+            agreementDialog.setAgreementAction(new AgreementDialog.AgreementAction() {
+                @Override
+                public void onAgree() {
+                    binding.getRoot().post(() -> {
+                        App.getInstance().initPrivacyRelated();
+                        nextStep();
+                    });
+                }
+
+                @Override
+                public void onDisagree() {
+                    finishAfterTransition();
+                }
+            });
+        }
+        agreementDialog.show();
     }
 
     @Override

+ 0 - 58
app/src/main/java/com/datarecovery/master/utils/livedata/SingleLiveEvent.java

@@ -1,58 +0,0 @@
-package com.datarecovery.master.utils.livedata;
-
-import android.util.Log;
-
-import androidx.annotation.MainThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.Observer;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * A lifecycle-aware observable that sends only new updates after subscription, used for events like
- * navigation and Snackbar messages.
- * <p>
- * This avoids a common problem with events: on configuration change (like rotation) an update
- * can be emitted if the observer is active. This LiveData only calls the observable if there's an
- * explicit call to setValue() or call().
- * <p>
- * Note that only one observer is going to be notified of changes.
- * <p>
- */
-public class SingleLiveEvent<T> extends MutableLiveData<T> {
-
-    private static final String TAG = "SingleLiveEvent";
-
-    private final AtomicBoolean mPending = new AtomicBoolean(false);
-
-    @MainThread
-    public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
-        if (hasActiveObservers()) {
-            Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");
-        }
-
-        // Observe the internal MutableLiveData
-        super.observe(owner, t -> {
-            if (mPending.compareAndSet(true, false)) {
-                observer.onChanged(t);
-            }
-        });
-    }
-
-    @MainThread
-    public void setValue(@Nullable T t) {
-        mPending.set(true);
-        super.setValue(t);
-    }
-
-    /**
-     * Used for cases where T is Void, to make calls cleaner.
-     */
-    @MainThread
-    public void call() {
-        setValue(null);
-    }
-}

BIN
app/src/main/res/drawable-xxhdpi/icon_back.webp


+ 5 - 0
app/src/main/res/drawable/bg_agreement_disagree.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="8dp" />
+    <solid android:color="#E1E1E1" />
+</shape>

+ 5 - 0
app/src/main/res/drawable/bg_common_btn.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="8dp" />
+    <solid android:color="@color/colorPrimary" />
+</shape>

+ 5 - 0
app/src/main/res/drawable/bg_dialog_agreement.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="8dp" />
+    <solid android:color="@color/white" />
+</shape>

+ 35 - 0
app/src/main/res/layout/activity_browser.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+
+    <data>
+
+        <variable
+            name="browserViewModel"
+            type="com.datarecovery.master.module.browser.BrowserViewModel" />
+    </data>
+
+    <androidx.constraintlayout.widget.ConstraintLayout 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"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <androidx.appcompat.widget.Toolbar
+            android:id="@+id/browser_header"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            app:layout_constraintTop_toTopOf="parent"
+            app:navigationIcon="@drawable/icon_back"
+            app:navigationOnClickListener="@{()-> browserViewModel.onBackClick()}"
+            app:title="@{browserViewModel.webTitle}"
+            style="@style/tool_bar_style"
+            tools:title="this is a test title" />
+
+        <WebView
+            android:id="@+id/browser_web_view"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/browser_header" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</layout>

+ 260 - 0
app/src/main/res/layout/dialog_agreement.xml

@@ -0,0 +1,260 @@
+<?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">
+
+    <data>
+
+        <variable
+            name="isTwoStep"
+            type="Boolean" />
+
+        <variable
+            name="onAgreeClickListener"
+            type="android.view.View.OnClickListener" />
+
+        <variable
+            name="onStepOneDisagreeClickListener"
+            type="android.view.View.OnClickListener" />
+
+        <variable
+            name="onStepTwoDisagreeClickListener"
+            type="android.view.View.OnClickListener" />
+
+
+    </data>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        tools:background="@color/black70">
+
+
+        <androidx.constraintlayout.widget.ConstraintLayout
+            isGone="@{isTwoStep}"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintWidth_percent="0.7777777777777778">
+
+            <Space
+                android:id="@+id/space_one_1"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintDimensionRatio="360:24"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <View
+                android:id="@+id/v_one_step_bg"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:background="@drawable/bg_dialog_agreement"
+                app:layout_constraintBottom_toBottomOf="@+id/space_one_5"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="@+id/space_one_1"
+                app:layout_constraintWidth_percent="0.7777777777777778" />
+
+            <TextView
+                android:id="@+id/tv_one_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/agreement_privacy_policy"
+                android:textColor="#202020"
+                android:textSize="15sp"
+                android:textStyle="bold"
+                app:layout_constraintEnd_toEndOf="@+id/v_one_step_bg"
+                app:layout_constraintStart_toStartOf="@+id/v_one_step_bg"
+                app:layout_constraintTop_toBottomOf="@+id/space_one_1" />
+
+            <Space
+                android:id="@+id/space_one_2"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintDimensionRatio="360:16"
+                app:layout_constraintTop_toBottomOf="@+id/tv_one_title" />
+
+
+            <TextView
+                android:id="@+id/tv_one_content"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:textColor="#404040"
+                android:textSize="14sp"
+                app:layout_constraintEnd_toEndOf="@+id/v_one_step_bg"
+                app:layout_constraintStart_toStartOf="@id/v_one_step_bg"
+                app:layout_constraintTop_toBottomOf="@+id/space_one_2"
+                app:layout_constraintWidth_percent="0.6444444444444444"
+                tools:text="欢迎使用文件恢复大师!
+在开始之前,请花一些时间仔细阅读《用户协议》和《隐私政策》。这些文件描述了您与我们之间的权利和义务,以及我们收集、使用和保护您的个人信息的方式,我们建议您阅读用户协议和隐私政策,以确保理解您的权益和我们的责任,只有在您理解并同意协议和政策内容后,才能继续使用我们的服务。" />
+
+            <Space
+                android:id="@+id/space_one_3"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintDimensionRatio="360:12"
+                app:layout_constraintTop_toBottomOf="@+id/tv_one_content" />
+
+            <TextView
+                android:id="@+id/tv_one_agree"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:background="@drawable/bg_common_btn"
+                android:gravity="center"
+                android:onClick="@{onAgreeClickListener}"
+                android:text="@string/agreement_agree"
+                android:textColor="@color/white"
+                android:textSize="14sp"
+                android:textStyle="bold"
+                app:layout_constraintDimensionRatio="150:36"
+                app:layout_constraintEnd_toEndOf="@id/v_one_step_bg"
+                app:layout_constraintStart_toStartOf="@id/v_one_step_bg"
+                app:layout_constraintTop_toBottomOf="@+id/space_one_3"
+                app:layout_constraintWidth_percent="0.4166666666666667" />
+
+
+            <Space
+                android:id="@+id/space_one_4"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintDimensionRatio="360:14"
+                app:layout_constraintTop_toBottomOf="@+id/tv_one_agree" />
+
+            <TextView
+                android:id="@+id/tv_one_disagree"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="@{onStepOneDisagreeClickListener}"
+                android:text="@string/agreement_disagree"
+                android:textColor="#404040"
+                android:textSize="14sp"
+                app:layout_constraintEnd_toEndOf="@id/v_one_step_bg"
+                app:layout_constraintStart_toStartOf="@id/v_one_step_bg"
+                app:layout_constraintTop_toBottomOf="@+id/space_one_4" />
+
+            <Space
+                android:id="@+id/space_one_5"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintDimensionRatio="360:16"
+                app:layout_constraintTop_toBottomOf="@+id/tv_one_disagree" />
+
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+        <androidx.constraintlayout.widget.ConstraintLayout
+            isGone="@{!isTwoStep}"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintWidth_percent="0.7777777777777778">
+
+            <Space
+                android:id="@+id/space_two_1"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintDimensionRatio="360:24"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <View
+                android:id="@+id/v_two_step_bg"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:background="@drawable/bg_dialog_agreement"
+                app:layout_constraintBottom_toBottomOf="@+id/space_two_4"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="@+id/space_two_1"
+                app:layout_constraintWidth_percent="0.7777777777777778" />
+
+            <TextView
+                android:id="@+id/tv_two_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/agreement_kind_tips"
+                android:textColor="#202020"
+                android:textSize="15sp"
+                android:textStyle="bold"
+                app:layout_constraintEnd_toEndOf="@+id/v_two_step_bg"
+                app:layout_constraintStart_toStartOf="@+id/v_two_step_bg"
+                app:layout_constraintTop_toBottomOf="@+id/space_two_1" />
+
+            <Space
+                android:id="@+id/space_two_2"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintDimensionRatio="360:16"
+                app:layout_constraintTop_toBottomOf="@+id/tv_two_title" />
+
+
+            <TextView
+                android:id="@+id/tv_two_content"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:text="@string/agreement_two_step_content"
+                android:textColor="#404040"
+                android:textSize="14sp"
+                app:layout_constraintEnd_toEndOf="@+id/v_two_step_bg"
+                app:layout_constraintStart_toStartOf="@id/v_two_step_bg"
+                app:layout_constraintTop_toBottomOf="@+id/space_two_2"
+                app:layout_constraintWidth_percent="0.6444444444444444" />
+
+            <Space
+                android:id="@+id/space_two_3"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintDimensionRatio="360:36"
+                app:layout_constraintTop_toBottomOf="@+id/tv_two_content" />
+
+            <TextView
+                android:id="@+id/tv_two_agree"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:background="@drawable/bg_agreement_disagree"
+                android:gravity="center"
+                android:onClick="@{onStepTwoDisagreeClickListener}"
+                android:text="@string/agreement_exit"
+                android:textColor="@color/white"
+                android:textSize="14sp"
+                android:textStyle="bold"
+                app:layout_constraintDimensionRatio="110:36"
+                app:layout_constraintLeft_toLeftOf="@id/v_two_step_bg"
+                app:layout_constraintRight_toLeftOf="@+id/tv_two_disagree"
+                app:layout_constraintTop_toBottomOf="@+id/space_two_3"
+                app:layout_constraintWidth_percent="0.3055555555555556" />
+
+
+            <TextView
+                android:id="@+id/tv_two_disagree"
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:background="@drawable/bg_common_btn"
+                android:gravity="center"
+                android:onClick="@{onAgreeClickListener}"
+                android:text="@string/agreement_consider_it"
+                android:textColor="@color/white"
+                android:textStyle="bold"
+                app:layout_constraintDimensionRatio="110:36"
+                app:layout_constraintLeft_toRightOf="@+id/tv_two_agree"
+                app:layout_constraintRight_toRightOf="@id/v_two_step_bg"
+                app:layout_constraintTop_toTopOf="@+id/tv_two_agree"
+                app:layout_constraintWidth_percent="0.3055555555555556" />
+
+            <Space
+                android:id="@+id/space_two_4"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintDimensionRatio="360:24"
+                app:layout_constraintTop_toBottomOf="@+id/tv_two_agree" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</layout>

+ 11 - 0
app/src/main/res/values/strings.xml

@@ -7,4 +7,15 @@
     <string name="main_pager_mine">我的</string>
 
     <string name="exit_application_text">再按一次退出程序</string>
+
+    <string name="agreement_privacy_policy">用户协议与隐私政策</string>
+    <string name="agreement_agree">同意并继续</string>
+    <string name="agreement_disagree">不同意</string>
+    <string name="agreement_kind_tips">温馨提示</string>
+    <string name="agreement_exit">退出</string>
+    <string name="agreement_consider_it">考虑一下</string>
+    <string name="agreement_one_step_content">欢迎使用文件恢复大师!在开始之前,请花一些时间仔细阅读《用户协议》和《隐私政策》。这些文件描述了您与我们之间的权利和义务,以及我们收集、使用和保护您的个人信息的方式,我们建议您阅读用户协议和隐私政策,以确保理解您的权益和我们的责任,只有在您理解并同意协议和政策内容后,才能继续使用我们的服务。</string>
+    <string name="agreement_two_step_content">您需要同意相关协议才能使用本产品</string>
+    <string name="user_terms_text">《用户协议》</string>
+    <string name="privacy_policy_text">《隐私政策》</string>
 </resources>

+ 20 - 0
app/src/main/res/values/style.xml

@@ -19,5 +19,25 @@
         <item name="android:paddingLeft">12dp</item>
     </style>
 
+    <style name="Theme.Common.Dialog" parent="Theme.MaterialComponents.Light.Dialog">
+        <!-- Primary brand color. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryVariant">@color/colorPrimaryVariant</item>
+        <item name="colorOnPrimary">@color/white</item>
+
+        <!-- Customize your theme here. -->
+        <item name="android:windowFullscreen">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:backgroundDimAmount">0.7</item>
+
+        <item name="android:windowAnimationStyle">@style/Animation.CommonDialog</item>
+    </style>
+
+
+    <style name="Animation.CommonDialog" parent="Animation.AppCompat.Dialog">
+        <item name="android:windowEnterAnimation">@anim/anim_alpha_in</item>
+        <item name="android:windowExitAnimation">@anim/anim_alpha_out</item>
+    </style>
+
 
 </resources>