是否可以从 Xamarin Android 应用直接使用 Google Play BillingClient?
Is it possible to directly consume the Google Play BillingClient from a Xamarin Android app?
我正在努力将订阅集成到 Xamarin Android 应用程序中。我可以在网上找到的所有特定于 Xamarin 的示例都使用来自 Montemagno 等人的 Plugin.InAppBilling
。
这当然很方便,但是为了尽职调查,我想看看直接消费BillingClient
类需要什么,如[=27]中所述=] 的文档(例如,此处:https://developer.android.com/google/play/billing/billing_java_kotlin)。
奇怪的是,Xamarin 文档显示了如何直接使用 iOS 计费 类,而不是 Android 的计费。我认为 Xamarin.GooglePlayServices
NuGet 程序包可能包含我需要的内容,但我没有看到似乎与计费直接相关的内容。
如有指点,将不胜感激。
TL;DR:是的,你可以...(我用它...)
"Implement Google Play Billing" 文档中显示的 类 是最终使用 Billing AIDL 的包装器 类。该 AIDL 接口是实际计费 API 并且 AIDL 定义了对它的那些 IPC 调用(这不仅用于跨进程方法调用,还用于安全性)...
Android Studio,通过 Gradle,自动导入计费包装器和 AIDL,并在您将计费 api 依赖项添加到 build.gradle
时为您设置一切文件。 (当然,这不是通过 Visual Studio 和 MSBuild 的选项...)
Montemagno 的 Android 应用内结算直接使用 AIDL 接口方法并以跨平台方式包装它们...
要使用 Java 包装器 类,基本步骤是从 Jcenter Maven 存储库中获取 aar (billing-1.1.aar
),创建一个 Xamarin.Android 绑定库,添加 aar,修复警告(如果需要,还有命名空间)并在您的 Xamarin.Android 应用程序项目中引用该库...
现在您可以直接使用 Google 文档,以及一些较小的 Xamarin.Android/C# 规范化,即:
// I did not alter the original Java namespace in the binding lib
using Com.Android.Billingclient.Api;
~~~
var billingClient = BillingClient
.NewBuilder(this)
.SetListener(this)
.Build();
~~~
var flowParams = BillingFlowParams
.NewBuilder()
.SetSku("WhosebugXamarinTag")
.SetType("Answer")
.Build();
使用Android.BillingClient.Api.BillingClient;
https://www.nuget.org/packages/Xamarin.Android.Google.BillingClient/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.BillingClient.Api;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using static Android.BillingClient.Api.BillingClient;
namespace Android.Basic.Core
{
public class BilingSupport : Java.Lang.Object, IPurchasesUpdatedListener, IBillingClientStateListener, ISkuDetailsResponseListener, IConsumeResponseListener
{
Context Context;
public IList<SkuDetails> SkuDetails;
Android.BillingClient.Api.BillingClient billingClient;
private List<string> skuList = new List<string>() { "get_5_coins", "get_10_coins" };
public BilingSupport(Context context)
{
this.Context = context;
billingClient = Android.BillingClient.Api.BillingClient.NewBuilder(this.Context).SetListener(this).Build();
billingClient.StartConnection(this);
}
public void LoadPurchases()
{
if (billingClient.IsReady)
{
var paramse = SkuDetailsParams.NewBuilder().SetSkusList(skuList).SetType(Android.BillingClient.Api.BillingClient.SkuType.Inapp).Build();
billingClient.QuerySkuDetails(paramse, this);
}
}
public void PurchaseNow(SkuDetails skuDetails)
{
var billingFlowParams = BillingFlowParams.NewBuilder().SetSkuDetails(skuDetails).Build();
billingClient.LaunchBillingFlow(this.Context as Activity, billingFlowParams);
}
public void OnBillingServiceDisconnected()
{
Console.WriteLine("BILLING | onBillingServiceDisconnected | DISCONNECTED");
}
public void OnBillingSetupFinished(BillingResult p0)
{
if (p0.ResponseCode == BillingResponseCode.Ok)
{
Console.WriteLine("BILLING | startConnection | RESULT OK");
}
else
{
Console.WriteLine("BILLING | startConnection | RESULT: $billingResponseCode");
}
}
//Response code 7 in OnPurchasesUpdated.It means: Item Already Owned.
public void OnPurchasesUpdated(BillingResult p0, IList<Purchase> p1)
{
}
public void OnSkuDetailsResponse(BillingResult p0, IList<SkuDetails> p1)
{
if (p0.ResponseCode == BillingResponseCode.Ok)
{
Console.WriteLine("querySkuDetailsAsync, responseCode: $responseCode");
InitProductAdapter(p1);
}
else
{
Console.WriteLine("Can't querySkuDetailsAsync, responseCode: $responseCode");
}
}
public event EventHandler<IList<SkuDetails>> SkuDetailsLoaded;
public void InitProductAdapter(IList<SkuDetails> skuDetails)
{
this.SkuDetails = skuDetails;
this.SkuDetailsLoaded(this, this.SkuDetails);
}
public void ClearOrConsumeAllPurchases()
{
var querylist = billingClient.QueryPurchases(Android.BillingClient.Api.BillingClient.SkuType.Inapp).PurchasesList;
foreach (var query in querylist)
{
var consumeParams = ConsumeParams.NewBuilder().SetPurchaseToken(query.PurchaseToken).Build();
billingClient.Consume(consumeParams, this);
}
}
public void OnConsumeResponse(BillingResult p0, string p1)
{
if (p0.ResponseCode == BillingResponseCode.Ok && p1 != null)
{
Console.WriteLine("onPurchases Updated consumeAsync, purchases token removed: $purchaseToken");
}
else
{
Console.WriteLine("onPurchases some troubles happened: $responseCode");
}
}
}
}
我正在努力将订阅集成到 Xamarin Android 应用程序中。我可以在网上找到的所有特定于 Xamarin 的示例都使用来自 Montemagno 等人的 Plugin.InAppBilling
。
这当然很方便,但是为了尽职调查,我想看看直接消费BillingClient
类需要什么,如[=27]中所述=] 的文档(例如,此处:https://developer.android.com/google/play/billing/billing_java_kotlin)。
奇怪的是,Xamarin 文档显示了如何直接使用 iOS 计费 类,而不是 Android 的计费。我认为 Xamarin.GooglePlayServices
NuGet 程序包可能包含我需要的内容,但我没有看到似乎与计费直接相关的内容。
如有指点,将不胜感激。
TL;DR:是的,你可以...(我用它...)
"Implement Google Play Billing" 文档中显示的 类 是最终使用 Billing AIDL 的包装器 类。该 AIDL 接口是实际计费 API 并且 AIDL 定义了对它的那些 IPC 调用(这不仅用于跨进程方法调用,还用于安全性)...
Android Studio,通过 Gradle,自动导入计费包装器和 AIDL,并在您将计费 api 依赖项添加到 build.gradle
时为您设置一切文件。 (当然,这不是通过 Visual Studio 和 MSBuild 的选项...)
Montemagno 的 Android 应用内结算直接使用 AIDL 接口方法并以跨平台方式包装它们...
要使用 Java 包装器 类,基本步骤是从 Jcenter Maven 存储库中获取 aar (billing-1.1.aar
),创建一个 Xamarin.Android 绑定库,添加 aar,修复警告(如果需要,还有命名空间)并在您的 Xamarin.Android 应用程序项目中引用该库...
现在您可以直接使用 Google 文档,以及一些较小的 Xamarin.Android/C# 规范化,即:
// I did not alter the original Java namespace in the binding lib
using Com.Android.Billingclient.Api;
~~~
var billingClient = BillingClient
.NewBuilder(this)
.SetListener(this)
.Build();
~~~
var flowParams = BillingFlowParams
.NewBuilder()
.SetSku("WhosebugXamarinTag")
.SetType("Answer")
.Build();
使用Android.BillingClient.Api.BillingClient; https://www.nuget.org/packages/Xamarin.Android.Google.BillingClient/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.BillingClient.Api;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using static Android.BillingClient.Api.BillingClient;
namespace Android.Basic.Core
{
public class BilingSupport : Java.Lang.Object, IPurchasesUpdatedListener, IBillingClientStateListener, ISkuDetailsResponseListener, IConsumeResponseListener
{
Context Context;
public IList<SkuDetails> SkuDetails;
Android.BillingClient.Api.BillingClient billingClient;
private List<string> skuList = new List<string>() { "get_5_coins", "get_10_coins" };
public BilingSupport(Context context)
{
this.Context = context;
billingClient = Android.BillingClient.Api.BillingClient.NewBuilder(this.Context).SetListener(this).Build();
billingClient.StartConnection(this);
}
public void LoadPurchases()
{
if (billingClient.IsReady)
{
var paramse = SkuDetailsParams.NewBuilder().SetSkusList(skuList).SetType(Android.BillingClient.Api.BillingClient.SkuType.Inapp).Build();
billingClient.QuerySkuDetails(paramse, this);
}
}
public void PurchaseNow(SkuDetails skuDetails)
{
var billingFlowParams = BillingFlowParams.NewBuilder().SetSkuDetails(skuDetails).Build();
billingClient.LaunchBillingFlow(this.Context as Activity, billingFlowParams);
}
public void OnBillingServiceDisconnected()
{
Console.WriteLine("BILLING | onBillingServiceDisconnected | DISCONNECTED");
}
public void OnBillingSetupFinished(BillingResult p0)
{
if (p0.ResponseCode == BillingResponseCode.Ok)
{
Console.WriteLine("BILLING | startConnection | RESULT OK");
}
else
{
Console.WriteLine("BILLING | startConnection | RESULT: $billingResponseCode");
}
}
//Response code 7 in OnPurchasesUpdated.It means: Item Already Owned.
public void OnPurchasesUpdated(BillingResult p0, IList<Purchase> p1)
{
}
public void OnSkuDetailsResponse(BillingResult p0, IList<SkuDetails> p1)
{
if (p0.ResponseCode == BillingResponseCode.Ok)
{
Console.WriteLine("querySkuDetailsAsync, responseCode: $responseCode");
InitProductAdapter(p1);
}
else
{
Console.WriteLine("Can't querySkuDetailsAsync, responseCode: $responseCode");
}
}
public event EventHandler<IList<SkuDetails>> SkuDetailsLoaded;
public void InitProductAdapter(IList<SkuDetails> skuDetails)
{
this.SkuDetails = skuDetails;
this.SkuDetailsLoaded(this, this.SkuDetails);
}
public void ClearOrConsumeAllPurchases()
{
var querylist = billingClient.QueryPurchases(Android.BillingClient.Api.BillingClient.SkuType.Inapp).PurchasesList;
foreach (var query in querylist)
{
var consumeParams = ConsumeParams.NewBuilder().SetPurchaseToken(query.PurchaseToken).Build();
billingClient.Consume(consumeParams, this);
}
}
public void OnConsumeResponse(BillingResult p0, string p1)
{
if (p0.ResponseCode == BillingResponseCode.Ok && p1 != null)
{
Console.WriteLine("onPurchases Updated consumeAsync, purchases token removed: $purchaseToken");
}
else
{
Console.WriteLine("onPurchases some troubles happened: $responseCode");
}
}
}
}