前言
团队介绍
作者:徐庆
团队:坚果派 大众号:“大前端之旅” 润开鸿生态技术专家,华为HDE,CSDN博客专家,CSDN超级个别,CSDN特邀嘉宾,InfoQ签约作者,OpenHarmony布道师,电子发烧友专家博客,51CTO博客专家,擅长HarmonyOS/OpenHarmony应用开发、熟悉服务卡片开发。欢迎协作。
效果图 :
完成办法
咱们是经过AkrUi-X和安卓交互 然后在原生安卓里边参加了内购付出结算库的依靠 最终调起的Google 付出 安卓原生内购付出教程
ArkUI端代码
akrui 端我这边只写了一个按钮调用Google内购付出和接纳数据
导入渠道桥接模块
// 导入渠道桥接模块
import bridge from '@arkui-x.bridge';
创立渠道桥接目标
// 创立渠道桥接目标
private bridgeImpl = bridge.createBridge('Bridge');
// 发送数据到Android侧,并经过状态变量,将Android侧的呼应数据显示在页面上
this.nativeResponse = await this.bridgeImpl.sendMessage('Hello ArkUI-X!');
接回收传回来的数据
aboutToAppear() {
this.getHelloArkUI();
}
getHelloArkUI() {
// 调用Android侧办法
this.bridgeImpl.callMethod('getHelloArkUI').then((result: string) => {
// 经过状态变量,将Android侧办法的返回值显示在页面上
this.helloArkUI = result;
});
完整代码
// 导入渠道桥接模块
import bridge from '@arkui-x.bridge';
@Entry
@Component
struct Index {
// 创立渠道桥接目标
private bridgeImpl = bridge.createBridge('Bridge');
@State helloArkUI: string = '';
@State nativeResponse: string = '';
aboutToAppear() {
this.getHelloArkUI();
}
getHelloArkUI() {
// 调用Android侧办法
// this.bridgeImpl.callMethod('getHelloArkUI').then((result: string) => {
// // 经过状态变量,将Android侧办法的返回值显示在页面上
// this.helloArkUI = result;
// });
/* this.bridgeImpl?.callMethod('getHelloArkUI').then((data)=>{
});*/
// let resultPromise=this.bridgeImpl.callMethod('getHelloArkUI'):resultPromise.then((data)=>{
//
//
//
// })
}
build() {
Row() {
Column() {
Text(this.helloArkUI)
.fontSize(15)
.margin(10)
Button('点击Google付出')
.fontSize(15)
.margin(10)
.onClick(async () => {
// 发送数据到Android侧,并经过状态变量,将Android侧的呼应数据显示在页面上
await this.bridgeImpl.sendMessage('Hello ArkUI-X!');
})
Text('Response from Native: ' + this.nativeResponse)
.fontSize(15)
.margin(10)
}
.width('100%')
}
.height('100%')
}
}
安卓部分
咱们编译项目 需求导入arkui-x编译之后发生的安卓原生宿主工程
官方文档地址
需求的依靠
def billing_version = "6.0.0"
implementation "com.android.billingclient:billing:$billing_version"
akrui-x 和原生安卓通信交互
引证渠道桥接模块
package com.example.helloworld;
/**
* 作者:xuqing
* 时间:2024年04月01日 15:27:31
* 邮箱:1693891473@qq.com
* 说明:
*/
import android.app.Activity;
import android.content.Context;
import android.util.Log;
// 引证渠道桥接模块
import ohos.ace.adapter.capability.bridge.BridgePlugin;
import ohos.ace.adapter.capability.bridge.IMessageListener;
public class Bridge extends BridgePlugin implements IMessageListener {
private static final String TAG = "Bridge";
private Context context;
public Bridge(Context context, String name, int id) {
super(context, name, id);
this.context=context;
setMessageListener(this);
}
// Android侧办法,供ArkUI侧调用
public String getHelloArkUI() {
return "Hello ArkUI!";
}
// 注册回调,接纳ArkUI侧发来的数据
@Override
public Object onMessage(Object object) {
// new EntryEntryAbilityActivity(). initgooglePlay();
GooglePay.getInstance().toGooglePay((Activity) context,"com.testgame.099");
Log.e(TAG, "onMessage: "+object.toString() );
return "java onMessage success";
}
@Override
public void onMessageResponse(Object object) {
}
}
内购付出初始化
public void initgooglePlay(Activity context) {
billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases()
.build();
if(billingClient!=null){
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
}
}
@Override
public void onBillingServiceDisconnected() {
}
});
}
}
调用起内购付出
public void toGooglePay(Activity context,String productId){
// String productId ="xxxx";
List<QueryProductDetailsParams.Product> productList= new ArrayList<>();
productList.add(QueryProductDetailsParams.Product.newBuilder()
.setProductId(productId)
.setProductType(BillingClient.ProductType.INAPP)
.build());
QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().
setProductList(productList)
.build();
if(billingClient!=null){
billingClient.queryProductDetailsAsync(
queryProductDetailsParams,
new ProductDetailsResponseListener() {
public void onProductDetailsResponse(BillingResult billingResult,
List<ProductDetails> productDetailsList) {
if(productDetailsList!=null&&productDetailsList.size()>0){
ProductDetails productDetails=productDetailsList.get(0);
List<BillingFlowParams.ProductDetailsParams> productDetailsParamsList= new ArrayList<>();
productDetailsParamsList.add(BillingFlowParams.ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.build());
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.build();
billingClient.launchBillingFlow((Activity) context, billingFlowParams);
}else {
Toast.makeText(context,"产品ID无效",Toast.LENGTH_SHORT).show();
}
}
}
);
}
}
咱们在arkui-x调用安卓原生的回调办法里边去调用咱们的 toGooglePay 传入咱们的产品ID 即可
-
付出回调
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
Log.e(TAG, "getPurchaseToken: "+ purchase.getPurchaseToken() );
Log.e(TAG, "getSignature: "+ purchase.getSignature() );
Log.e(TAG, "getSignature: "+ purchase.getSignature() );
}
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
} else {
}
}
};
咱们拿到回调里边的 getPurchaseToken getSignature getSignature 信息之后可以去自己服务端进行验签 假如验签成功了才算是真实的成功付出成功 然后再进行耗费
-
产品耗费
public void handlePurchase(final Purchase purchase) {
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = new ConsumeResponseListener() {
@Override
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.e(TAG, "getPurchaseToken: "+ purchase.getPurchaseToken() );
Log.e(TAG, "getSignature: "+ purchase.getSignature() );
Log.e(TAG, "getSignature: "+ purchase.getSignature() );
}
}
};
if(billingClient!=null){
billingClient.consumeAsync(consumeParams, listener);
}
}
-
付出完成后下次付出前查询耗费
public void queryPurchasesAsync(Activity context){
if(billingClient!=null){
if(!billingClient.isReady()){
Toast.makeText(context,"BillingClient is not ready",Toast.LENGTH_SHORT).show();
}
billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build(),
new PurchasesResponseListener() {
public void onQueryPurchasesResponse(
BillingResult billingResult,
List<Purchase> purchases) {
if(billingResult.getResponseCode()==BillingClient.BillingResponseCode.OK){
if(purchases!=null&&purchases.size()>0){
for (Purchase purchase:purchases){
handlePurchase(purchase);
}
}
}
}
}
);
}
}
请再 onResume 声明周期办法里边调用
@Override
protected void onResume() {
super.onResume();
GooglePay.getInstance().queryPurchasesAsync(EntryEntryAbilityActivity.this);
}
完整Android端代码
EntryEntryAbilityActivity 端代码
package com.example.helloworld;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import com.android.billingclient.api.BillingClient;
import ohos.stage.ability.adapter.StageActivity;
/**
* Example ace activity class, which will load ArkUI-X ability instance.
* StageActivity is provided by ArkUI-X
* @see <a href=
* "https://gitee.com/arkui-crossplatform/doc/blob/master/contribute/tutorial/how-to-build-Android-app.md">
* to build android library</a>
*/
public class EntryEntryAbilityActivity extends StageActivity {
private static final String TAG = "MainActivity";
private Context context=EntryEntryAbilityActivity.this;
private BillingClient billingClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.e("HiHelloWorld", "EntryEntryAbilityActivity");
new Bridge(this, "Bridge", getInstanceId());
//setInstanceName("com.example.helloworld:entry:EntryAbility:");
setInstanceName("com.example.helloworld:entry:EntryAbility:");
super.onCreate(savedInstanceState);
GooglePay.getInstance().initgooglePlay(EntryEntryAbilityActivity.this);
}
@Override
protected void onResume() {
super.onResume();
GooglePay.getInstance().queryPurchasesAsync(EntryEntryAbilityActivity.this);
}
@Override
public void onStop() {
super.onStop();
}
@Override
protected void onPause() {
super.onPause();
}
}
googlepay 工具类代码
package com.example.helloworld;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.android.billingclient.api.BillingClient;
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.ConsumeResponseListener;
import com.android.billingclient.api.ProductDetails;
import com.android.billingclient.api.ProductDetailsResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesResponseListener;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.QueryProductDetailsParams;
import com.android.billingclient.api.QueryPurchasesParams;
import java.util.ArrayList;
import java.util.List;
/**
* 作者:xuqing
* 时间:2024年04月01日 16:20:30
* 邮箱:1693891473@qq.com
* 说明:
*/
public class GooglePay {
private static final String TAG = "GooglePay";
private BillingClient billingClient;
private static GooglePay instance=null;
private GooglePay() {
}
public static GooglePay getInstance(){
if(instance==null){
synchronized (GooglePay.class){
if(instance==null){
instance=new GooglePay();
}
}
}
return instance;
}
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
handlePurchase(purchase);
Log.e(TAG, "getPurchaseToken: "+ purchase.getPurchaseToken() );
Log.e(TAG, "getSignature: "+ purchase.getSignature() );
Log.e(TAG, "getSignature: "+ purchase.getSignature() );
}
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
} else {
}
}
};
public void handlePurchase(final Purchase purchase) {
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = new ConsumeResponseListener() {
@Override
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.e(TAG, "getPurchaseToken: "+ purchase.getPurchaseToken() );
Log.e(TAG, "getSignature: "+ purchase.getSignature() );
Log.e(TAG, "getSignature: "+ purchase.getSignature() );
}
}
};
if(billingClient!=null){
billingClient.consumeAsync(consumeParams, listener);
}
}
public void initgooglePlay(Activity context) {
billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases()
.build();
if(billingClient!=null){
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
}
}
@Override
public void onBillingServiceDisconnected() {
}
});
}
}
public void toGooglePay(Activity context,String productId){
// String productId ="xxxx";
List<QueryProductDetailsParams.Product> productList= new ArrayList<>();
productList.add(QueryProductDetailsParams.Product.newBuilder()
.setProductId(productId)
.setProductType(BillingClient.ProductType.INAPP)
.build());
QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().
setProductList(productList)
.build();
if(billingClient!=null){
billingClient.queryProductDetailsAsync(
queryProductDetailsParams,
new ProductDetailsResponseListener() {
public void onProductDetailsResponse(BillingResult billingResult,
List<ProductDetails> productDetailsList) {
if(productDetailsList!=null&&productDetailsList.size()>0){
ProductDetails productDetails=productDetailsList.get(0);
List<BillingFlowParams.ProductDetailsParams> productDetailsParamsList= new ArrayList<>();
productDetailsParamsList.add(BillingFlowParams.ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.build());
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.build();
billingClient.launchBillingFlow((Activity) context, billingFlowParams);
}else {
Toast.makeText(context,"产品ID无效",Toast.LENGTH_SHORT).show();
}
}
}
);
}
}
public void queryPurchasesAsync(Activity context){
if(billingClient!=null){
if(!billingClient.isReady()){
Toast.makeText(context,"BillingClient is not ready",Toast.LENGTH_SHORT).show();
}
billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build(),
new PurchasesResponseListener() {
public void onQueryPurchasesResponse(
BillingResult billingResult,
List<Purchase> purchases) {
if(billingResult.getResponseCode()==BillingClient.BillingResponseCode.OK){
if(purchases!=null&&purchases.size()>0){
for (Purchase purchase:purchases){
handlePurchase(purchase);
}
}
}
}
}
);
}
}
}
最终总结:
鸿蒙arkui-x才是刚起步期望有更多开发能参加进来一同共同建设完善好生态。也期望国产体系和框架越来越好 最终呢 期望我都文章能协助到各位同学工作和学习 假如你觉得文章还不错麻烦给我三连 关注点赞和转发 谢谢