AndroidでXamarin.Androidでアプリ内課金を行っているのですが、
AIDL から Google Play Billing Libraryへの移行が必要とのことで、
対応中なのですが、最初から壁にぶち当たり前に進めていません。
開発環境は、下記の通りです。
開発ソフト:Microsoft Visual Studio Community 2019
開発言語:Xamarin.Android
NuGet:Xamarin.Android.Google.Billing.Clinetを利用
(以前は、Plugin.InAppBillingを使っていました。)
困っていることは、
「BuyActivity」と「BillingSupport」というクラスを作り、
「BuyActivity」の「Resume」の中で、「BillingSupport」のインスタンスを作成しています。
この後、「BuyActivity」の中の「BuyInApp」関数を呼び出して、「BillingSupport.LoadPurchases_InApp」関数で
商品の読み込みを行おうとしているのですが、「QuerySkuDetailsAsync」関数が
応答がないようで、「OnSkuDetailsResponse」が呼び出されませんでした。
そのため、「SkuDetails」がnullのままとなり、処理が継続できません。
Googleの開発サイトなどを参照しているのですが、Xamarin.Androidの事例が
あまり見つからず、解決方法が分かっておりません。
試したこと、確認したことは下記の通りです。
1)「OnBillingSetupFinished」はOKがかえってきている。
2)QuerySkuDetailsAsyncをWait()すると、応答がないままフリーズする。
3)予約アイテム「android.test.purchased」を使っても応答はないまま。
以上です。
どなたか、お分かりになる方いらっしゃいましたら、
ご教授よろしくお願いいたします。
ソース抜粋
C#
1using System; 2using System.Collections.Generic; 3using System.Threading.Tasks; 4using Android.App; 5using Android.BillingClient.Api; 6using Android.Content; 7 8 class BillingSupport : Java.Lang.Object, IPurchasesUpdatedListener, IBillingClientStateListener, ISkuDetailsResponseListener, IConsumeResponseListener 9 { 10 Context Context; 11 private BillingClient billingClient; 12 public IList<SkuDetails> SkuDetails; 13 14 #region 購入開始 15 public BillingSupport(Activity activity) 16 { 17 Context = activity.ApplicationContext; 18 billingClient = BillingClient.NewBuilder(Context).EnablePendingPurchases().SetListener(this).Build(); 19 billingClient.StartConnection(this); 20 } 21 22 public void OnBillingSetupFinished(BillingResult p0) 23 { 24 if (p0.ResponseCode == BillingResponseCode.Ok) 25 { 26 Console.WriteLine("BILLING | startConnection | RESULT OK"); 27 // The BillingClient is ready. You can query purchases here. 28 } 29 else 30 { 31 Console.WriteLine("BILLING | startConnection | RESULT: $billingResponseCode"); 32 } 33 } 34 35 public void OnBillingServiceDisconnected() 36 { 37 Console.WriteLine("BILLING | onBillingServiceDisconnected | DISCONNECTED"); 38 // Try to restart the connection on the next request to 39 // Google Play by calling the startConnection() method. 40 } 41 42 #endregion 43 44 #region 商品の読み込み 45 //public void LoadPurchases_InApp() 46 //{ 47 48 // if (billingClient.IsReady) 49 // { 50 // List<string> skuList = new List<string>(); 51 // skuList.Add("android.test.purchased"); 52 // skuList.Add("android.test.canceled"); 53 // skuList.Add("android.test.item_unavailable"); 54 // SkuDetailsParams.Builder paramse = SkuDetailsParams.NewBuilder(); 55 // paramse.SetSkusList(skuList).SetType(BillingClient.SkuType.Inapp); 56 // billingClient.QuerySkuDetailsAsync(paramse.Build());(★応答がない) 57 // } 58 //} 59 //変更 REV001 60 public async Task<QuerySkuDetailsResult> LoadPurchases_InApp() 61 { 62 if (BillingClient == null || !BillingClient.IsReady) 63 { 64 await ConnectAsync(); 65 } 66 67 IList<string> skuList = new JavaList<string> 68 { 69 "android.test.purchased", 70 "android.test.canceled", 71 "android.test.item_unavailable" 72 }; 73 74 SkuDetailsParams paramse = SkuDetailsParams.NewBuilder().SetSkusList(skuList).SetType(BillingClient.SkuType.Inapp).Build(); 75 76 var querySkuDetailsResult = await BillingClient.QuerySkuDetailsAsync(paramse); 77 return querySkuDetailsResult; 78 } 79 } 80 //<=== 変更 REV001 81 82 public void OnSkuDetailsResponse(BillingResult p0, IList<SkuDetails> p1) 83 { 84 if (p0.ResponseCode == BillingResponseCode.Ok) 85 { 86 Console.WriteLine("querySkuDetailsAsync, responseCode: $responseCode"); 87 InitProductAdapter(p1); 88 } 89 else 90 { 91 Console.WriteLine("Can't querySkuDetailsAsync, responseCode: $responseCode"); 92 } 93 } 94 public void InitProductAdapter(IList<SkuDetails> skuDetails) 95 { 96 this.SkuDetails = skuDetails; 97 } 98 #endregion 99 100 101 #region 商品の購入 102 public void PurchaseInApp(SkuDetails skuDetails) 103 { 104 BillingFlowParams billingFlowParams = 105 BillingFlowParams.NewBuilder() 106 .SetSkuDetails(skuDetails) 107 .Build(); 108 109 billingClient.LaunchBillingFlow(this.Context as Activity, billingFlowParams); 110 } 111 112 //Response code 7 in OnPurchasesUpdated. It means: Item Already Owned. 113 public void OnPurchasesUpdated(BillingResult p0, IList<Purchase> p1) 114 { 115 if (p0.ResponseCode == BillingResponseCode.Ok && p1 != null) 116 { 117 foreach (Purchase purchase in p1) 118 { 119 HandlePurchase(purchase); 120 } 121 } 122 else if (p0.ResponseCode == BillingResponseCode.UserCancelled) 123 { 124 // ユーザーが購入フローをキャンセルした場合に発生したエラーを処理します。 125 } 126 else 127 { 128 // 他のエラー コードを処理します。 129 } 130 } 131 132 public void HandlePurchase(Purchase purchase) 133 { 134 if (purchase.PurchaseState == PurchaseState.Purchased) 135 { 136 // ユーザーに権利を付与します。 137 138 // 購入がまだ承認されていない場合は、購入を承認します。 139 if (!purchase.IsAcknowledged) 140 { 141 AcknowledgePurchaseParams acknowledgePurchaseParams = 142 AcknowledgePurchaseParams.NewBuilder() 143 .SetPurchaseToken(purchase.PurchaseToken) 144 .Build(); 145 billingClient.AcknowledgePurchase(acknowledgePurchaseParams, (IAcknowledgePurchaseResponseListener)this); 146 } 147 148 } 149 else if (purchase.PurchaseState == PurchaseState.Pending) 150 { 151 // Here you can confirm to the user that they've started the pending 152 // purchase, and to complete it, they should follow instructions that 153 // are given to them. You can also choose to remind the user in the 154 // future to complete the purchase if you detect that it is still 155 // pending. 156 } 157 } 158 #endregion 159 160 #region アイテム消費 161 public void ConsumePurchases(string purchaseToken) 162 { 163 ConsumeParams consumeParams = 164 ConsumeParams.NewBuilder() 165 .SetPurchaseToken(purchaseToken) 166 .Build(); 167 billingClient.ConsumeAsync(consumeParams); 168 } 169 170 public void OnConsumeResponse(BillingResult p0, string p1) 171 { 172 if (p0.ResponseCode == BillingResponseCode.Ok && p1 != null) 173 { 174 Console.WriteLine("onPurchases Updated consumeAsync, purchases token removed: $purchaseToken"); 175 } 176 else 177 { 178 Console.WriteLine("onPurchases some troubles happened: $responseCode"); 179 } 180 } 181 182 #endregion 183 }
C#
1 public class BuyActivity : Activity 2 { 3 BillingSupport billingSupport; 4 5 protected override void OnCreate(Bundle savedInstanceState) 6 { 7 //省略 8 } 9 10 protected override void OnResume() 11 { 12 base.OnResume(); 13 14 #region Google Play 請求サービス起動 15 billingSupport = new BillingSupport(this); 16 #endregion 17 } 18 19 //private void BuyInApp() 20 //{ 21 // //商品の詳細情報を取得 22 // billingSupport.LoadPurchases_InApp(); 23 24 // //商品を購入 25 // billingSupport.PurchaseInApp(billingSupport.SkuDetails[0]);//★ここでSkuDetailsがnullになる 26 //} 27 //変更 REV001 ===> 28 private async Task BuyInApp() 29 { 30 //商品の詳細情報を取得 31 var response = await billingSupport.LoadPurchases_InApp(); 32 33 //商品を購入/消費 34 billingSupport.PurchaseInApp(billingSupport.SkuDetails[0]); 35 } 36 //<=== 変更 REV001 37 }
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/16 13:34
2020/08/16 14:18
2020/08/16 14:22