feat:初步搭建google隔离架构
This commit is contained in:
@@ -303,6 +303,8 @@ dependencies {
|
||||
implementation 'com.contrarywind:wheelview:4.1.0'
|
||||
|
||||
implementation 'tech.sud.mgp:SudMGP-static:1.3.3.1158'
|
||||
|
||||
implementation project(':modules:module_google')
|
||||
}
|
||||
|
||||
channel {
|
||||
|
@@ -14,8 +14,9 @@ import android.util.Log;
|
||||
|
||||
import androidx.multidex.MultiDex;
|
||||
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.bumptech.glide.request.target.ViewTarget;
|
||||
import com.chuhai.utils.LanguageUtils;
|
||||
import com.example.lib_utils.LanguageUtils;
|
||||
import com.coorchice.library.utils.LogUtils;
|
||||
import com.facebook.stetho.Stetho;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
@@ -208,6 +209,13 @@ public class XChatApplication extends BaseApp {
|
||||
|
||||
initEnv();
|
||||
|
||||
// ARouter
|
||||
if (isDebug()) { // These two lines must be written before init, otherwise these configurations will be invalid in the init process
|
||||
ARouter.openLog(); // Print log
|
||||
ARouter.openDebug(); // Turn on debugging mode (If you are running in InstantRun mode, you must turn on debug mode! Online version needs to be closed, otherwise there is a security risk)
|
||||
}
|
||||
ARouter.init(application); // As early as possible, it is recommended to initialize in the Application
|
||||
|
||||
//延迟初始化云信
|
||||
NIMClient.init(context, null, options());
|
||||
|
||||
|
@@ -16,18 +16,18 @@ import android.view.WindowManager
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.android.billingclient.api.BillingClient
|
||||
import com.android.billingclient.api.BillingResult
|
||||
import com.android.billingclient.api.ProductDetails
|
||||
import com.android.billingclient.api.Purchase
|
||||
import com.appsflyer.AFInAppEventParameterName
|
||||
import com.appsflyer.AFInAppEventType
|
||||
import com.appsflyer.AppsFlyerLib
|
||||
import com.example.module_base.support.billing.IBillingResult
|
||||
import com.example.module_base.support.billing.IBillingService
|
||||
import com.example.module_base.support.billing.IProductDetails
|
||||
import com.example.module_base.support.billing.IPurchase
|
||||
import com.example.module_base.support.google.IGoogleService
|
||||
import com.netease.nim.uikit.common.util.sys.ScreenUtil
|
||||
import com.yizhuan.habu.R
|
||||
import com.yizhuan.habu.base.BaseViewBindingActivity
|
||||
import com.yizhuan.habu.databinding.DialogFirstChargeBinding
|
||||
import com.yizhuan.habu.ui.pay.BillingManager
|
||||
import com.yizhuan.habu.ui.setting.ModifyPwdActivity
|
||||
import com.yizhuan.habu.ui.webview.CommonWebViewActivity
|
||||
import com.yizhuan.habu.ui.widget.magicindicator.buildins.UIUtil
|
||||
@@ -56,14 +56,14 @@ import org.greenrobot.eventbus.ThreadMode
|
||||
* desc: 限时首充
|
||||
*/
|
||||
class FirstChargeDialog : BaseViewBindingActivity<DialogFirstChargeBinding>(),
|
||||
BillingManager.BillingUpdatesListener {
|
||||
IBillingService.Listener {
|
||||
|
||||
private var goodsList: List<FirstChargeGoods>? = null
|
||||
|
||||
private var currGoods: FirstChargeGoods? = null
|
||||
|
||||
private lateinit var helpPopupWindow: PopupWindow
|
||||
private var billingManager: BillingManager? = null
|
||||
private var billingManager: IBillingService? = null
|
||||
private var position = -1
|
||||
|
||||
private val mReward2Adapter by lazy { Reward2Adapter() }
|
||||
@@ -220,7 +220,7 @@ class FirstChargeDialog : BaseViewBindingActivity<DialogFirstChargeBinding>(),
|
||||
}
|
||||
|
||||
private fun initBilling() {
|
||||
billingManager = BillingManager(this, this)
|
||||
billingManager = IGoogleService.newBillingService(this,this)
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@@ -234,50 +234,53 @@ class FirstChargeDialog : BaseViewBindingActivity<DialogFirstChargeBinding>(),
|
||||
for (bean in goodsList) {
|
||||
productKeys.add(bean.chargeProdId)
|
||||
}
|
||||
billingManager?.querySkuDetailsAsync(productKeys) { billingResult: BillingResult, productDetails: MutableList<ProductDetails> ->
|
||||
if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Unsuccessful query for type: " + BillingClient.ProductType.INAPP + ". Error code: " + billingResult.responseCode
|
||||
)
|
||||
return@querySkuDetailsAsync
|
||||
}
|
||||
if (productDetails.isNotEmpty()) {
|
||||
for (chargeBean in goodsList) {
|
||||
for (skuDetails in productDetails) {
|
||||
if (skuDetails.productId == chargeBean.chargeProdId) {
|
||||
chargeBean.productDetails = skuDetails
|
||||
break
|
||||
billingManager?.querySkuDetailsAsync(productKeys,object :IBillingService.ProductDetailsResponseListener{
|
||||
override fun onProductDetailsResponse(
|
||||
billingResult: IBillingResult,
|
||||
productDetails: List<IProductDetails>
|
||||
) {
|
||||
if (!billingResult.isResponseOk()) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Unsuccessful query for Error code: " + billingResult.getResponseCode()
|
||||
)
|
||||
}else if (productDetails.isNotEmpty()) {
|
||||
for (chargeBean in goodsList) {
|
||||
for (skuDetails in productDetails) {
|
||||
if (skuDetails.getProductId() == chargeBean.chargeProdId) {
|
||||
chargeBean.productDetails = skuDetails
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/*商品更新回调*/
|
||||
@SuppressLint("CheckResult")
|
||||
override fun onPurchasesUpdated(purchases: List<Purchase>) {
|
||||
override fun onPurchasesUpdated(purchases: List<IPurchase>) {
|
||||
for (purchase in purchases) {
|
||||
if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED &&
|
||||
purchase.accountIdentifiers != null
|
||||
if (purchase.isPurchasedState() &&
|
||||
purchase.getAccountIdentifiers() != null
|
||||
) {
|
||||
PayModel.get().verifyOrder(
|
||||
purchase.accountIdentifiers!!.obfuscatedAccountId,
|
||||
purchase.products[0],
|
||||
purchase.packageName,
|
||||
purchase.purchaseToken
|
||||
purchase.getAccountIdentifiers()!!.getObfuscatedAccountId(),
|
||||
purchase.getProducts()[0],
|
||||
purchase.getPackageName(),
|
||||
purchase.getPurchaseToken()
|
||||
)
|
||||
.compose(bindToLifecycle())
|
||||
.subscribe(
|
||||
{ token: String? ->
|
||||
{ token: String ->
|
||||
//L.i("token=" + token);
|
||||
billingManager?.consumeAsync(token)
|
||||
var skuDetails: ProductDetails? = null
|
||||
var skuDetails: IProductDetails? = null
|
||||
val goodList = goodsList
|
||||
if (!goodList.isNullOrEmpty()) {
|
||||
for (datum in goodList) {
|
||||
if (datum.chargeProdId == purchase.products[0]) {
|
||||
if (datum.chargeProdId == purchase.getProducts()[0]) {
|
||||
skuDetails = datum.productDetails
|
||||
break
|
||||
}
|
||||
@@ -288,12 +291,14 @@ class FirstChargeDialog : BaseViewBindingActivity<DialogFirstChargeBinding>(),
|
||||
HashMap()
|
||||
eventValue[AFInAppEventParameterName.CONTENT_TYPE] = "Gold"
|
||||
eventValue[AFInAppEventParameterName.QUANTITY] = 1
|
||||
eventValue[AFInAppEventParameterName.CONTENT_ID] = purchase.orderId!!
|
||||
eventValue[AFInAppEventParameterName.REVENUE] =
|
||||
skuDetails.oneTimePurchaseOfferDetails?.priceAmountMicros!! / 1000000f
|
||||
eventValue["Price"] = skuDetails.oneTimePurchaseOfferDetails?.formattedPrice!!
|
||||
eventValue[AFInAppEventParameterName.CURRENCY] =
|
||||
skuDetails.oneTimePurchaseOfferDetails?.priceCurrencyCode!!
|
||||
eventValue[AFInAppEventParameterName.CONTENT_ID] = purchase.getOrderId()!!
|
||||
skuDetails.getOneTimePurchaseOfferDetails()?.let {
|
||||
eventValue[AFInAppEventParameterName.REVENUE] =
|
||||
it.getPriceAmountMicros() / 1000000f
|
||||
eventValue["Price"] = it.getFormattedPrice()
|
||||
eventValue[AFInAppEventParameterName.CURRENCY] =
|
||||
it.getPriceCurrencyCode()
|
||||
}
|
||||
AppsFlyerLib.getInstance().logEvent(
|
||||
applicationContext,
|
||||
AFInAppEventType.PURCHASE,
|
||||
@@ -321,10 +326,10 @@ class FirstChargeDialog : BaseViewBindingActivity<DialogFirstChargeBinding>(),
|
||||
|
||||
/*购买商品*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun buyProduct(skuDetails: ProductDetails?) {
|
||||
fun buyProduct(skuDetails: IProductDetails?) {
|
||||
if (skuDetails != null) {
|
||||
Log.d(TAG, "BuyProduct:" + skuDetails.productId)
|
||||
PayModel.get().placeOrder(skuDetails.productId)
|
||||
Log.d(TAG, "BuyProduct:" + skuDetails.getProductId())
|
||||
PayModel.get().placeOrder(skuDetails.getProductId())
|
||||
.compose(bindToLifecycle())
|
||||
.subscribe(
|
||||
{ recordId: PayRecordId ->
|
||||
@@ -345,7 +350,7 @@ class FirstChargeDialog : BaseViewBindingActivity<DialogFirstChargeBinding>(),
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (billingManager?.isServiceConnected == true) {
|
||||
if (billingManager?.isServiceConnected() == true) {
|
||||
billingManager?.onQueryPurchases()
|
||||
}
|
||||
}
|
||||
|
@@ -6,8 +6,8 @@ import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.chuhai.utils.ServiceTime
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.example.lib_utils.ServiceTime
|
||||
import com.example.lib_utils.ktx.singleClick
|
||||
import com.yizhuan.habu.R
|
||||
import com.yizhuan.habu.avroom.redpackage.open.RedPackageOpenDialog
|
||||
import com.yizhuan.habu.common.widget.dialog.DialogManager
|
||||
|
@@ -11,12 +11,12 @@ import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.LinearInterpolator
|
||||
import androidx.core.view.isVisible
|
||||
import com.chuhai.utils.ServiceTime
|
||||
import com.chuhai.utils.ktx.getColorById
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.chuhai.utils.ktx.toStringRes
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.chuhai.utils.spannable.spannableBuilder
|
||||
import com.example.lib_utils.ServiceTime
|
||||
import com.example.lib_utils.ktx.getColorById
|
||||
import com.example.lib_utils.ktx.singleClick
|
||||
import com.example.lib_utils.ktx.toStringRes
|
||||
import com.example.lib_utils.log.ILog
|
||||
import com.example.lib_utils.spannable.spannableBuilder
|
||||
import com.trello.rxlifecycle3.android.FragmentEvent
|
||||
import com.yizhuan.habu.R
|
||||
import com.yizhuan.habu.avroom.redpackage.RedPackageHandler
|
||||
|
@@ -2,11 +2,11 @@ package com.yizhuan.habu.avroom.redpackage.send
|
||||
|
||||
import android.graphics.Color
|
||||
import androidx.core.view.isVisible
|
||||
import com.chuhai.utils.ktx.addDisableFilter
|
||||
import com.chuhai.utils.ktx.getColorById
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.chuhai.utils.ktx.toStringRes
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.example.lib_utils.ktx.addDisableFilter
|
||||
import com.example.lib_utils.ktx.getColorById
|
||||
import com.example.lib_utils.ktx.singleClick
|
||||
import com.example.lib_utils.ktx.toStringRes
|
||||
import com.example.lib_utils.log.ILog
|
||||
import com.yizhuan.habu.R
|
||||
import com.yizhuan.habu.base.BaseBindingFragment
|
||||
import com.yizhuan.habu.databinding.RedPackagePrivateFragmentBinding
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package com.yizhuan.habu.avroom.redpackage.send
|
||||
|
||||
import com.chuhai.utils.ktx.addDisableFilter
|
||||
import com.chuhai.utils.ktx.setOnInputChangedListener
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.chuhai.utils.ktx.toStringRes
|
||||
import com.example.lib_utils.ktx.addDisableFilter
|
||||
import com.example.lib_utils.ktx.setOnInputChangedListener
|
||||
import com.example.lib_utils.ktx.singleClick
|
||||
import com.example.lib_utils.ktx.toStringRes
|
||||
import com.yizhuan.habu.R
|
||||
import com.yizhuan.habu.base.BaseBindingFragment
|
||||
import com.yizhuan.habu.databinding.RedPackagePublicFragmentBinding
|
||||
|
@@ -6,8 +6,8 @@ import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.WindowManager
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.chuhai.utils.ktx.toStringRes
|
||||
import com.example.lib_utils.ktx.singleClick
|
||||
import com.example.lib_utils.ktx.toStringRes
|
||||
import com.yizhuan.habu.R
|
||||
import com.yizhuan.habu.avroom.redpackage.RedPackageEvent
|
||||
import com.yizhuan.habu.base.BaseDialog
|
||||
|
@@ -2,7 +2,7 @@ package com.yizhuan.habu.avroom.redpackage.send
|
||||
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter
|
||||
import com.chad.library.adapter.base.BaseViewHolder
|
||||
import com.chuhai.utils.ktx.getColorById
|
||||
import com.example.lib_utils.ktx.getColorById
|
||||
import com.yizhuan.habu.R
|
||||
import io.realm.internal.Keep
|
||||
|
||||
|
@@ -8,7 +8,6 @@ import android.widget.FrameLayout;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
import com.chuhai.utils.UiUtils;
|
||||
import com.yizhuan.habu.R;
|
||||
import com.yizhuan.habu.common.util.Utils;
|
||||
import com.yizhuan.habu.ui.widget.magicindicator.buildins.UIUtil;
|
||||
|
@@ -13,7 +13,7 @@ import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.chuhai.core.component.SuperBottomSheetDialog;
|
||||
import com.example.lib_core.component.SuperBottomSheetDialog;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import com.yizhuan.habu.R;
|
||||
import com.yizhuan.habu.common.util.Utils;
|
||||
|
@@ -15,8 +15,10 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.example.module_base.support.google.IGoogleService;
|
||||
import com.example.module_base.support.login.ILoginService;
|
||||
import com.netease.nim.uikit.StatusBarUtil;
|
||||
import com.netease.nim.uikit.common.util.log.LogUtil;
|
||||
import com.yizhuan.habu.upgrade.AppUpgradeHelper;
|
||||
import com.trello.rxlifecycle3.android.ActivityEvent;
|
||||
import com.yizhuan.habu.MainActivity;
|
||||
@@ -37,16 +39,11 @@ import com.yizhuan.xchat_android_core.auth.event.LoginReportEvent;
|
||||
import com.yizhuan.xchat_android_library.common.SpConstants;
|
||||
import com.yizhuan.xchat_android_library.common.util.SPUtils;
|
||||
import com.yizhuan.xchat_android_library.utils.AppMetaDataUtil;
|
||||
import com.yizhuan.xchat_android_library.utils.DeviceUtils;
|
||||
import com.yizhuan.xchat_android_library.utils.ResUtil;
|
||||
import com.yizhuan.xchat_android_library.utils.SingleToastUtil;
|
||||
import com.yizhuan.xchat_android_library.utils.constant.PackageNameConstants;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import io.reactivex.SingleObserver;
|
||||
@@ -79,7 +76,6 @@ public class LoginActivity extends BaseActivity implements View.OnClickListener
|
||||
HashMap<String, Object> map = new HashMap<>(2);
|
||||
map.put(IReportConstants.MODULE, IReportConstants.PEKO_LOGIN);
|
||||
ReportManager.get().reportEvent(IReportConstants.LOGIN_SHOW, map);
|
||||
|
||||
// callbackManager = CallbackManager.Factory.create();
|
||||
// LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
|
||||
// @Override
|
||||
@@ -288,7 +284,7 @@ public class LoginActivity extends BaseActivity implements View.OnClickListener
|
||||
case R.id.cs_google:
|
||||
reportLoginType(IReportConstants.THREE);
|
||||
getDialogManager().showProgressDialog(this);
|
||||
AuthModel.get().googleLogin()
|
||||
AuthModel.get().googleLogin(this)
|
||||
.compose(bindUntilEvent(ActivityEvent.DESTROY))
|
||||
.subscribe(new SingleObserver<String>() {
|
||||
@Override
|
||||
@@ -328,6 +324,7 @@ public class LoginActivity extends BaseActivity implements View.OnClickListener
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
AuthModel.get().getGoogleLoginService().onActivityResult(requestCode, resultCode, data);
|
||||
// callbackManager.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
|
@@ -1,222 +0,0 @@
|
||||
package com.yizhuan.habu.ui.pay;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.android.billingclient.api.BillingClient;
|
||||
import com.android.billingclient.api.BillingClient.BillingResponseCode;
|
||||
import com.android.billingclient.api.BillingClientStateListener;
|
||||
import com.android.billingclient.api.BillingFlowParams;
|
||||
import com.android.billingclient.api.BillingResult;
|
||||
import com.android.billingclient.api.ConsumeParams;
|
||||
import com.android.billingclient.api.ProductDetails;
|
||||
import com.android.billingclient.api.ProductDetailsResponseListener;
|
||||
import com.android.billingclient.api.Purchase;
|
||||
import com.android.billingclient.api.PurchasesUpdatedListener;
|
||||
import com.android.billingclient.api.QueryProductDetailsParams;
|
||||
import com.android.billingclient.api.QueryPurchasesParams;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BillingManager implements PurchasesUpdatedListener {
|
||||
|
||||
private static final String TAG = "BillingManager";
|
||||
|
||||
/*购买key*/
|
||||
private static final String BASE_64_ENCODED_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApNboVqeCAvW1s2mNCaNipu0bd15HC6FP86E1+dTEdMTD9XLWkYiXCzEbt+ciTda/XdAOYYe4YNnyfW7T/a9E7O0ZyjPj08q2LQaMqgTBecpzQhE7ZhYYmh3DdWrGKCEMLImX4yNuEEX9yC/dVP49nHNqfLWxmnzhDrJ5JDSlpvguOI4lMRe0/1gx7kfEeB8DOg8HfvdibiVZI4vhjk9Oz6sWJQZd1/bOuUe4huAj9Ys/4zcgniE8Da45lGdefjn12y7ELhcUZpFLLKvXmj0qnfqBX94CB+wfbEOYvALKaFb+bBZe/a8YEn/9zA4UsA0j+eRweXBb6e1AqaZJ4wp/JQIDAQAB";
|
||||
|
||||
/*客户端*/
|
||||
private BillingClient billingClient;
|
||||
|
||||
/*活动*/
|
||||
private final Activity mActivity;
|
||||
|
||||
/*监听*/
|
||||
private final BillingUpdatesListener mBillingUpdatesListener;
|
||||
|
||||
/*是否连接成功*/
|
||||
private boolean mIsServiceConnected;
|
||||
|
||||
/*商品列表*/
|
||||
private final List<Purchase> purchaseList = new ArrayList<>();
|
||||
|
||||
/*监听接口*/
|
||||
public interface BillingUpdatesListener {
|
||||
void onBillingClientSetupFinished();
|
||||
|
||||
void onPurchasesUpdated(List<Purchase> purchases);
|
||||
|
||||
void onConsumeFinished(String token, @BillingResponseCode int result);
|
||||
|
||||
void onFailedHandle(@BillingResponseCode int result);
|
||||
}
|
||||
|
||||
public boolean isServiceConnected() {
|
||||
return mIsServiceConnected;
|
||||
}
|
||||
|
||||
public BillingManager(Activity activity, final BillingUpdatesListener updatesListener) {
|
||||
mActivity = activity;
|
||||
mBillingUpdatesListener = updatesListener;
|
||||
billingClient = BillingClient.newBuilder(mActivity).enablePendingPurchases().setListener(this).build();
|
||||
startServiceConnection(() -> {
|
||||
mBillingUpdatesListener.onBillingClientSetupFinished();
|
||||
onQueryPurchases();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/*开始连接Play*/
|
||||
public void startServiceConnection(final Runnable executeOnSuccess) {
|
||||
billingClient.startConnection(new BillingClientStateListener() {
|
||||
@Override
|
||||
public void onBillingSetupFinished(@NotNull BillingResult billingResult) {
|
||||
Log.d(TAG, "Setup finished. Response code: " + billingResult.getDebugMessage() + " code = " + billingResult.getResponseCode());
|
||||
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
|
||||
mIsServiceConnected = true;
|
||||
if (executeOnSuccess != null) {
|
||||
executeOnSuccess.run();
|
||||
}
|
||||
} else {
|
||||
mIsServiceConnected = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBillingServiceDisconnected() {
|
||||
mIsServiceConnected = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*请求商品库存*/
|
||||
public void onQueryPurchases() {
|
||||
Runnable queryToExecute = () ->
|
||||
billingClient.queryPurchasesAsync(
|
||||
QueryPurchasesParams.newBuilder()
|
||||
.setProductType(BillingClient.ProductType.INAPP)
|
||||
.build(), this::onPurchasesUpdated);
|
||||
executeServiceRequest(queryToExecute);
|
||||
}
|
||||
|
||||
/*更新商品*/
|
||||
@Override
|
||||
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
|
||||
Log.i(TAG, "billingResult.getResponseCode()==" + billingResult.getResponseCode());
|
||||
purchaseList.clear();
|
||||
if (billingResult.getResponseCode() == BillingResponseCode.OK) {
|
||||
if (purchases != null) {
|
||||
for (Purchase purchase : purchases) {
|
||||
handlePurchase(purchase);
|
||||
}
|
||||
}
|
||||
mBillingUpdatesListener.onPurchasesUpdated(purchaseList);
|
||||
} else {
|
||||
if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
|
||||
} else {
|
||||
}
|
||||
mBillingUpdatesListener.onFailedHandle(billingResult.getResponseCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*商品处理*/
|
||||
private void handlePurchase(Purchase purchase) {
|
||||
//验证签名数据
|
||||
if (!verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature())) {
|
||||
return;
|
||||
}
|
||||
purchaseList.add(purchase);
|
||||
}
|
||||
|
||||
/*验证签名*/
|
||||
private boolean verifyValidSignature(String signedData, String signature) {
|
||||
try {
|
||||
return Security.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, signedData, signature);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Got an exception trying to validate a purchase: " + e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*执行服务请求*/
|
||||
private void executeServiceRequest(Runnable runnable) {
|
||||
if (mIsServiceConnected) {
|
||||
runnable.run();
|
||||
} else {
|
||||
startServiceConnection(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
/*查询内购商品详情*/
|
||||
public void querySkuDetailsAsync(final List<String> productIdList,
|
||||
final ProductDetailsResponseListener listener) {
|
||||
Runnable queryRequest = () -> {
|
||||
ArrayList<QueryProductDetailsParams.Product> products = new ArrayList<>();
|
||||
for (String productId : productIdList) {
|
||||
products.add(QueryProductDetailsParams.Product.newBuilder()
|
||||
.setProductId(productId)
|
||||
.setProductType(BillingClient.ProductType.INAPP)
|
||||
.build());
|
||||
}
|
||||
QueryProductDetailsParams queryProductDetailsParams =
|
||||
QueryProductDetailsParams.newBuilder()
|
||||
.setProductList(products)
|
||||
.build();
|
||||
|
||||
billingClient.queryProductDetailsAsync(
|
||||
queryProductDetailsParams,
|
||||
listener
|
||||
);
|
||||
};
|
||||
executeServiceRequest(queryRequest);
|
||||
}
|
||||
|
||||
/*启动购买,订购流程*/
|
||||
public void initiatePurchaseFlow(final ProductDetails productDetails, String recordId) {
|
||||
Runnable purchaseFlowRequest = () -> {
|
||||
BillingFlowParams.ProductDetailsParams p = BillingFlowParams.ProductDetailsParams.newBuilder()
|
||||
.setProductDetails(productDetails)
|
||||
.build();
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
ProductDetails.OneTimePurchaseOfferDetails oneTimePurchaseOfferDetails = productDetails.getOneTimePurchaseOfferDetails();
|
||||
if (oneTimePurchaseOfferDetails != null) {
|
||||
jsonObject.put("p", oneTimePurchaseOfferDetails.getFormattedPrice());
|
||||
jsonObject.put("a", oneTimePurchaseOfferDetails.getPriceAmountMicros() / 10000);
|
||||
jsonObject.put("c", oneTimePurchaseOfferDetails.getPriceCurrencyCode());
|
||||
}
|
||||
BillingFlowParams purchaseParams = BillingFlowParams.newBuilder()
|
||||
.setObfuscatedAccountId(recordId)
|
||||
.setObfuscatedProfileId(jsonObject.toJSONString())
|
||||
.setProductDetailsParamsList(List.of(p))
|
||||
.build();
|
||||
BillingResult billingResult = billingClient.launchBillingFlow(mActivity, purchaseParams);
|
||||
Log.i(TAG, " initiatePurchaseFlow billingResult=" + billingResult.getResponseCode() + " " + billingResult.getDebugMessage());
|
||||
};
|
||||
executeServiceRequest(purchaseFlowRequest);
|
||||
}
|
||||
|
||||
public void consumeAsync(final String purchaseToken) {
|
||||
final ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken).build();
|
||||
|
||||
executeServiceRequest(() -> billingClient.consumeAsync(consumeParams, (billingResult, s) ->
|
||||
mBillingUpdatesListener.onConsumeFinished(purchaseToken, billingResult.getResponseCode())));
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁结算客户端并断开连接
|
||||
*/
|
||||
public void destroy() {
|
||||
Log.d(TAG, "Destroying the manager.");
|
||||
if (billingClient != null && billingClient.isReady()) {
|
||||
billingClient.endConnection();
|
||||
billingClient = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -19,16 +19,18 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.billingclient.api.BillingClient;
|
||||
import com.android.billingclient.api.ProductDetails;
|
||||
import com.android.billingclient.api.Purchase;
|
||||
import com.appsflyer.AFInAppEventParameterName;
|
||||
import com.appsflyer.AFInAppEventType;
|
||||
import com.appsflyer.AppsFlyerLib;
|
||||
import com.example.module_base.support.billing.IBillingService;
|
||||
import com.example.module_base.support.billing.IProductDetails;
|
||||
import com.example.module_base.support.billing.IPurchase;
|
||||
import com.example.module_base.support.google.IGoogleService;
|
||||
import com.netease.nim.uikit.StatusBarUtil;
|
||||
import com.yizhuan.habu.R;
|
||||
import com.yizhuan.habu.application.IReportConstants;
|
||||
@@ -70,7 +72,7 @@ import java.util.Map;
|
||||
*/
|
||||
@CreatePresenter(ChargePresenter.class)
|
||||
public class ChargeActivity extends BaseMvpActivity<IChargeView, ChargePresenter>
|
||||
implements IChargeView, BillingManager.BillingUpdatesListener {
|
||||
implements IChargeView, IBillingService.Listener {
|
||||
private static final String TAG = "ChargeActivity";
|
||||
|
||||
private TextView mTv_gold;
|
||||
@@ -83,7 +85,7 @@ public class ChargeActivity extends BaseMvpActivity<IChargeView, ChargePresenter
|
||||
|
||||
private final int BINDCODE_GOLD = 200;
|
||||
|
||||
private BillingManager billingManager;
|
||||
private IBillingService billingManager;
|
||||
|
||||
private int mChargePosition = -1;
|
||||
|
||||
@@ -166,7 +168,7 @@ public class ChargeActivity extends BaseMvpActivity<IChargeView, ChargePresenter
|
||||
|
||||
/*初始化*/
|
||||
public void initBilling() {
|
||||
billingManager = new BillingManager(this, this);
|
||||
billingManager = IGoogleService.Companion.newBillingService(this, this);
|
||||
}
|
||||
|
||||
/*客户端设置成功回调*/
|
||||
@@ -186,17 +188,19 @@ public class ChargeActivity extends BaseMvpActivity<IChargeView, ChargePresenter
|
||||
productKeys.add(chargeBean.getChargeProdId());
|
||||
}
|
||||
mChargeAdapter.setNewData(chargeBeanList);
|
||||
if (billingManager == null) {
|
||||
return;
|
||||
}
|
||||
billingManager.querySkuDetailsAsync(productKeys, (billingResult, productDetails) -> {
|
||||
if (billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK) {
|
||||
Log.w(TAG, "Unsuccessful query for type: " + BillingClient.ProductType.INAPP
|
||||
+ ". Error code: " + billingResult.getResponseCode());
|
||||
if (!billingResult.isResponseOk()) {
|
||||
Log.w(TAG, "Unsuccessful query for Error code: " + billingResult.getResponseCode());
|
||||
getDialogManager().dismissDialog();
|
||||
toast(getString(R.string.Recharge_failure));
|
||||
} else if (productDetails.size() > 0) {
|
||||
getDialogManager().dismissDialog();
|
||||
List<ChargeBean> showChargeList = new ArrayList<>();
|
||||
for (ChargeBean chargeBean : chargeBeanList) {
|
||||
for (ProductDetails product : productDetails) {
|
||||
for (IProductDetails product : productDetails) {
|
||||
if (product.getProductId().equals(chargeBean.getChargeProdId())) {
|
||||
chargeBean.setProductDetails(product);
|
||||
showChargeList.add(chargeBean);
|
||||
@@ -212,12 +216,13 @@ public class ChargeActivity extends BaseMvpActivity<IChargeView, ChargePresenter
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*商品更新回调*/
|
||||
@SuppressLint("CheckResult")
|
||||
@Override
|
||||
public void onPurchasesUpdated(List<Purchase> purchases) {
|
||||
for (Purchase purchase : purchases) {
|
||||
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED &&
|
||||
public void onPurchasesUpdated(@Nullable List<? extends IPurchase> purchases) {
|
||||
for (IPurchase purchase : purchases) {
|
||||
if (purchase.isPurchasedState() &&
|
||||
purchase.getAccountIdentifiers() != null) {
|
||||
PayModel.get().verifyOrder(
|
||||
purchase.getAccountIdentifiers().getObfuscatedAccountId(),
|
||||
@@ -228,7 +233,7 @@ public class ChargeActivity extends BaseMvpActivity<IChargeView, ChargePresenter
|
||||
.subscribe(token -> {
|
||||
billingManager.consumeAsync(token);
|
||||
|
||||
ProductDetails productDetails = null;
|
||||
IProductDetails productDetails = null;
|
||||
for (ChargeBean datum : mChargeAdapter.getData()) {
|
||||
if (datum.getChargeProdId().equals(purchase.getProducts().get(0))) {
|
||||
productDetails = datum.getProductDetails();
|
||||
@@ -240,9 +245,11 @@ public class ChargeActivity extends BaseMvpActivity<IChargeView, ChargePresenter
|
||||
eventValue.put(AFInAppEventParameterName.CONTENT_TYPE, "Gold");
|
||||
eventValue.put(AFInAppEventParameterName.QUANTITY, 1);
|
||||
eventValue.put(AFInAppEventParameterName.CONTENT_ID, purchase.getOrderId());
|
||||
eventValue.put(AFInAppEventParameterName.REVENUE, productDetails.getOneTimePurchaseOfferDetails().getPriceAmountMicros() / 1000000f);
|
||||
eventValue.put("Price", productDetails.getOneTimePurchaseOfferDetails().getFormattedPrice());
|
||||
eventValue.put(AFInAppEventParameterName.CURRENCY, productDetails.getOneTimePurchaseOfferDetails().getPriceCurrencyCode());
|
||||
if (productDetails.getOneTimePurchaseOfferDetails() != null) {
|
||||
eventValue.put(AFInAppEventParameterName.REVENUE, productDetails.getOneTimePurchaseOfferDetails().getPriceAmountMicros() / 1000000f);
|
||||
eventValue.put("Price", productDetails.getOneTimePurchaseOfferDetails().getFormattedPrice());
|
||||
eventValue.put(AFInAppEventParameterName.CURRENCY, productDetails.getOneTimePurchaseOfferDetails().getPriceCurrencyCode());
|
||||
}
|
||||
AppsFlyerLib.getInstance().logEvent(getApplicationContext(), AFInAppEventType.PURCHASE, eventValue);
|
||||
}
|
||||
},
|
||||
@@ -262,12 +269,15 @@ public class ChargeActivity extends BaseMvpActivity<IChargeView, ChargePresenter
|
||||
}
|
||||
|
||||
/*失败处理*/
|
||||
public void onFailedHandle(@BillingClient.BillingResponseCode int result) {
|
||||
public void onFailedHandle(int result) {
|
||||
}
|
||||
|
||||
/*购买商品*/
|
||||
@SuppressLint("CheckResult")
|
||||
public void buyProduct(ProductDetails productDetails) {
|
||||
public void buyProduct(IProductDetails productDetails) {
|
||||
if (billingManager == null) {
|
||||
return;
|
||||
}
|
||||
if (productDetails != null) {
|
||||
Log.d(TAG, "BuyProduct:" + productDetails.getProductId());
|
||||
PayModel.get().placeOrder(productDetails.getProductId())
|
||||
|
@@ -6,7 +6,7 @@ import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.text.SpannableString
|
||||
import android.view.View
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.example.lib_utils.log.ILog
|
||||
import com.netease.nim.uikit.StatusBarUtil
|
||||
import com.yizhuan.habu.upgrade.AppUpgradeHelper
|
||||
import com.yizhuan.habu.BuildConfig
|
||||
|
@@ -7,7 +7,7 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.chuhai.utils.UiUtils
|
||||
import com.example.lib_utils.UiUtils
|
||||
import com.yizhuan.habu.R
|
||||
import com.yizhuan.habu.ui.webview.CommonWebViewActivity
|
||||
import com.yizhuan.xchat_android_core.home.bean.BannerInfo
|
||||
|
@@ -7,7 +7,7 @@ import android.view.LayoutInflater
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.example.lib_utils.ktx.singleClick
|
||||
import com.yizhuan.habu.R
|
||||
import com.yizhuan.habu.avroom.activity.AVRoomActivity
|
||||
import com.yizhuan.habu.databinding.AllServiceGiftGoRoomTipsDialogBinding
|
||||
|
@@ -12,10 +12,10 @@ import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.chuhai.utils.ktx.getColorById
|
||||
import com.chuhai.utils.ktx.singleClick
|
||||
import com.chuhai.utils.ktx.toStringRes
|
||||
import com.chuhai.utils.spannable.SpannableTextBuilder
|
||||
import com.example.lib_utils.ktx.getColorById
|
||||
import com.example.lib_utils.ktx.singleClick
|
||||
import com.example.lib_utils.ktx.toStringRes
|
||||
import com.example.lib_utils.spannable.SpannableTextBuilder
|
||||
import com.yizhuan.habu.R
|
||||
import com.yizhuan.habu.avroom.activity.AVRoomActivity
|
||||
import com.yizhuan.habu.databinding.DialogGiftAllServiceLevelBinding
|
||||
|
@@ -16,7 +16,7 @@ import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.chuhai.utils.ServiceTime;
|
||||
import com.example.lib_utils.ServiceTime;
|
||||
import com.opensource.svgaplayer.SVGADrawable;
|
||||
import com.opensource.svgaplayer.SVGADynamicEntity;
|
||||
import com.opensource.svgaplayer.SVGAImageView;
|
||||
|
@@ -12,13 +12,14 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.android.billingclient.api.BillingClient
|
||||
import com.android.billingclient.api.BillingResult
|
||||
import com.android.billingclient.api.ProductDetails
|
||||
import com.android.billingclient.api.Purchase
|
||||
import com.appsflyer.AFInAppEventParameterName
|
||||
import com.appsflyer.AFInAppEventType
|
||||
import com.appsflyer.AppsFlyerLib
|
||||
import com.example.module_base.support.billing.IBillingResult
|
||||
import com.example.module_base.support.billing.IBillingService
|
||||
import com.example.module_base.support.billing.IProductDetails
|
||||
import com.example.module_base.support.billing.IPurchase
|
||||
import com.example.module_base.support.google.IGoogleService
|
||||
import com.netease.nim.uikit.StatusBarUtil
|
||||
import com.netease.nim.uikit.common.util.sys.TimeUtil
|
||||
import com.opensource.svgaplayer.SVGADrawable
|
||||
@@ -30,8 +31,6 @@ import com.yizhuan.habu.base.BaseViewBindingActivity
|
||||
import com.yizhuan.habu.base.TitleBar
|
||||
import com.yizhuan.habu.common.EmptyViewHelper
|
||||
import com.yizhuan.habu.databinding.ActivityVipMainBinding
|
||||
import com.yizhuan.habu.ui.pay.BillingManager
|
||||
import com.yizhuan.habu.ui.pay.BillingManager.BillingUpdatesListener
|
||||
import com.yizhuan.habu.ui.pay.ChargeActivity
|
||||
import com.yizhuan.habu.ui.setting.ModifyPwdActivity
|
||||
import com.yizhuan.habu.ui.utils.RVDelegate
|
||||
@@ -63,7 +62,7 @@ import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
|
||||
class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
|
||||
VipMagicIndicatorAdapter.OnItemSelectListener, BillingUpdatesListener {
|
||||
VipMagicIndicatorAdapter.OnItemSelectListener, IBillingService.Listener {
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -80,7 +79,7 @@ class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
|
||||
private val authAdapter = VipAuthAdapter()
|
||||
private lateinit var rvDelegate: RVDelegate<VipAuthInfo>
|
||||
private val vipViewModel: VipViewModel by viewModels()
|
||||
private var billingManager: BillingManager? = null
|
||||
private var billingManager: IBillingService? = null
|
||||
private var googleChargeBean: ChargeBean? = null//google
|
||||
private var chargeInfo: ChargeBean? = null//official
|
||||
|
||||
@@ -233,12 +232,15 @@ class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
|
||||
|
||||
binding.tvOpenVip.setOnClickListener {
|
||||
if (AppMetaDataUtil.getChannelID().equals(Constants.GOOGLE)) {
|
||||
if ((googleChargeBean?.productDetails?.oneTimePurchaseOfferDetails?.priceAmountMicros ?: "0") == "0") {
|
||||
if ((googleChargeBean?.productDetails?.getOneTimePurchaseOfferDetails()
|
||||
?.getPriceAmountMicros() ?: "0") == "0"
|
||||
) {
|
||||
toast(getString(R.string.Recharge_failure))
|
||||
return@setOnClickListener
|
||||
}
|
||||
SelectPayTypeDialog.newInstance(
|
||||
googleChargeBean?.productDetails?.oneTimePurchaseOfferDetails?.formattedPrice ?: "0",
|
||||
googleChargeBean?.productDetails?.getOneTimePurchaseOfferDetails()
|
||||
?.getFormattedPrice() ?: "0",
|
||||
true,
|
||||
googleChargeBean?.getMoney() ?: 0.0
|
||||
)
|
||||
@@ -311,7 +313,7 @@ class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
|
||||
}
|
||||
|
||||
private fun initBilling() {
|
||||
billingManager = BillingManager(this, this)
|
||||
billingManager = IGoogleService.newBillingService(this,this)
|
||||
}
|
||||
|
||||
override fun initWhiteTitleBar(title: String?) {
|
||||
@@ -396,31 +398,36 @@ class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
|
||||
chargeInfo?.let { chargeBean ->
|
||||
val productKeys: MutableList<String> = ArrayList()
|
||||
productKeys.add(chargeBean.getChargeProdId())
|
||||
billingManager?.querySkuDetailsAsync(productKeys) { billingResult: BillingResult, productDetails: List<ProductDetails> ->
|
||||
if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Unsuccessful query for type: " + BillingClient.SkuType.INAPP
|
||||
+ ". Error code: " + billingResult.responseCode
|
||||
)
|
||||
} else if (productDetails.isNotEmpty()) {
|
||||
val showChargeList: MutableList<ChargeBean> = ArrayList()
|
||||
for (skuDetails in productDetails) {
|
||||
if (skuDetails.productId == chargeBean.getChargeProdId()) {
|
||||
chargeBean.productDetails = skuDetails
|
||||
showChargeList.add(chargeBean)
|
||||
break
|
||||
billingManager?.querySkuDetailsAsync(productKeys,
|
||||
object : IBillingService.ProductDetailsResponseListener {
|
||||
override fun onProductDetailsResponse(
|
||||
billingResult: IBillingResult,
|
||||
productDetails: List<IProductDetails>
|
||||
) {
|
||||
if (!billingResult.isResponseOk()) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Unsuccessful query for Error code: " + billingResult.getResponseCode()
|
||||
)
|
||||
} else if (productDetails.isNotEmpty()) {
|
||||
val showChargeList: MutableList<ChargeBean> = ArrayList()
|
||||
for (skuDetails in productDetails) {
|
||||
if (skuDetails.getProductId() == chargeBean.getChargeProdId()) {
|
||||
chargeBean.productDetails = skuDetails
|
||||
showChargeList.add(chargeBean)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (showChargeList.size > 0) {
|
||||
googleChargeBean = showChargeList[0]
|
||||
binding.tvOpenVip.text = "${
|
||||
googleChargeBean?.getMoney()
|
||||
}${getString(R.string.me_immediately_become_a_Peko_nobleman)}"
|
||||
}
|
||||
}
|
||||
}
|
||||
if (showChargeList.size > 0) {
|
||||
googleChargeBean = showChargeList[0]
|
||||
binding.tvOpenVip.text = "${
|
||||
googleChargeBean?.getMoney()
|
||||
}${getString(R.string.me_immediately_become_a_Peko_nobleman)}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}, {
|
||||
it.printStackTrace()
|
||||
@@ -430,24 +437,26 @@ class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
|
||||
|
||||
/*商品更新回调*/
|
||||
@SuppressLint("CheckResult")
|
||||
override fun onPurchasesUpdated(purchases: List<Purchase>) {
|
||||
override fun onPurchasesUpdated(purchases: List<IPurchase>) {
|
||||
for (purchase in purchases) {
|
||||
if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED &&
|
||||
purchase.accountIdentifiers != null
|
||||
if (purchase.isPurchasedState() &&
|
||||
purchase.getAccountIdentifiers() != null
|
||||
) {
|
||||
PayModel.get().verifyOrder(
|
||||
purchase.accountIdentifiers!!.obfuscatedAccountId,
|
||||
purchase.products[0],
|
||||
purchase.packageName,
|
||||
purchase.purchaseToken
|
||||
purchase.getAccountIdentifiers()!!.getObfuscatedAccountId(),
|
||||
purchase.getProducts().firstOrNull(),
|
||||
purchase.getPackageName(),
|
||||
purchase.getPurchaseToken()
|
||||
)
|
||||
.compose(bindToLifecycle())
|
||||
.subscribe(
|
||||
{ token: String? ->
|
||||
{ token: String ->
|
||||
//L.i("token=" + token);
|
||||
billingManager?.consumeAsync(token)
|
||||
var skuDetails: ProductDetails? = null
|
||||
if (googleChargeBean?.getChargeProdId() == purchase.products[0]) {
|
||||
var skuDetails: IProductDetails? = null
|
||||
if (googleChargeBean?.getChargeProdId() == purchase.getProducts()
|
||||
.firstOrNull()
|
||||
) {
|
||||
skuDetails = googleChargeBean?.productDetails
|
||||
}
|
||||
if (skuDetails != null) {
|
||||
@@ -455,12 +464,19 @@ class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
|
||||
HashMap()
|
||||
eventValue[AFInAppEventParameterName.CONTENT_TYPE] = "Gold"
|
||||
eventValue[AFInAppEventParameterName.QUANTITY] = 1
|
||||
eventValue[AFInAppEventParameterName.CONTENT_ID] = purchase.orderId!!
|
||||
eventValue[AFInAppEventParameterName.REVENUE] =
|
||||
skuDetails.oneTimePurchaseOfferDetails?.priceAmountMicros!! / 1000000f
|
||||
eventValue["Price"] = skuDetails.oneTimePurchaseOfferDetails?.formattedPrice!!
|
||||
eventValue[AFInAppEventParameterName.CURRENCY] =
|
||||
skuDetails.oneTimePurchaseOfferDetails?.priceCurrencyCode!!
|
||||
eventValue[AFInAppEventParameterName.CONTENT_ID] =
|
||||
purchase.getOrderId()!!
|
||||
if (skuDetails.getOneTimePurchaseOfferDetails() != null) {
|
||||
eventValue[AFInAppEventParameterName.REVENUE] =
|
||||
skuDetails.getOneTimePurchaseOfferDetails()
|
||||
?.getPriceAmountMicros()!! / 1000000f
|
||||
eventValue["Price"] =
|
||||
skuDetails.getOneTimePurchaseOfferDetails()
|
||||
?.getFormattedPrice()!!
|
||||
eventValue[AFInAppEventParameterName.CURRENCY] =
|
||||
skuDetails.getOneTimePurchaseOfferDetails()
|
||||
?.getPriceCurrencyCode()!!
|
||||
}
|
||||
AppsFlyerLib.getInstance().logEvent(
|
||||
applicationContext,
|
||||
AFInAppEventType.PURCHASE,
|
||||
@@ -488,10 +504,10 @@ class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
|
||||
|
||||
/*购买商品*/
|
||||
@SuppressLint("CheckResult")
|
||||
fun buyProduct(productDetails: ProductDetails?) {
|
||||
fun buyProduct(productDetails: IProductDetails?) {
|
||||
if (productDetails != null) {
|
||||
Log.d(TAG, "BuyProduct:" + productDetails.productId)
|
||||
PayModel.get().placeOrder(productDetails.productId)
|
||||
Log.d(TAG, "BuyProduct:" + productDetails.getProductId())
|
||||
PayModel.get().placeOrder(productDetails.getProductId())
|
||||
.compose(bindToLifecycle())
|
||||
.subscribe(
|
||||
{ recordId: PayRecordId ->
|
||||
@@ -512,7 +528,7 @@ class VipMainActivity : BaseViewBindingActivity<ActivityVipMainBinding>(),
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (billingManager?.isServiceConnected == true) {
|
||||
if (billingManager?.isServiceConnected() == true) {
|
||||
billingManager?.onQueryPurchases()
|
||||
}
|
||||
}
|
||||
|
@@ -19,6 +19,8 @@ buildscript {
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||
// aRouter
|
||||
classpath "com.alibaba:arouter-register:1.0.2"
|
||||
//realm 数据库插件
|
||||
classpath "io.realm:realm-gradle-plugin:10.16.1"
|
||||
// android 资源混淆插件
|
||||
|
@@ -94,10 +94,6 @@ dependencies {
|
||||
// implementation 'com.google.firebase:firebase-core:19.0.0'
|
||||
// implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
|
||||
|
||||
//googleplay内购
|
||||
api 'com.google.android.gms:play-services-wallet:19.2.1'
|
||||
api 'com.android.billingclient:billing:6.0.1'
|
||||
|
||||
api 'org.jetbrains.kotlin:kotlin-reflect:1.7.10'
|
||||
|
||||
api project(':nim_uikit')
|
||||
@@ -107,6 +103,8 @@ dependencies {
|
||||
implementation 'com.liulishuo.okdownload:okhttp:1.0.7'
|
||||
|
||||
implementation 'com.tencent.liteav:LiteAVSDK_TRTC:11.4.0.13189'
|
||||
|
||||
api project(':modules:module_base')
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
@@ -1,8 +1,15 @@
|
||||
package com.yizhuan.xchat_android_core.auth;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.example.module_base.support.google.IGoogleService;
|
||||
import com.example.module_base.support.login.ILoginService;
|
||||
import com.example.module_base.support.login.LoginSDKException;
|
||||
import com.example.module_base.support.login.PlatformInfo;
|
||||
import com.netease.nim.uikit.api.NimUIKit;
|
||||
import com.netease.nim.uikit.common.util.log.LogUtil;
|
||||
import com.netease.nim.uikit.common.util.string.StringUtil;
|
||||
@@ -134,6 +141,7 @@ public class AuthModel extends BaseModel implements IAuthModel {
|
||||
private Platform facebook;
|
||||
private Platform line;
|
||||
private Platform google;
|
||||
private ILoginService googleLoginService;
|
||||
/****************************************************** IM *************************************************************/
|
||||
|
||||
private StatusCode statusCode;
|
||||
@@ -166,6 +174,14 @@ public class AuthModel extends BaseModel implements IAuthModel {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILoginService getGoogleLoginService() {
|
||||
if (googleLoginService == null) {
|
||||
googleLoginService = IGoogleService.Companion.newLoginService();
|
||||
}
|
||||
return googleLoginService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThirdUserInfo getThirdUserInfo() {
|
||||
return thirdUserInfo;
|
||||
@@ -437,58 +453,40 @@ public class AuthModel extends BaseModel implements IAuthModel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<String> googleLogin() {
|
||||
return Single.create(new SingleOnSubscribe<Platform>() {
|
||||
@Override
|
||||
public void subscribe(SingleEmitter<Platform> e) throws Exception {
|
||||
google = ShareSDK.getPlatform(GooglePlus.NAME);
|
||||
//是否安装客户端
|
||||
if (!DeviceUtils.isAppInstalled(getContext(), PackageNameConstants.GOOGLE_NAME)) {
|
||||
e.onError(new Throwable(ResUtil.getString(R.string.xchat_android_core_auth_authmodel_09)));
|
||||
return;
|
||||
}
|
||||
//判断指定平台是否已经完成授权
|
||||
if (google.isAuthValid()) {
|
||||
google.removeAccount(true);
|
||||
}
|
||||
google.setPlatformActionListener(new PlatformActionListener() {
|
||||
@Override
|
||||
public void onComplete(Platform platform, int i, HashMap<String, Object> hashMap) {
|
||||
if (i == Platform.ACTION_USER_INFOR) {
|
||||
String openid = platform.getDb().getUserId();
|
||||
String unionid = platform.getDb().get("unionid");
|
||||
Logger.i("openid:" + openid + " unionid:" + unionid + platform.getDb().getUserIcon());
|
||||
public Single<String> googleLogin(Activity activity) {
|
||||
return Single.create((SingleOnSubscribe<PlatformInfo>) e -> {
|
||||
ILoginService loginService = getGoogleLoginService();
|
||||
if (loginService == null) {
|
||||
e.onError(new Throwable(ResUtil.getString(R.string.bean_response_serviceresult_015)));
|
||||
return;
|
||||
}
|
||||
//是否安装客户端
|
||||
if (!DeviceUtils.isAppInstalled(getContext(), PackageNameConstants.GOOGLE_NAME)) {
|
||||
e.onError(new Throwable(ResUtil.getString(R.string.xchat_android_core_auth_authmodel_09)));
|
||||
return;
|
||||
}
|
||||
loginService.login(activity, new ILoginService.Listener() {
|
||||
@Override
|
||||
public void onSuccess(@NonNull PlatformInfo platformInfo) {
|
||||
thirdUserInfo = new ThirdUserInfo();
|
||||
thirdUserInfo.setType(ThirdUserInfo.TYPE_GOOGLE);
|
||||
thirdUserInfo.setPlatform("Google");
|
||||
thirdUserInfo.setUserName(platformInfo.getName());
|
||||
thirdUserInfo.setUserIcon(platformInfo.getAvatar());
|
||||
e.onSuccess(platformInfo);
|
||||
}
|
||||
|
||||
thirdUserInfo = new ThirdUserInfo();
|
||||
thirdUserInfo.setType(ThirdUserInfo.TYPE_GOOGLE);
|
||||
thirdUserInfo.setPlatform("Google");
|
||||
thirdUserInfo.setUserName(platform.getDb().getUserName());
|
||||
thirdUserInfo.setUserGender(platform.getDb().getUserGender());
|
||||
thirdUserInfo.setUserIcon(platform.getDb().getUserIcon());
|
||||
e.onSuccess(platform);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Platform platform, int i, Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
LogUtils.d("googleLogin" + i);
|
||||
e.onError(new Throwable(ResUtil.getString(R.string.xchat_android_core_auth_authmodel_010) + i));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(Platform platform, int i) {
|
||||
e.onError(new Throwable(ResUtil.getString(R.string.xchat_android_core_auth_authmodel_011)));
|
||||
}
|
||||
});
|
||||
google.SSOSetting(false);
|
||||
google.showUser(null);
|
||||
|
||||
}
|
||||
})
|
||||
@Override
|
||||
public void onFailure(@NonNull LoginSDKException exception) {
|
||||
exception.printStackTrace();
|
||||
LogUtils.d("googleLogin" + exception);
|
||||
e.onError(new Throwable(ResUtil.getString(R.string.xchat_android_core_auth_authmodel_010) + exception.getCode()));
|
||||
}
|
||||
});
|
||||
})
|
||||
.flatMap(platform -> {
|
||||
String openid = platform.getDb().getUserId();
|
||||
String unionid = platform.getDb().getUserId();
|
||||
String openid = platform.getId();
|
||||
String unionid = platform.getId();
|
||||
String avatar = thirdUserInfo.getUserIcon();
|
||||
if (avatar != null && avatar.equals("null")) {
|
||||
avatar = null;
|
||||
@@ -509,6 +507,79 @@ public class AuthModel extends BaseModel implements IAuthModel {
|
||||
.doOnSuccess(s -> EventBus.getDefault().post(new LoginEvent()));
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Single<String> googleLogin() {
|
||||
// return Single.create(new SingleOnSubscribe<Platform>() {
|
||||
// @Override
|
||||
// public void subscribe(SingleEmitter<Platform> e) throws Exception {
|
||||
// google = ShareSDK.getPlatform(GooglePlus.NAME);
|
||||
// //是否安装客户端
|
||||
// if (!DeviceUtils.isAppInstalled(getContext(), PackageNameConstants.GOOGLE_NAME)) {
|
||||
// e.onError(new Throwable(ResUtil.getString(R.string.xchat_android_core_auth_authmodel_09)));
|
||||
// return;
|
||||
// }
|
||||
// //判断指定平台是否已经完成授权
|
||||
// if (google.isAuthValid()) {
|
||||
// google.removeAccount(true);
|
||||
// }
|
||||
// google.setPlatformActionListener(new PlatformActionListener() {
|
||||
// @Override
|
||||
// public void onComplete(Platform platform, int i, HashMap<String, Object> hashMap) {
|
||||
// if (i == Platform.ACTION_USER_INFOR) {
|
||||
// String openid = platform.getDb().getUserId();
|
||||
// String unionid = platform.getDb().get("unionid");
|
||||
// Logger.i("openid:" + openid + " unionid:" + unionid + platform.getDb().getUserIcon());
|
||||
//
|
||||
// thirdUserInfo = new ThirdUserInfo();
|
||||
// thirdUserInfo.setType(ThirdUserInfo.TYPE_GOOGLE);
|
||||
// thirdUserInfo.setPlatform("Google");
|
||||
// thirdUserInfo.setUserName(platform.getDb().getUserName());
|
||||
// thirdUserInfo.setUserGender(platform.getDb().getUserGender());
|
||||
// thirdUserInfo.setUserIcon(platform.getDb().getUserIcon());
|
||||
// e.onSuccess(platform);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onError(Platform platform, int i, Throwable throwable) {
|
||||
// throwable.printStackTrace();
|
||||
// LogUtils.d("googleLogin" + i);
|
||||
// e.onError(new Throwable(ResUtil.getString(R.string.xchat_android_core_auth_authmodel_010) + i));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onCancel(Platform platform, int i) {
|
||||
// e.onError(new Throwable(ResUtil.getString(R.string.xchat_android_core_auth_authmodel_011)));
|
||||
// }
|
||||
// });
|
||||
// google.SSOSetting(false);
|
||||
// google.showUser(null);
|
||||
//
|
||||
// }
|
||||
// })
|
||||
// .flatMap(platform -> {
|
||||
// String openid = platform.getDb().getUserId();
|
||||
// String unionid = platform.getDb().getUserId();
|
||||
// String avatar = thirdUserInfo.getUserIcon();
|
||||
// if (avatar != null && avatar.equals("null")) {
|
||||
// avatar = null;
|
||||
// }
|
||||
// thirdUserInfo.setUserIcon(avatar);
|
||||
// String gender = thirdUserInfo.getUserGender();
|
||||
// if (gender != null && !gender.trim().isEmpty()) {
|
||||
// gender = gender.replace("m", "1").replace("f", "2");
|
||||
// }
|
||||
// thirdUserInfo.setUserGender(gender);
|
||||
// EventBus.getDefault().post(new LoginReportEvent(3));
|
||||
// return thirdLogin(openid, unionid, TYPE_GOOGLE_LOGIN, "", "");
|
||||
// })
|
||||
// .flatMap(s -> imLogin(currentAccountInfo))
|
||||
// .subscribeOn(AndroidSchedulers.mainThread())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .compose(RxHelper.handleException())
|
||||
// .doOnSuccess(s -> EventBus.getDefault().post(new LoginEvent()));
|
||||
// }
|
||||
|
||||
/**
|
||||
* 第三方信息登录
|
||||
*
|
||||
|
@@ -1,5 +1,8 @@
|
||||
package com.yizhuan.xchat_android_core.auth;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.example.module_base.support.login.ILoginService;
|
||||
import com.yizhuan.xchat_android_core.auth.entity.ThirdUserInfo;
|
||||
import com.yizhuan.xchat_android_core.base.IModel;
|
||||
|
||||
@@ -9,6 +12,8 @@ import io.reactivex.Single;
|
||||
|
||||
public interface IAuthModel extends IModel {
|
||||
|
||||
ILoginService getGoogleLoginService();
|
||||
|
||||
ThirdUserInfo getThirdUserInfo();
|
||||
|
||||
void setThirdUserInfo(ThirdUserInfo thirdUserInfo);
|
||||
@@ -63,7 +68,9 @@ public interface IAuthModel extends IModel {
|
||||
|
||||
Single<String> lineLogin();
|
||||
|
||||
Single<String> googleLogin();
|
||||
// Single<String> googleLogin();
|
||||
|
||||
Single<String> googleLogin(Activity activity);
|
||||
|
||||
/**
|
||||
* 重置用户信息
|
||||
|
@@ -15,8 +15,8 @@ import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.bumptech.glide.request.FutureTarget;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.chuhai.utils.LanguageUtils;
|
||||
import com.chuhai.utils.TelephonyUtils;
|
||||
import com.example.lib_utils.LanguageUtils;
|
||||
import com.example.lib_utils.TelephonyUtils;
|
||||
import com.netease.nim.uikit.support.glide.GlideApp;
|
||||
import com.yizhuan.xchat_android_core.R;
|
||||
import com.yizhuan.xchat_android_core.DemoCache;
|
||||
|
@@ -5,7 +5,7 @@ import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.chuhai.utils.TelephonyUtils;
|
||||
import com.example.lib_utils.TelephonyUtils;
|
||||
import com.yizhuan.xchat_android_core.auth.AuthModel;
|
||||
import com.yizhuan.xchat_android_core.utils.APIEncryptUtil;
|
||||
import com.yizhuan.xchat_android_core.utils.OaidUtil;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package com.yizhuan.xchat_android_core.interceptor
|
||||
|
||||
import com.chuhai.utils.AppUtils
|
||||
import com.chuhai.utils.ServiceTime
|
||||
import com.example.lib_utils.AppUtils
|
||||
import com.example.lib_utils.ServiceTime
|
||||
import com.yizhuan.xchat_android_core.utils.LogUtils
|
||||
import com.yizhuan.xchat_android_library.utils.NetworkUtils
|
||||
import okhttp3.Headers
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.yizhuan.xchat_android_core.pay.bean;
|
||||
|
||||
import com.android.billingclient.api.ProductDetails;
|
||||
import com.example.module_base.support.billing.IProductDetails;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@@ -25,7 +25,7 @@ public class ChargeBean implements Serializable{
|
||||
public int giftGoldNum;
|
||||
public int channel;
|
||||
public String prodDesc;
|
||||
private ProductDetails mProductDetails;
|
||||
private IProductDetails mProductDetails;
|
||||
|
||||
public boolean isSelected;
|
||||
|
||||
@@ -82,11 +82,11 @@ public class ChargeBean implements Serializable{
|
||||
this.prodDesc = prodDesc;
|
||||
}
|
||||
|
||||
public ProductDetails getProductDetails() {
|
||||
public IProductDetails getProductDetails() {
|
||||
return mProductDetails;
|
||||
}
|
||||
|
||||
public void setProductDetails(ProductDetails productDetails) {
|
||||
public void setProductDetails(IProductDetails productDetails) {
|
||||
this.mProductDetails = productDetails;
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package com.yizhuan.xchat_android_core.pay.bean;
|
||||
|
||||
import com.android.billingclient.api.ProductDetails;
|
||||
|
||||
import com.example.module_base.support.billing.IProductDetails;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -17,5 +18,5 @@ public class FirstChargeGoods {
|
||||
private ArrayList<FirstChargeReward> firstChargeRewardList;
|
||||
private String giveMoney;
|
||||
private boolean finishCharge;
|
||||
private ProductDetails productDetails;
|
||||
private IProductDetails productDetails;
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import androidx.annotation.CallSuper
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.example.lib_utils.log.ILog
|
||||
import com.trello.rxlifecycle3.LifecycleProvider
|
||||
import com.trello.rxlifecycle3.LifecycleTransformer
|
||||
import com.trello.rxlifecycle3.OutsideLifecycleException
|
||||
|
@@ -2,7 +2,7 @@ package com.yizhuan.xchat_android_core.support.room
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.example.lib_utils.log.ILog
|
||||
import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomLifecycle
|
||||
import com.yizhuan.xchat_android_core.support.room.lifecycle.RoomLifecycleRegistry
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.yizhuan.xchat_android_core.support.room
|
||||
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.example.lib_utils.log.ILog
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 17:12
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.yizhuan.xchat_android_core.support.room.lifecycle
|
||||
|
||||
import com.chuhai.utils.ICleared
|
||||
import com.example.lib_utils.ICleared
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 11:50
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.yizhuan.xchat_android_core.support.room.lifecycle
|
||||
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.example.lib_utils.log.ILog
|
||||
import com.yizhuan.xchat_android_core.support.room.RoomContext
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
||||
|
@@ -35,8 +35,6 @@ android {
|
||||
'src/module_luban/java',
|
||||
'src/module_easyphoto/java',
|
||||
'src/module_common/java',
|
||||
'src/module_utils/java',
|
||||
'src/module_core/java',
|
||||
|
||||
]
|
||||
|
||||
@@ -45,8 +43,6 @@ android {
|
||||
'src/module_easypermission/res',
|
||||
'src/module_easyphoto/res',
|
||||
'src/module_common/res',
|
||||
'src/module_utils/res',
|
||||
'src/module_core/res',
|
||||
|
||||
]
|
||||
|
||||
@@ -88,18 +84,10 @@ dependencies {
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
||||
api 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
api 'androidx.appcompat:appcompat:1.4.2'
|
||||
api 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
api 'androidx.cardview:cardview:1.0.0'
|
||||
api 'androidx.gridlayout:gridlayout:1.0.0'
|
||||
api "androidx.core:core-ktx:1.7.0"
|
||||
api "androidx.fragment:fragment:$fragment_version"
|
||||
api "androidx.fragment:fragment-ktx:$fragment_version"
|
||||
api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
|
||||
api 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
|
||||
api 'com.google.android.material:material:1.6.1'
|
||||
|
||||
api "com.squareup.retrofit2:retrofit:${retrofitVersion}"
|
||||
api "com.squareup.okhttp3:okhttp:${okhttp3}"
|
||||
@@ -151,6 +139,9 @@ dependencies {
|
||||
// 网络请求chrome数据调试
|
||||
api 'com.facebook.stetho:stetho:1.5.1'
|
||||
api 'com.facebook.stetho:stetho-okhttp3:1.5.1'
|
||||
|
||||
api project(':libs:lib_utils')
|
||||
api project(':libs:lib_core')
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
@@ -3,6 +3,8 @@ package com.yizhuan.xchat_android_library.common.application;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.example.lib_utils.AppUtils;
|
||||
|
||||
/**
|
||||
* Application的代理类
|
||||
*/
|
||||
@@ -26,7 +28,7 @@ public abstract class BaseApp extends Application{
|
||||
|
||||
public static void init(Application application) {
|
||||
gContext = application;
|
||||
com.chuhai.utils.AppUtils.init(application);
|
||||
AppUtils.init(application);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
|
||||
</resources>
|
@@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
|
||||
</resources>
|
1
libs/lib_core/.gitignore
vendored
Normal file
1
libs/lib_core/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
19
libs/lib_core/build.gradle
Normal file
19
libs/lib_core/build.gradle
Normal file
@@ -0,0 +1,19 @@
|
||||
apply from : "../lib_standard.gradle"
|
||||
|
||||
android {
|
||||
namespace 'com.example.lib_core'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// 工具集
|
||||
api project(path: ":libs:lib_utils")
|
||||
|
||||
api 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
api 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
api 'com.google.android.material:material:1.6.1'
|
||||
api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
|
||||
api 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
|
||||
|
||||
api "com.alibaba:fastjson:1.2.41"
|
||||
}
|
0
libs/lib_core/consumer-rules.pro
Normal file
0
libs/lib_core/consumer-rules.pro
Normal file
21
libs/lib_core/proguard-rules.pro
vendored
Normal file
21
libs/lib_core/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@@ -0,0 +1,24 @@
|
||||
package com.example.lib_core
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.example.lib_core.test", appContext.packageName)
|
||||
}
|
||||
}
|
4
libs/lib_core/src/main/AndroidManifest.xml
Normal file
4
libs/lib_core/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
@@ -1,10 +1,10 @@
|
||||
package com.chuhai.core.component
|
||||
package com.example.lib_core.component
|
||||
|
||||
import LifecycleCleared
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import com.chuhai.utils.ktx.asLifecycle
|
||||
import com.example.lib_utils.ktx.asLifecycle
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
|
||||
|
@@ -0,0 +1,17 @@
|
||||
package com.example.lib_core
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
41
libs/lib_standard.gradle
Normal file
41
libs/lib_standard.gradle
Normal file
@@ -0,0 +1,41 @@
|
||||
apply plugin: "com.android.library"
|
||||
apply plugin: "org.jetbrains.kotlin.android"
|
||||
apply plugin: "kotlin-android"
|
||||
apply plugin: "kotlin-kapt"
|
||||
|
||||
android {
|
||||
compileSdkVersion COMPILE_SDK_VERSION.toInteger()
|
||||
defaultConfig {
|
||||
minSdkVersion MIN_SDK_VERSION.toInteger()
|
||||
targetSdkVersion TARGET_SDK_VERSION.toInteger()
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
zipAlignEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '11'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
|
1
libs/lib_utils/.gitignore
vendored
Normal file
1
libs/lib_utils/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
10
libs/lib_utils/build.gradle
Normal file
10
libs/lib_utils/build.gradle
Normal file
@@ -0,0 +1,10 @@
|
||||
apply from : "../lib_standard.gradle"
|
||||
|
||||
android {
|
||||
namespace 'com.example.lib_utils'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api "androidx.core:core-ktx:1.7.0"
|
||||
api 'androidx.appcompat:appcompat:1.4.2'
|
||||
}
|
0
libs/lib_utils/consumer-rules.pro
Normal file
0
libs/lib_utils/consumer-rules.pro
Normal file
21
libs/lib_utils/proguard-rules.pro
vendored
Normal file
21
libs/lib_utils/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@@ -0,0 +1,24 @@
|
||||
package com.example.lib_utils
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.example.lib_utils.test", appContext.packageName)
|
||||
}
|
||||
}
|
4
libs/lib_utils/src/main/AndroidManifest.xml
Normal file
4
libs/lib_utils/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils;
|
||||
package com.example.lib_utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActivityManager;
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils
|
||||
package com.example.lib_utils
|
||||
|
||||
|
||||
/**
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils
|
||||
package com.example.lib_utils
|
||||
|
||||
import android.os.Build
|
||||
import android.os.LocaleList
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils
|
||||
package com.example.lib_utils
|
||||
|
||||
import android.os.SystemClock
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils
|
||||
package com.example.lib_utils
|
||||
|
||||
import android.graphics.Outline
|
||||
import android.view.View
|
@@ -1,8 +1,8 @@
|
||||
package com.chuhai.utils
|
||||
package com.example.lib_utils
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.TelephonyManager
|
||||
import com.chuhai.utils.log.ILog
|
||||
import com.example.lib_utils.log.ILog
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/14 10:17
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils
|
||||
package com.example.lib_utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.ktx
|
||||
package com.example.lib_utils.ktx
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
@@ -1,9 +1,8 @@
|
||||
package com.chuhai.utils.ktx
|
||||
package com.example.lib_utils.ktx
|
||||
|
||||
import android.text.Editable
|
||||
import android.text.InputFilter
|
||||
import android.text.InputFilter.LengthFilter
|
||||
import android.text.Spanned
|
||||
import android.text.TextWatcher
|
||||
import android.text.method.HideReturnsTransformationMethod
|
||||
import android.text.method.PasswordTransformationMethod
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.ktx
|
||||
package com.example.lib_utils.ktx
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
@@ -9,7 +9,7 @@ import androidx.annotation.*
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.chuhai.utils.AppUtils
|
||||
import com.example.lib_utils.AppUtils
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/24 15:11
|
@@ -1,6 +1,6 @@
|
||||
package com.chuhai.utils.ktx
|
||||
package com.example.lib_utils.ktx
|
||||
|
||||
import com.chuhai.utils.UiUtils
|
||||
import com.example.lib_utils.UiUtils
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.ktx
|
||||
package com.example.lib_utils.ktx
|
||||
|
||||
import android.graphics.*
|
||||
import android.os.Build
|
||||
@@ -9,8 +9,8 @@ import android.view.ViewGroup
|
||||
import android.widget.Checkable
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.ScrollingView
|
||||
import com.chuhai.utils.ShapeViewOutlineProvider
|
||||
import com.chuhai.utils.UiUtils
|
||||
import com.example.lib_utils.ShapeViewOutlineProvider
|
||||
import com.example.lib_utils.UiUtils
|
||||
|
||||
|
||||
/**
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.log
|
||||
package com.example.lib_utils.log
|
||||
|
||||
import android.util.Log
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.log
|
||||
package com.example.lib_utils.log
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 10:29
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.log
|
||||
package com.example.lib_utils.log
|
||||
|
||||
|
||||
/**
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.log
|
||||
package com.example.lib_utils.log
|
||||
|
||||
import android.util.Log
|
||||
|
||||
@@ -22,7 +22,7 @@ object LogUtil {
|
||||
* 设置文件打印
|
||||
*/
|
||||
fun setFilePrinter(filePrinter: LogPrinter) {
|
||||
this.filePrinter = filePrinter
|
||||
LogUtil.filePrinter = filePrinter
|
||||
}
|
||||
|
||||
fun e(tag: String, message: String, filePrinter: Boolean = false) {
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.spannable;
|
||||
package com.example.lib_utils.spannable;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.spannable
|
||||
package com.example.lib_utils.spannable
|
||||
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.spannable
|
||||
package com.example.lib_utils.spannable
|
||||
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
@@ -10,7 +10,7 @@ import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.chuhai.utils.ktx.dp
|
||||
import com.example.lib_utils.ktx.dp
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/10/26 20:14
|
||||
@@ -209,7 +209,7 @@ class SpannableTextBuilder(private val textView: TextView) {
|
||||
spannableBuilder.append(text)
|
||||
val end = spannableBuilder.length
|
||||
spannableBuilder.setSpan(
|
||||
IconTextSpan(
|
||||
com.example.lib_utils.spannable.IconTextSpan(
|
||||
textView.context,
|
||||
backgroundColor,
|
||||
text,
|
@@ -1,4 +1,4 @@
|
||||
package com.chuhai.utils.spannable
|
||||
package com.example.lib_utils.spannable
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
@@ -0,0 +1,17 @@
|
||||
package com.example.lib_utils
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
54
modules/module_base.gradle
Normal file
54
modules/module_base.gradle
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 文件说明:module的基础配置
|
||||
*/
|
||||
apply plugin: "com.android.library"
|
||||
apply plugin: "org.jetbrains.kotlin.android"
|
||||
apply plugin: "kotlin-android"
|
||||
apply plugin: "kotlin-kapt"
|
||||
apply plugin: "com.alibaba.arouter"
|
||||
|
||||
android {
|
||||
compileSdkVersion COMPILE_SDK_VERSION.toInteger()
|
||||
defaultConfig {
|
||||
minSdkVersion MIN_SDK_VERSION.toInteger()
|
||||
targetSdkVersion TARGET_SDK_VERSION.toInteger()
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
zipAlignEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '11'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.2'
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
|
||||
// aRouter
|
||||
api 'com.alibaba:arouter-api:1.4.0'
|
||||
api 'com.alibaba:arouter-annotation:1.0.6'
|
||||
kapt 'com.alibaba:arouter-compiler:1.5.2'
|
||||
}
|
||||
|
1
modules/module_base/.gitignore
vendored
Normal file
1
modules/module_base/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
17
modules/module_base/build.gradle
Normal file
17
modules/module_base/build.gradle
Normal file
@@ -0,0 +1,17 @@
|
||||
apply from: "../module_base.gradle"
|
||||
|
||||
android {
|
||||
namespace 'com.example.module_base'
|
||||
}
|
||||
|
||||
kapt {
|
||||
arguments {
|
||||
arg("AROUTER_MODULE_NAME", project.getName())
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// 内部组件库
|
||||
api project(path: ":libs:lib_core")
|
||||
api project(path: ":libs:lib_utils")
|
||||
}
|
0
modules/module_base/consumer-rules.pro
Normal file
0
modules/module_base/consumer-rules.pro
Normal file
21
modules/module_base/proguard-rules.pro
vendored
Normal file
21
modules/module_base/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@@ -0,0 +1,24 @@
|
||||
package com.example.module_base
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.example.module_base.test", appContext.packageName)
|
||||
}
|
||||
}
|
4
modules/module_base/src/main/AndroidManifest.xml
Normal file
4
modules/module_base/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
@@ -0,0 +1,9 @@
|
||||
package com.example.module_base.config
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 16:01
|
||||
* Desc:
|
||||
**/
|
||||
object RouterPath {
|
||||
const val GOOGLE_SERVICE = "/google/service"
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.example.module_base.support.billing
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 20:55
|
||||
* Desc:
|
||||
**/
|
||||
interface IAccountIdentifiers {
|
||||
|
||||
fun getObfuscatedAccountId(): String?
|
||||
|
||||
fun getObfuscatedProfileId(): String?
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.example.module_base.support.billing
|
||||
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 20:20
|
||||
* Desc:
|
||||
**/
|
||||
interface IBillingResult {
|
||||
fun getResponseCode(): Int
|
||||
|
||||
fun isResponseOk(): Boolean
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package com.example.module_base.support.billing
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 17:44
|
||||
* Desc:支付
|
||||
**/
|
||||
interface IBillingService {
|
||||
|
||||
fun isServiceConnected(): Boolean
|
||||
|
||||
fun onQueryPurchases()
|
||||
|
||||
fun querySkuDetailsAsync(
|
||||
productIdList: List<String>,
|
||||
listener: IBillingService.ProductDetailsResponseListener
|
||||
)
|
||||
|
||||
fun consumeAsync(purchaseToken: String)
|
||||
|
||||
fun initiatePurchaseFlow(productDetails: IProductDetails, recordId: String)
|
||||
|
||||
fun destroy()
|
||||
|
||||
interface Listener {
|
||||
fun onBillingClientSetupFinished()
|
||||
fun onPurchasesUpdated(purchases: List<IPurchase>)
|
||||
fun onConsumeFinished(token: String?, result: Int)
|
||||
fun onFailedHandle(result: Int)
|
||||
}
|
||||
|
||||
interface ProductDetailsResponseListener {
|
||||
fun onProductDetailsResponse(billingResult: IBillingResult, productDetails: List<IProductDetails>)
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.example.module_base.support.billing
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 21:06
|
||||
* Desc:
|
||||
**/
|
||||
interface IOneTimePurchaseOfferDetails {
|
||||
fun getPriceAmountMicros(): Long
|
||||
|
||||
fun getFormattedPrice(): String
|
||||
|
||||
fun getPriceCurrencyCode(): String
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package com.example.module_base.support.billing
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 20:17
|
||||
* Desc:
|
||||
**/
|
||||
interface IProductDetails {
|
||||
|
||||
fun getData(): Any
|
||||
|
||||
fun getProductId(): String
|
||||
|
||||
fun getOneTimePurchaseOfferDetails(): IOneTimePurchaseOfferDetails?
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package com.example.module_base.support.billing
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 19:22
|
||||
* Desc:
|
||||
**/
|
||||
interface IPurchase {
|
||||
|
||||
fun getData(): Any
|
||||
|
||||
fun getPurchaseState(): Int
|
||||
|
||||
fun isPurchasedState(): Boolean
|
||||
|
||||
fun getAccountIdentifiers(): IAccountIdentifiers?
|
||||
fun getProducts(): List<String>
|
||||
|
||||
fun getPackageName(): String
|
||||
|
||||
fun getPurchaseToken(): String
|
||||
|
||||
fun getOrderId(): String?
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package com.example.module_base.support.google
|
||||
|
||||
import android.app.Activity
|
||||
import com.alibaba.android.arouter.facade.template.IProvider
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.example.module_base.support.billing.IBillingService
|
||||
import com.example.module_base.support.login.ILoginService
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 15:30
|
||||
* Desc:google服务
|
||||
**/
|
||||
interface IGoogleService : IProvider {
|
||||
companion object {
|
||||
val instance: IGoogleService? by lazy {
|
||||
ARouter.getInstance().navigation(IGoogleService::class.java)
|
||||
}
|
||||
|
||||
fun newLoginService(): ILoginService? {
|
||||
return instance?.newLoginService()
|
||||
}
|
||||
|
||||
fun newBillingService(
|
||||
activity: Activity,
|
||||
listener: IBillingService.Listener
|
||||
): IBillingService? {
|
||||
return instance?.newBillingService(activity, listener)
|
||||
}
|
||||
}
|
||||
|
||||
fun newLoginService(): ILoginService
|
||||
|
||||
fun newBillingService(
|
||||
activity: Activity,
|
||||
listener: IBillingService.Listener
|
||||
): IBillingService
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package com.example.module_base.support.login
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 15:52
|
||||
* Desc:登录服务
|
||||
**/
|
||||
interface ILoginService {
|
||||
|
||||
fun login(activity: Activity, listener: Listener)
|
||||
|
||||
fun logout()
|
||||
|
||||
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
|
||||
|
||||
interface Listener {
|
||||
fun onSuccess(platformInfo: PlatformInfo)
|
||||
fun onFailure(exception: LoginSDKException)
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package com.example.module_base.support.login
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 17:06
|
||||
* Desc:登录SDK-异常
|
||||
**/
|
||||
class LoginSDKException : Exception {
|
||||
private var code: Int = -1
|
||||
|
||||
fun getCode(): Int {
|
||||
return code
|
||||
}
|
||||
|
||||
constructor(code: Int) : super() {
|
||||
this.code = code
|
||||
}
|
||||
|
||||
constructor(code: Int, cause: Throwable?) : super(cause) {
|
||||
this.code = code
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
package com.example.module_base.support.login
|
||||
|
||||
/**
|
||||
* Created by Max on 2023/11/22 15:45
|
||||
* Desc:第三方平台信息
|
||||
**/
|
||||
data class PlatformInfo(val id: String, var name: String?, var gender: Int?, var avatar: String?) {
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package com.example.module_base
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
1
modules/module_google/.gitignore
vendored
Normal file
1
modules/module_google/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
24
modules/module_google/build.gradle
Normal file
24
modules/module_google/build.gradle
Normal file
@@ -0,0 +1,24 @@
|
||||
apply from: "../module_standard.gradle"
|
||||
android {
|
||||
namespace 'com.example.module_google'
|
||||
|
||||
defaultConfig {
|
||||
buildConfigField "String", "GOOGLE_APP_KEY", "\"xxx\""
|
||||
buildConfigField "String", "GOOGLE_SERVER_CLIENT_ID", "\"..com\""
|
||||
}
|
||||
}
|
||||
|
||||
kapt {
|
||||
arguments {
|
||||
arg("AROUTER_MODULE_NAME", project.getName())
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// google登录
|
||||
implementation 'com.google.android.gms:play-services-auth:20.7.0'
|
||||
|
||||
// googleplay内购
|
||||
implementation 'com.google.android.gms:play-services-wallet:19.2.1'
|
||||
implementation 'com.android.billingclient:billing:6.0.1'
|
||||
}
|
0
modules/module_google/consumer-rules.pro
Normal file
0
modules/module_google/consumer-rules.pro
Normal file
21
modules/module_google/proguard-rules.pro
vendored
Normal file
21
modules/module_google/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@@ -0,0 +1,24 @@
|
||||
package com.example.module_google
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.example.module_google.test", appContext.packageName)
|
||||
}
|
||||
}
|
4
modules/module_google/src/main/AndroidManifest.xml
Normal file
4
modules/module_google/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user