Prechádzať zdrojové kódy

[new]增加新的开屏页

zk 1 rok pred
rodič
commit
21ff353a5e

+ 4 - 1
app/src/main/AndroidManifest.xml

@@ -23,9 +23,11 @@
         tools:replace="android:allowBackup"
         tools:targetApi="32">
 
-
         <activity
             android:name=".module.splash.SplashActivity"
+            android:screenOrientation="portrait" />
+        <activity
+            android:name=".module.newsplash.NewSplashActivity"
             android:exported="true"
             android:screenOrientation="portrait"
             android:theme="@style/Theme.Splash">
@@ -60,6 +62,7 @@
             android:name=".module.integral.IntegralPurchaseActivity"
             android:screenOrientation="portrait" />
 
+
         <provider
             android:name="androidx.core.content.FileProvider"
             android:authorities="${applicationId}.fileprovider"

BIN
app/src/main/assets/anim/splash_loading.zip


+ 4 - 0
app/src/main/java/com/atmob/voiceai/data/api/AtmobApi.java

@@ -19,6 +19,7 @@ import com.atmob.voiceai.data.api.response.OrderPayResponse;
 import com.atmob.voiceai.data.api.response.OrderStatusResponse;
 import com.atmob.voiceai.data.api.response.PayGoodsResponse;
 import com.atmob.voiceai.data.api.response.RandomTextResponse;
+import com.atmob.voiceai.data.api.response.SplashPageResponse;
 import com.atmob.voiceai.data.api.response.TextToSpeechResponse;
 import com.atmob.voiceai.data.api.response.UserInfoResponse;
 import com.atmob.voiceai.data.api.response.VoiceCloneListResponse;
@@ -90,4 +91,7 @@ public interface AtmobApi {
     @POST("/project/voice/v1/attribution/info")
     Single<BaseResponse<Object>> attributionInfo(@Body AttributionRequest request);
 
+    @POST("/project/voice/v1/item/splashPage")
+    Single<BaseResponse<SplashPageResponse>> splashPage(@Body BaseRequest request);
+
 }

+ 217 - 0
app/src/main/java/com/atmob/voiceai/data/api/bean/SplashPageBean.java

