feat:初步搭建google隔离架构

This commit is contained in:
Max
2023-11-22 21:35:05 +08:00
parent 7291b61e44
commit a7ba26a85b
114 changed files with 1510 additions and 501 deletions

View File

@@ -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 {

View File

@@ -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());

View File

@@ -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()
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;
}
}
}

View File

@@ -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())

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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()
}
}

View File

@@ -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 资源混淆插件

View File

@@ -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()

View File

@@ -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()));
// }
/**
* 第三方信息登录
*

View File

@@ -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);
/**
* 重置用户信息

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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);
}
/**

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>

View File

@@ -1,3 +0,0 @@
<resources>
</resources>

1
libs/lib_core/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View 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"
}

View File

21
libs/lib_core/proguard-rules.pro vendored Normal file
View 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

View File

@@ -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)
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@@ -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

View File

@@ -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
View 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
View File

@@ -0,0 +1 @@
/build

View 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'
}

View File

21
libs/lib_utils/proguard-rules.pro vendored Normal file
View 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

View File

@@ -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)
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils;
package com.example.lib_utils;
import android.annotation.SuppressLint;
import android.app.ActivityManager;

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils
package com.example.lib_utils
/**

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils
package com.example.lib_utils
import android.os.Build
import android.os.LocaleList

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils
package com.example.lib_utils
import android.os.SystemClock

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils
package com.example.lib_utils
import android.graphics.Outline
import android.view.View

View File

@@ -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

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils
package com.example.lib_utils
import android.annotation.SuppressLint
import android.content.Context

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils.ktx
package com.example.lib_utils.ktx
import android.app.Activity
import android.content.Context

View File

@@ -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

View File

@@ -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

View File

@@ -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
/**

View File

@@ -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
/**

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils.log
package com.example.lib_utils.log
import android.util.Log

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils.log
package com.example.lib_utils.log
/**
* Created by Max on 2023/10/26 10:29

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils.log
package com.example.lib_utils.log
/**

View File

@@ -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) {

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils.spannable;
package com.example.lib_utils.spannable;
import android.content.Context;
import android.graphics.Canvas;

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils.spannable
package com.example.lib_utils.spannable
import android.graphics.Canvas
import android.graphics.Paint

View File

@@ -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,

View File

@@ -1,4 +1,4 @@
package com.chuhai.utils.spannable
package com.example.lib_utils.spannable
import android.content.Context
import android.graphics.Canvas

View File

@@ -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)
}
}

View 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
View File

@@ -0,0 +1 @@
/build

View 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")
}

View File

21
modules/module_base/proguard-rules.pro vendored Normal file
View 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

View File

@@ -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)
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@@ -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"
}

View File

@@ -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?
}

View File

@@ -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
}

View File

@@ -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>)
}
}

View File

@@ -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
}

View File

@@ -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?
}

View File

@@ -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?
}

View File

@@ -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
}

View File

@@ -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)
}
}

View File

@@ -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
}
}

View File

@@ -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?) {
}

View File

@@ -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
View File

@@ -0,0 +1 @@
/build

View 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'
}

View File

View 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

View File

@@ -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)
}
}

View 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