@@ -65,7 +65,7 @@ public void SetListener(Action<BillingResult, IList<Purchase>> handler)
65
65
}
66
66
}
67
67
68
- public Task < BillingResult > AcknowledgePurchaseAsync ( AcknowledgePurchaseParams acknowledgePurchaseParams )
68
+ public async Task < BillingResult > AcknowledgePurchaseAsync ( AcknowledgePurchaseParams acknowledgePurchaseParams )
69
69
{
70
70
var tcs = new TaskCompletionSource < BillingResult > ( ) ;
71
71
@@ -76,10 +76,12 @@ public Task<BillingResult> AcknowledgePurchaseAsync(AcknowledgePurchaseParams ac
76
76
77
77
AcknowledgePurchase ( acknowledgePurchaseParams , listener ) ;
78
78
79
- return tcs . Task ;
79
+ var result = await tcs . Task ;
80
+ GC . KeepAlive ( listener ) ;
81
+ return result ;
80
82
}
81
83
82
- public Task < ConsumeResult > ConsumeAsync ( ConsumeParams consumeParams )
84
+ public async Task < ConsumeResult > ConsumeAsync ( ConsumeParams consumeParams )
83
85
{
84
86
var tcs = new TaskCompletionSource < ConsumeResult > ( ) ;
85
87
@@ -94,7 +96,9 @@ public Task<ConsumeResult> ConsumeAsync(ConsumeParams consumeParams)
94
96
95
97
Consume ( consumeParams , listener ) ;
96
98
97
- return tcs . Task ;
99
+ var result = await tcs . Task ;
100
+ GC . KeepAlive ( listener ) ;
101
+ return result ;
98
102
}
99
103
100
104
const string QueryPurchaseHistoryNotSupported = "QueryPurchaseHistory method was removed in Billing Client v8.0.0. Use QueryPurchasesAsync instead. See: https://developer.android.com/google/play/billing/migrate" ;
@@ -125,7 +129,7 @@ public Task<QuerySkuDetailsResult> QuerySkuDetailsAsync(SkuDetailsParams skuDeta
125
129
throw new NotSupportedException ( QuerySkuDetailsNotSupported ) ;
126
130
}
127
131
128
- public Task < QueryProductDetailsResult > QueryProductDetailsAsync ( QueryProductDetailsParams productDetailsParams )
132
+ public async Task < QueryProductDetailsResult > QueryProductDetailsAsync ( QueryProductDetailsParams productDetailsParams )
129
133
{
130
134
var tcs = new TaskCompletionSource < QueryProductDetailsResult > ( ) ;
131
135
@@ -136,10 +140,12 @@ public Task<QueryProductDetailsResult> QueryProductDetailsAsync(QueryProductDeta
136
140
137
141
QueryProductDetails ( productDetailsParams , listener ) ;
138
142
139
- return tcs . Task ;
143
+ var result = await tcs . Task ;
144
+ GC . KeepAlive ( listener ) ;
145
+ return result ;
140
146
}
141
147
142
- public Task < QueryPurchasesResult > QueryPurchasesAsync ( QueryPurchasesParams purchasesParams )
148
+ public async Task < QueryPurchasesResult > QueryPurchasesAsync ( QueryPurchasesParams purchasesParams )
143
149
{
144
150
var tcs = new TaskCompletionSource < QueryPurchasesResult > ( ) ;
145
151
@@ -154,10 +160,12 @@ public Task<QueryPurchasesResult> QueryPurchasesAsync(QueryPurchasesParams purch
154
160
155
161
QueryPurchases ( purchasesParams , listener ) ;
156
162
157
- return tcs . Task ;
163
+ var result = await tcs . Task ;
164
+ GC . KeepAlive ( listener ) ;
165
+ return result ;
158
166
}
159
167
160
- public Task < BillingResult > StartConnectionAsync ( Action onDisconnected = null )
168
+ public async Task < BillingResult > StartConnectionAsync ( Action onDisconnected = null )
161
169
{
162
170
var tcs = new TaskCompletionSource < BillingResult > ( ) ;
163
171
@@ -174,7 +182,9 @@ public Task<BillingResult> StartConnectionAsync(Action onDisconnected = null)
174
182
175
183
StartConnection ( listener ) ;
176
184
177
- return tcs . Task ;
185
+ var result = await tcs . Task ;
186
+ GC . KeepAlive ( listener ) ;
187
+ return result ;
178
188
}
179
189
180
190
public void StartConnection ( Action < BillingResult > setupFinished , Action onDisconnected )
@@ -196,15 +206,7 @@ internal class InternalAcknowledgePurchaseResponseListener : Java.Lang.Object, I
196
206
public Action < BillingResult > AcknowledgePurchaseResponseHandler { get ; set ; }
197
207
198
208
public void OnAcknowledgePurchaseResponse ( BillingResult result )
199
- {
200
- // Create a copy of the BillingResult to ensure it stays alive after the callback
201
- var resultCopy = BillingResult . NewBuilder ( )
202
- . SetResponseCode ( ( int ) result . ResponseCode )
203
- . SetDebugMessage ( result . DebugMessage )
204
- . SetOnPurchasesUpdatedSubResponseCode ( result . OnPurchasesUpdatedSubResponseCode )
205
- . Build ( ) ;
206
- AcknowledgePurchaseResponseHandler ? . Invoke ( resultCopy ) ;
207
- }
209
+ => AcknowledgePurchaseResponseHandler ? . Invoke ( result ) ;
208
210
}
209
211
210
212
internal class InternalBillingClientStateListener : Java . Lang . Object , IBillingClientStateListener
@@ -217,76 +219,36 @@ public void OnBillingServiceDisconnected()
217
219
=> BillingServiceDisconnectedHandler ? . Invoke ( ) ;
218
220
219
221
public void OnBillingSetupFinished ( BillingResult result )
220
- {
221
- // Create a copy of the BillingResult to ensure it stays alive after the callback
222
- var resultCopy = BillingResult . NewBuilder ( )
223
- . SetResponseCode ( ( int ) result . ResponseCode )
224
- . SetDebugMessage ( result . DebugMessage )
225
- . SetOnPurchasesUpdatedSubResponseCode ( result . OnPurchasesUpdatedSubResponseCode )
226
- . Build ( ) ;
227
- BillingSetupFinishedHandler ? . Invoke ( resultCopy ) ;
228
- }
222
+ => BillingSetupFinishedHandler ? . Invoke ( result ) ;
229
223
}
230
224
231
225
internal class InternalConsumeResponseListener : Java . Lang . Object , IConsumeResponseListener
232
226
{
233
227
public Action < BillingResult , string > ConsumeResponseHandler { get ; set ; }
234
228
public void OnConsumeResponse ( BillingResult result , string str )
235
- {
236
- // Create a copy of the BillingResult to ensure it stays alive after the callback
237
- var resultCopy = BillingResult . NewBuilder ( )
238
- . SetResponseCode ( ( int ) result . ResponseCode )
239
- . SetDebugMessage ( result . DebugMessage )
240
- . SetOnPurchasesUpdatedSubResponseCode ( result . OnPurchasesUpdatedSubResponseCode )
241
- . Build ( ) ;
242
- ConsumeResponseHandler ? . Invoke ( resultCopy , str ) ;
243
- }
229
+ => ConsumeResponseHandler ? . Invoke ( result , str ) ;
244
230
}
245
231
246
232
internal class InternalPriceChangeConfirmationListener : Java . Lang . Object //, IPriceChangeConfirmationListener
247
233
{
248
234
public Action < BillingResult > PriceChangeConfirmationHandler { get ; set ; }
249
235
public void OnPriceChangeConfirmationResult ( BillingResult result )
250
- {
251
- // Create a copy of the BillingResult to ensure it stays alive after the callback
252
- var resultCopy = BillingResult . NewBuilder ( )
253
- . SetResponseCode ( ( int ) result . ResponseCode )
254
- . SetDebugMessage ( result . DebugMessage )
255
- . SetOnPurchasesUpdatedSubResponseCode ( result . OnPurchasesUpdatedSubResponseCode )
256
- . Build ( ) ;
257
- PriceChangeConfirmationHandler ? . Invoke ( resultCopy ) ;
258
- }
236
+ => PriceChangeConfirmationHandler ? . Invoke ( result ) ;
259
237
}
260
238
261
239
internal class InternalPurchaseHistoryResponseListener : Java . Lang . Object , IPurchaseHistoryResponseListener
262
240
{
263
241
public Action < BillingResult , IList < PurchaseHistoryRecord > > PurchaseHistoryResponseHandler { get ; set ; }
264
242
265
243
public void OnPurchaseHistoryResponse ( BillingResult result , IList < PurchaseHistoryRecord > history )
266
- {
267
- // Create a copy of the BillingResult to ensure it stays alive after the callback
268
- var resultCopy = BillingResult . NewBuilder ( )
269
- . SetResponseCode ( ( int ) result . ResponseCode )
270
- . SetDebugMessage ( result . DebugMessage )
271
- . SetOnPurchasesUpdatedSubResponseCode ( result . OnPurchasesUpdatedSubResponseCode )
272
- . Build ( ) ;
273
- PurchaseHistoryResponseHandler ? . Invoke ( resultCopy , history ) ;
274
- }
244
+ => PurchaseHistoryResponseHandler ? . Invoke ( result , history ) ;
275
245
}
276
246
277
247
internal class InternalPurchasesUpdatedListener : Java . Lang . Object , IPurchasesUpdatedListener
278
248
{
279
249
public Action < BillingResult , IList < Purchase > > PurchasesUpdatedHandler { get ; set ; }
280
250
public void OnPurchasesUpdated ( BillingResult result , IList < Purchase > purchases )
281
- {
282
- // Create a copy of the BillingResult to ensure it stays alive after the callback
283
- var resultCopy = BillingResult . NewBuilder ( )
284
- . SetResponseCode ( ( int ) result . ResponseCode )
285
- . SetDebugMessage ( result . DebugMessage )
286
- . SetOnPurchasesUpdatedSubResponseCode ( result . OnPurchasesUpdatedSubResponseCode )
287
- . Build ( ) ;
288
- PurchasesUpdatedHandler ? . Invoke ( resultCopy , purchases ) ;
289
- }
251
+ => PurchasesUpdatedHandler ? . Invoke ( result , purchases ) ;
290
252
}
291
253
292
254
[ Obsolete ( "Use QueryProductDetailsAsync(QueryProductDetailsParams) instead" ) ]
@@ -305,15 +267,8 @@ internal class InternalProductDetailsResponseListener : Java.Lang.Object, IProdu
305
267
public void OnProductDetailsResponse ( BillingResult result , QueryProductDetailsResult queryResult )
306
268
{
307
269
queryResult ??= new ( ) ;
308
- // Create a copy of the BillingResult to ensure it stays alive after the callback
309
- // The original result may be disposed by the native side, causing ObjectDisposedException
310
- var resultCopy = BillingResult . NewBuilder ( )
311
- . SetResponseCode ( ( int ) result . ResponseCode )
312
- . SetDebugMessage ( result . DebugMessage )
313
- . SetOnPurchasesUpdatedSubResponseCode ( result . OnPurchasesUpdatedSubResponseCode )
314
- . Build ( ) ;
315
- queryResult . Result = resultCopy ;
316
- ProductDetailsResponseHandler ? . Invoke ( resultCopy , queryResult ) ;
270
+ queryResult . Result = result ;
271
+ ProductDetailsResponseHandler ? . Invoke ( result , queryResult ) ;
317
272
}
318
273
}
319
274
0 commit comments