@@ -0,0 +1,217 @@
+package com.atmob.voiceai.data.api.bean;
+
+import com.atmob.voiceai.sdk.billing.bean.GPProductInfo;
+import com.google.gson.annotations.SerializedName;
+
+public class SplashPageBean {
+    @SerializedName("id")
+    private int id;
+    @SerializedName("sort")
+    private int sort;
+    @SerializedName("name")
+    private String name;
+    @SerializedName("amount")
+    private int amount;
+    @SerializedName("originalAmount")
+    private int originalAmount;
+    @SerializedName("googleProductId")
+    private String googleProductId;
+    @SerializedName("subscribable")
+    private int subscribable;
+    @SerializedName("subscriptionGroup")
+    private String subscriptionGroup;
+    @SerializedName("packageName")
+    private String packageName;
+    @SerializedName("auth")
+    private String auth;
+    @SerializedName("content")
+    private String content;
+    @SerializedName("description")
+    private String description;
+    @SerializedName("subscriptionMillis")
+    private long subscriptionMillis;
+    @SerializedName("popular")
+    private boolean popular;
+    @SerializedName("planId")
+    private String planId;
+    @SerializedName("lowGoogleProductId")
+    private String lowGoogleProductId;
+    @SerializedName("lowPlanId")
+    private String lowPlanId;
+    @SerializedName("days")
+    private int days;
+    @SerializedName("authValue")
+    private int authValue;
+    @SerializedName("remark")
+    private String remark;
+
+    private GPProductInfo gpProductInfo;
+
+    public GPProductInfo getGpProductInfo() {
+        return gpProductInfo;
+    }
+
+    public void setGpProductInfo(GPProductInfo gpProductInfo) {
+        this.gpProductInfo = gpProductInfo;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getSort() {
+        return sort;
+    }
+
+    public void setSort(int sort) {
+        this.sort = sort;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getAmount() {
+        return amount;
+    }
+
+    public void setAmount(int amount) {
+        this.amount = amount;
+    }
+
+    public int getOriginalAmount() {
+        return originalAmount;
+    }
+
+    public void setOriginalAmount(int originalAmount) {
+        this.originalAmount = originalAmount;
+    }
+
+    public String getGoogleProductId() {
+        return googleProductId;
+    }
+
+    public void setGoogleProductId(String googleProductId) {
+        this.googleProductId = googleProductId;
+    }
+
+    public int getSubscribable() {
+        return subscribable;
+    }
+
+    public void setSubscribable(int subscribable) {
+        this.subscribable = subscribable;
+    }
+
+    public String getSubscriptionGroup() {
+        return subscriptionGroup;
+    }
+
+    public void setSubscriptionGroup(String subscriptionGroup) {
+        this.subscriptionGroup = subscriptionGroup;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName) {
+        this.packageName = packageName;
+    }
+
+    public String getAuth() {
+        return auth;
+    }
+
+    public void setAuth(String auth) {
+        this.auth = auth;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public long getSubscriptionMillis() {
+        return subscriptionMillis;
+    }
+
+    public void setSubscriptionMillis(long subscriptionMillis) {
+        this.subscriptionMillis = subscriptionMillis;
+    }
+
+    public boolean isPopular() {
+        return popular;
+    }
+
+    public void setPopular(boolean popular) {
+        this.popular = popular;
+    }
+
+    public String getPlanId() {
+        return planId;
+    }
+
+    public void setPlanId(String planId) {
+        this.planId = planId;
+    }
+
+    public String getLowGoogleProductId() {
+        return lowGoogleProductId;
+    }
+
+    public void setLowGoogleProductId(String lowGoogleProductId) {
+        this.lowGoogleProductId = lowGoogleProductId;
+    }
+
+    public String getLowPlanId() {
+        return lowPlanId;
+    }
+
+    public void setLowPlanId(String lowPlanId) {
+        this.lowPlanId = lowPlanId;
+    }
+
+    public int getDays() {
+        return days;
+    }
+
+    public void setDays(int days) {
+        this.days = days;
+    }
+
+    public int getAuthValue() {
+        return authValue;
+    }
+
+    public void setAuthValue(int authValue) {
+        this.authValue = authValue;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+}

+ 20 - 0
app/src/main/java/com/atmob/voiceai/data/api/response/SplashPageResponse.java

@@ -0,0 +1,20 @@
+package com.atmob.voiceai.data.api.response;
+
+import com.atmob.voiceai.data.api.bean.SplashPageBean;
+import com.google.gson.annotations.SerializedName;
+
+public class SplashPageResponse {
+
+
+    @SerializedName("item")
+    private SplashPageBean item;
+
+    public SplashPageBean getItem() {
+        return item;
+    }
+
+    public void setItem(SplashPageBean item) {
+        this.item = item;
+    }
+
+}

+ 9 - 2
app/src/main/java/com/atmob/voiceai/data/repositories/MemberRepository.java

@@ -25,6 +25,7 @@ import com.atmob.voiceai.data.api.request.SubResumeRequest;
 import com.atmob.voiceai.data.api.response.OrderPayResponse;
 import com.atmob.voiceai.data.api.response.OrderStatusResponse;
 import com.atmob.voiceai.data.api.response.PayGoodsResponse;
+import com.atmob.voiceai.data.api.response.SplashPageResponse;
 import com.atmob.voiceai.data.api.response.UserInfoResponse;
 import com.atmob.voiceai.data.consts.ErrorCode;
 import com.atmob.voiceai.data.consts.EventId;
@@ -79,6 +80,12 @@ public class MemberRepository {
         return credit;
     }
 
+    public Single<SplashPageResponse> requestSplashPage() {
+        return atmobApi.splashPage(new BaseRequest())
+                .compose(RxHttpHandler.handle(false))
+                .compose(RxJavaUtil.SingleSchedule.io2Main());
+    }
+
 
     public Single<Object> oneTimePurchaseResume() {
         return gpBillingClient.queryPurchase(BillingClient.ProductType.INAPP)
@@ -239,9 +246,9 @@ public class MemberRepository {
     }
 
 
-    private Single<UserInfoResponse> userInfo() {
+    public Single<UserInfoResponse> userInfo() {
         return atmobApi.userInfo(new BaseRequest())
-                .compose(RxHttpHandler.handle(true))
+                .compose(RxHttpHandler.handle(false))
                 .retryWhen(RxJavaUtil.exponentialBackOff(null, 3, TimeUnit.SECONDS))
                 .compose(RxJavaUtil.SingleSchedule.io2Main())
                 .doOnSuccess(userInfoResponse -> {

+ 56 - 0
app/src/main/java/com/atmob/voiceai/module/newsplash/NewSplashActivity.java

@@ -0,0 +1,56 @@
+package com.atmob.voiceai.module.newsplash;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+import com.atmob.app.lib.base.BaseActivity;
+import com.atmob.voiceai.databinding.ActivityNewSplashBinding;
+import com.atmob.voiceai.module.main.MainActivity;
+
+import dagger.hilt.android.AndroidEntryPoint;
+
+
+@AndroidEntryPoint
+public class NewSplashActivity extends BaseActivity<ActivityNewSplashBinding> {
+
+
+    private NewSplashViewModel newSplashViewModel;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        initView();
+        initObserver();
+    }
+
+    private void initObserver() {
+        newSplashViewModel.getShowMainEvent().observe(this, o -> goMain());
+    }
+
+    private void initView() {
+    }
+
+
+    @Override
+    protected boolean shouldImmersion() {
+        return true;
+    }
+
+    @Override
+    protected void initViewModel() {
+        super.initViewModel();
+        newSplashViewModel = getViewModelProvider().get(NewSplashViewModel.class);
+        binding.setNewSplashViewModel(newSplashViewModel);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+    }
+
+    private void goMain() {
+        MainActivity.start(this);
+        finish();
+    }
+}

+ 153 - 0
app/src/main/java/com/atmob/voiceai/module/newsplash/NewSplashViewModel.java

@@ -0,0 +1,153 @@
+package com.atmob.voiceai.module.newsplash;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+
+import com.android.billingclient.api.BillingClient;
+import com.atmob.app.lib.base.BaseViewModel;
+import com.atmob.app.lib.livedata.SingleLiveEvent;
+import com.atmob.voiceai.data.api.bean.SplashPageBean;
+import com.atmob.voiceai.data.api.response.SplashPageResponse;
+import com.atmob.voiceai.data.api.response.UserInfoResponse;
+import com.atmob.voiceai.data.consts.Constants;
+import com.atmob.voiceai.data.repositories.MemberRepository;
+import com.atmob.voiceai.sdk.billing.GPBillingClient;
+import com.atmob.voiceai.utils.BoxingUtil;
+import com.atmob.voiceai.utils.CommonUtils;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+
+import atmob.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
+import atmob.reactivex.rxjava3.annotations.NonNull;
+import atmob.reactivex.rxjava3.core.SingleObserver;
+import atmob.reactivex.rxjava3.disposables.Disposable;
+import atmob.reactivex.rxjava3.schedulers.Schedulers;
+import atmob.rxjava.utils.RxJavaUtil;
+import dagger.hilt.android.lifecycle.HiltViewModel;
+
+
+@HiltViewModel
+public class NewSplashViewModel extends BaseViewModel {
+
+    private final SingleLiveEvent<?> showMainEvent = new SingleLiveEvent<>();
+    private final MutableLiveData<Boolean> isShowRecommendPage = new MutableLiveData<>(false);
+    private final MutableLiveData<SplashPageBean> splashGoods = new MutableLiveData<>();
+    private final MutableLiveData<Boolean> isShowCloseBtn = new MutableLiveData<>();
+    private final MemberRepository memberRepository;
+    private final GPBillingClient gpBillingClient;
+    private long requestStartTime;
+    private final Handler handler = new Handler(Looper.getMainLooper());
+
+    private final long MAX_NET_REQUEST_TIME = 3000;
+    private final long MAX_NET_ERROR_TIME = 8000;
+
+
+    @Inject
+    public NewSplashViewModel(MemberRepository memberRepository, GPBillingClient gpBillingClient) {
+        this.memberRepository = memberRepository;
+        this.gpBillingClient = gpBillingClient;
+        refreshUserInfo();
+    }
+
+    public LiveData<Boolean> getIsShowCloseBtn() {
+        return isShowCloseBtn;
+    }
+
+    public LiveData<?> getShowMainEvent() {
+        return showMainEvent;
+    }
+
+
+    private void refreshUserInfo() {
+        memberRepository.userInfo()
+                .timeout(MAX_NET_ERROR_TIME, TimeUnit.MILLISECONDS)
+                .onErrorReturn(throwable -> new UserInfoResponse())
+                .map(userInfoResponse -> {
+                    refreshSplashGoods();
+                    return userInfoResponse != null && userInfoResponse.getMemberInfo() != null && userInfoResponse.getMemberInfo().isIsMember();
+                })
+                .subscribe(new SingleObserver<Boolean>() {
+                    @Override
+                    public void onSubscribe(@NonNull Disposable d) {
+                        addDisposable(d);
+                        requestStartTime = SystemClock.elapsedRealtime();
+                    }
+
+                    @Override
+                    public void onSuccess(@NonNull Boolean isMember) {
+                        long consumeTime = MAX_NET_REQUEST_TIME - (SystemClock.elapsedRealtime() - requestStartTime);
+                        if (BoxingUtil.boxing(isMember)) {
+                            startDelayTask(consumeTime, showMainEvent::call);
+                        } else {
+                            startDelayTask(consumeTime, () -> {
+                                isShowRecommendPage.setValue(true);
+                                addDisposable(RxJavaUtil.timer(3000, TimeUnit.MILLISECONDS, () -> isShowCloseBtn.setValue(true)));
+                            });
+                        }
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+
+                    }
+                });
+    }
+
+
+    private void refreshSplashGoods() {
+        memberRepository.requestSplashPage()
+                .map(SplashPageResponse::getItem)
+                .flatMap(splashPageBean ->
+                        gpBillingClient.queryGoodsDetails(BillingClient.ProductType.SUBS,
+                                        splashPageBean.getGoogleProductId(), splashPageBean.getPlanId(), splashPageBean.getLowGoogleProductId())
+                                .map(gPProductInfo -> {
+                                    splashPageBean.setGpProductInfo(gPProductInfo);
+                                    return splashPageBean;
+                                })
+                                .subscribeOn(Schedulers.io())
+                                .onErrorReturn(throwable -> splashPageBean))
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new SingleObserver<SplashPageBean>() {
+                    @Override
+                    public void onSubscribe(@NonNull Disposable d) {
+                        addDisposable(d);
+                    }
+
+                    @Override
+                    public void onSuccess(@NonNull SplashPageBean splashPageBean) {
+                        splashGoods.setValue(splashPageBean);
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable e) {
+
+                    }
+                });
+    }
+
+    private void startDelayTask(long delayTime, Runnable runnable) {
+        handler.postDelayed(runnable, delayTime);
+    }
+
+    public LiveData<Boolean> getIsShowRecommendPage() {
+        return isShowRecommendPage;
+    }
+
+    public void onTermsClick() {
+        CommonUtils.startWeb(Constants.USER_AGREEMENT);
+    }
+
+    public void onPrivacyPolicyClick() {
+        CommonUtils.startWeb(Constants.PRIVACY_POLICY);
+    }
+
+    public void onBackClick() {
+        showMainEvent.call();
+    }
+}

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


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


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


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


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


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


+ 23 - 0
app/src/main/res/drawable/bg_new_splash_introduce.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="20dp" />
+            <gradient
+                android:endColor="#12F25D"
+                android:startColor="#0594D7" />
+        </shape>
+    </item>
+
+    <item
+        android:bottom="1dp"
+        android:left="1dp"
+        android:right="1dp"
+        android:top="1dp">
+        <shape android:shape="rectangle">
+            <corners android:radius="20dp" />
+            <solid android:color="@color/colorPrimary" />
+        </shape>
+    </item>
+</layer-list>

+ 23 - 0
app/src/main/res/drawable/bg_splash_progress_bar_horizontal.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@android:id/background">
+        <shape>
+            <corners android:radius="100dp" />
+            <gradient
+                android:angle="90"
+                android:endColor="#D9D9D9"
+                android:startColor="#D9D9D9" />
+        </shape>
+    </item>
+    <item android:id="@android:id/progress">
+        <scale android:scaleWidth="100%">
+            <shape>
+                <corners android:radius="100dp" />
+                <gradient
+                    android:angle="0"
+                    android:endColor="#16C6FD"
+                    android:startColor="#03FFA7" />
+            </shape>
+        </scale>
+    </item>
+</layer-list>

+ 1 - 1
app/src/main/res/drawable/bg_theme_splash.xml

@@ -13,7 +13,7 @@
         <bitmap android:src="@drawable/bg_splash_bottom" />
     </item>
 
-    <item android:top="567px">
+    <item android:top="450px">
         <bitmap
             android:gravity="center|top"
             android:src="@drawable/ic_splash_logo" />

+ 277 - 0
app/src/main/res/layout/activity_new_splash.xml

@@ -0,0 +1,277 @@
+<?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="newSplashViewModel"
+            type="com.atmob.voiceai.module.newsplash.NewSplashViewModel" />
+
+        <import type="com.atmob.common.ui.SizeUtil" />
+    </data>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+
+        <com.airbnb.lottie.LottieAnimationView
+            isGone="@{newSplashViewModel.isShowRecommendPage}"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintDimensionRatio="1:1"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintVertical_bias="0.6657608695652174"
+            app:layout_constraintWidth_percent="0.8"
+            app:lottie_autoPlay="true"
+            app:lottie_fileName="anim/splash_loading.zip"
+            app:lottie_loop="true" />
+
+
+        <androidx.constraintlayout.widget.ConstraintLayout
+            isGone="@{!newSplashViewModel.isShowRecommendPage}"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/colorPrimary">
+
+            <ImageView
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:src="@drawable/bg_new_splash_header"
+                app:layout_constraintDimensionRatio="1080:936"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <androidx.core.widget.NestedScrollView
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                app:layout_constrainedHeight="true"
+                app:layout_constraintBottom_toTopOf="@+id/tv_auto_renewable"
+                app:layout_constraintTop_toTopOf="parent">
+
+
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent">
+
+                    <Space
+                        android:id="@+id/space_status_bar"
+                        android:layout_width="match_parent"
+                        android:layout_height="@{SizeUtil.getStatusBarHeight(), default=@dimen/app_status_bar_height}"
+                        app:layout_constraintTop_toTopOf="parent" />
+
+                    <Space
+                        android:id="@+id/space1"
+                        android:layout_width="match_parent"
+                        android:layout_height="0dp"
+                        app:layout_constraintDimensionRatio="360:16"
+                        app:layout_constraintTop_toBottomOf="@+id/space_status_bar" />
+
+                    <ImageView
+                        android:onClick="@{()-> newSplashViewModel.onBackClick()}"
+                        isInvisible="@{!newSplashViewModel.isShowCloseBtn}"
+                        android:id="@+id/iv_close"
+                        android:layout_width="0dp"
+                        android:layout_height="0dp"
+                        android:layout_marginStart="14dp"
+                        android:src="@drawable/icon_new_splash_close"
+                        app:layout_constraintDimensionRatio="1:1"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toBottomOf="@+id/space1"
+                        app:layout_constraintWidth_percent="0.1" />
+
+                    <Space
+                        android:id="@+id/space2"
+                        android:layout_width="match_parent"
+                        android:layout_height="0dp"
+                        app:layout_constraintDimensionRatio="360:33"
+                        app:layout_constraintTop_toBottomOf="@+id/iv_close" />
+
+                    <ImageView
+                        android:id="@+id/iv_logo"
+                        android:layout_width="0dp"
+                        android:layout_height="0dp"
+                        android:src="@drawable/ic_splash_logo"
+                        app:layout_constraintDimensionRatio="421:277"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toBottomOf="@+id/space2"
+                        app:layout_constraintWidth_percent="0.3888888888888889" />
+
+                    <TextView
+                        android:id="@+id/tv_title"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="12dp"
+                        android:text="@string/new_splash_title"
+                        android:textColor="@color/white80"
+                        android:textSize="14sp"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toBottomOf="@id/iv_logo" />
+
+                    <Space
+                        android:id="@+id/space3"
+                        android:layout_width="match_parent"
+                        android:layout_height="0dp"
+                        app:layout_constraintDimensionRatio="360:33"
+                        app:layout_constraintTop_toBottomOf="@+id/tv_title" />
+
+                    <LinearLayout
+                        android:id="@+id/ll_content"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:orientation="vertical"
+                        app:layout_constraintTop_toBottomOf="@+id/space3">
+
+                        <include
+                            introduceContent="@{@string/new_splash_unlimited_content}"
+                            introduceIcon="@{@drawable/icon_new_splash_unlimited}"
+                            introduceTitle="@{@string/new_splash_unlimited_title}"
+                            layout="@layout/layout_new_splash_introduce"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginBottom="10dp" />
+
+                        <include
+                            introduceContent="@{@string/new_splash_limits_content}"
+                            introduceIcon="@{@drawable/icon_new_splash_limits}"
+                            introduceTitle="@{@string/new_splash_limits_title}"
+                            layout="@layout/layout_new_splash_introduce"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginBottom="10dp" />
+
+                        <include
+                            introduceContent="@{@string/new_splash_turbo_content}"
+                            introduceIcon="@{@drawable/icon_new_splash_turbo}"
+                            introduceTitle="@{@string/new_splash_turbo_title}"
+                            layout="@layout/layout_new_splash_introduce"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginBottom="10dp" />
+
+                        <include
+                            introduceContent="@{@string/new_splash_no_ad_content}"
+                            introduceIcon="@{@drawable/icon_new_splash_no_ad}"
+                            introduceTitle="@{@string/new_splash_no_ad_title}"
+                            layout="@layout/layout_new_splash_introduce"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:layout_marginBottom="10dp" />
+                    </LinearLayout>
+
+                    <TextView
+                        android:id="@+id/tv_subscribe_price_desc"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:textColor="@color/white"
+                        android:textSize="20sp"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toBottomOf="@+id/ll_content"
+                        tools:text="US$ 3.99/Week" />
+
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="11dp"
+                        android:drawablePadding="5.5dp"
+                        android:textColor="#BEBFBE"
+                        android:textSize="12sp"
+                        app:drawableStartCompat="@drawable/icon_total_integration"
+                        app:layout_constraintEnd_toEndOf="@+id/tv_subscribe_price_desc"
+                        app:layout_constraintStart_toStartOf="@+id/tv_subscribe_price_desc"
+                        app:layout_constraintTop_toBottomOf="@+id/tv_subscribe_price_desc"
+                        tools:text="20000 renew yearly" />
+                </androidx.constraintlayout.widget.ConstraintLayout>
+
+            </androidx.core.widget.NestedScrollView>
+
+            <Space
+                android:id="@+id/space_bottom"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintDimensionRatio="360:22" />
+
+            <TextView
+                android:onClick="@{()-> newSplashViewModel.onTermsClick()}"
+                android:id="@+id/tv_terms_of_service"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/setting_terms_of_service"
+                android:textColor="@color/white80"
+                android:textSize="12sp"
+                app:layout_constraintBottom_toTopOf="@+id/space_bottom"
+                app:layout_constraintLeft_toLeftOf="parent"
+                app:layout_constraintRight_toLeftOf="@+id/tv_restore" />
+
+            <TextView
+                android:id="@+id/tv_restore"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/sub_restore"
+                android:textColor="@color/white80"
+                android:textSize="12sp"
+                app:layout_constraintBottom_toBottomOf="@+id/tv_terms_of_service"
+                app:layout_constraintLeft_toRightOf="@+id/tv_terms_of_service"
+                app:layout_constraintRight_toLeftOf="@+id/tv_privacy_policy"
+                app:layout_constraintTop_toTopOf="@+id/tv_terms_of_service" />
+
+            <TextView
+                android:onClick="@{()-> newSplashViewModel.onPrivacyPolicyClick()}"
+                android:id="@+id/tv_privacy_policy"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/setting_privacy_policy"
+                android:textColor="@color/white80"
+                android:textSize="12sp"
+                app:layout_constraintBottom_toBottomOf="@+id/tv_restore"
+                app:layout_constraintLeft_toRightOf="@+id/tv_restore"
+                app:layout_constraintRight_toRightOf="parent"
+                app:layout_constraintTop_toTopOf="@+id/tv_restore" />
+
+            <Space
+                android:id="@+id/space_bottom2"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                app:layout_constraintBottom_toTopOf="@+id/tv_terms_of_service"
+                app:layout_constraintDimensionRatio="360:10" />
+
+            <TextView
+                android:id="@+id/tv_continue"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginHorizontal="@dimen/app_common_page_horizontal_padding"
+                android:background="@drawable/bg_voice_ai_btn"
+                android:gravity="center"
+                android:text="@string/splash_continue"
+                android:textColor="@color/colorPrimary"
+                android:textSize="17sp"
+                android:textStyle="bold"
+                app:layout_constraintBottom_toTopOf="@+id/space_bottom2"
+                app:layout_constraintDimensionRatio="336:48" />
+
+            <TextView
+                android:id="@+id/tv_auto_renewable"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="8dp"
+                android:text="@string/splash_aunto_renewable"
+                android:textColor="@color/white70"
+                android:textSize="12sp"
+                app:layout_constraintBottom_toTopOf="@+id/tv_continue"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</layout>

+ 74 - 0
app/src/main/res/layout/layout_new_splash_introduce.xml

@@ -0,0 +1,74 @@
+<?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="introduceIcon"
+            type="android.graphics.drawable.Drawable" />
+
+        <variable
+            name="introduceTitle"
+            type="String" />
+
+        <variable
+            name="introduceContent"
+            type="String" />
+    </data>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <View
+            android:id="@+id/v_bg"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginHorizontal="16dp"
+            android:background="@drawable/bg_new_splash_introduce"
+            app:layout_constraintDimensionRatio="328:68"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <ImageView
+            android:id="@+id/iv_introduce_icon"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginStart="13dp"
+            app:layout_constraintBottom_toBottomOf="@+id/v_bg"
+            app:layout_constraintDimensionRatio="1:1"
+            app:layout_constraintStart_toStartOf="@id/v_bg"
+            app:layout_constraintTop_toTopOf="@+id/v_bg"
+            app:layout_constraintWidth_percent="0.0722222222222222"
+            tools:src="@drawable/icon_new_splash_unlimited" />
+
+        <TextView
+            android:id="@+id/tv_introduce_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="11dp"
+            android:text="@{introduceTitle}"
+            android:textColor="@color/white"
+            android:textSize="20sp"
+            app:layout_constraintBottom_toTopOf="@+id/tv_introduce_content"
+            app:layout_constraintStart_toEndOf="@+id/iv_introduce_icon"
+            app:layout_constraintTop_toTopOf="@+id/iv_introduce_icon"
+            app:layout_constraintVertical_chainStyle="packed"
+            tools:text="unlimited Voices" />
+
+        <TextView
+            android:id="@+id/tv_introduce_content"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="4dp"
+            android:text="@{introduceContent}"
+            android:textColor="@color/white70"
+            android:textSize="12sp"
+            app:layout_constraintBottom_toBottomOf="@+id/iv_introduce_icon"
+            app:layout_constraintStart_toStartOf="@+id/tv_introduce_title"
+            app:layout_constraintTop_toBottomOf="@+id/tv_introduce_title"
+            tools:text="Select any voice you want" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</layout>

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

@@ -131,4 +131,15 @@
     <string name="integral_buy_now">Buy Now</string>
     <string name="integral_tips">-Purchased top up credits do not expire,but it can only be used on current devices;\n-Prioritize the use of points earned from subscriptions\n-Purchased top up credits require an active subscription to use.</string>
     <string name="onetime_purchase_success">Success</string>
+    <string name="new_splash_title">Very realistic and easy to use AI voice tool</string>
+    <string name="new_splash_unlimited_title">unlimited Voices</string>
+    <string name="new_splash_unlimited_content">Select any voice you want</string>
+    <string name="new_splash_limits_title">NO Limits</string>
+    <string name="new_splash_limits_content">Have unlimited Text</string>
+    <string name="new_splash_turbo_title">Turbo Processing</string>
+    <string name="new_splash_turbo_content">Get your Voice in seconds</string>
+    <string name="new_splash_no_ad_title">NO Ads</string>
+    <string name="new_splash_no_ad_content">Block advertisements</string>
+    <string name="splash_aunto_renewable">Aunto Renewable. Cancel Anytime</string>
+
 </resources>