Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[in_app_purchase] Remove the custom analysis options, fix failing lints. #3220

Merged
merged 2 commits into from
Oct 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions packages/in_app_purchase/analysis_options.yaml

This file was deleted.

13 changes: 11 additions & 2 deletions packages/in_app_purchase/example/lib/consumable_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,31 @@
import 'dart:async';
import 'package:shared_preferences/shared_preferences.dart';

// This is just a development prototype for locally storing consumables. Do not
// use this.
/// A store of consumable items.
///
/// This is a development prototype tha stores consumables in the shared
/// preferences. Do not use this in real world apps.
class ConsumableStore {
static const String _kPrefKey = 'consumables';
static Future<void> _writes = Future.value();

/// Adds a consumable with ID `id` to the store.
///
/// The consumable is only added after the returned Future is complete.
static Future<void> save(String id) {
_writes = _writes.then((void _) => _doSave(id));
return _writes;
}

/// Consumes a consumable with ID `id` from the store.
///
/// The consumable was only consumed after the returned Future is complete.
static Future<void> consume(String id) {
_writes = _writes.then((void _) => _doConsume(id));
return _writes;
}

/// Returns the list of consumables from the store.
static Future<List<String>> load() async {
return (await SharedPreferences.getInstance()).getStringList(_kPrefKey) ??
[];
Expand Down
12 changes: 6 additions & 6 deletions packages/in_app_purchase/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ void main() {
// [enablePendingPurchases](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.Builder.html#enablependingpurchases)
// as part of initializing the app.
InAppPurchaseConnection.enablePendingPurchases();
runApp(MyApp());
runApp(_MyApp());
}

const bool kAutoConsume = true;
const bool _kAutoConsume = true;

const String _kConsumableId = 'consumable';
const List<String> _kProductIds = <String>[
Expand All @@ -25,12 +25,12 @@ const List<String> _kProductIds = <String>[
'subscription'
];

class MyApp extends StatefulWidget {
class _MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
class _MyAppState extends State<_MyApp> {
final InAppPurchaseConnection _connection = InAppPurchaseConnection.instance;
StreamSubscription<List<PurchaseDetails>> _subscription;
List<String> _notFoundIds = [];
Expand Down Expand Up @@ -257,7 +257,7 @@ class _MyAppState extends State<MyApp> {
if (productDetails.id == _kConsumableId) {
_connection.buyConsumable(
purchaseParam: purchaseParam,
autoConsume: kAutoConsume || Platform.isIOS);
autoConsume: _kAutoConsume || Platform.isIOS);
} else {
_connection.buyNonConsumable(
purchaseParam: purchaseParam);
Expand Down Expand Up @@ -374,7 +374,7 @@ class _MyAppState extends State<MyApp> {
}
}
if (Platform.isAndroid) {
if (!kAutoConsume && purchaseDetails.productID == _kConsumableId) {
if (!_kAutoConsume && purchaseDetails.productID == _kConsumableId) {
await InAppPurchaseConnection.instance
.consumePurchase(purchaseDetails);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'purchase_wrapper.dart';
import 'sku_details_wrapper.dart';
import 'enum_converters.dart';

/// Method identifier for the OnPurchaseUpdated method channel method.
@visibleForTesting
const String kOnPurchasesUpdated =
'PurchasesUpdatedListener#onPurchasesUpdated(int, List<Purchase>)';
Expand Down Expand Up @@ -51,6 +52,9 @@ typedef void PurchasesUpdatedListener(PurchasesResultWrapper purchasesResult);
class BillingClient {
bool _enablePendingPurchases = false;

/// Creates a billing client.
///
/// The `onPurchasesUpdated` parameter must not be null.
BillingClient(PurchasesUpdatedListener onPurchasesUpdated) {
assert(onPurchasesUpdated != null);
channel.setMethodCallHandler(callHandler);
Expand Down Expand Up @@ -273,6 +277,7 @@ class BillingClient {
}));
}

/// The method call handler for [channel].
@visibleForTesting
Future<void> callHandler(MethodCall call) async {
switch (call.method) {
Expand Down Expand Up @@ -309,36 +314,47 @@ enum BillingResponse {
// WARNING: Changes to this class need to be reflected in our generated code.
// Run `flutter packages pub run build_runner watch` to rebuild and watch for
// further changes.
/// The requested feature is not supported by Play Store on the current device.
@JsonValue(-2)
featureNotSupported,

/// The play Store service is not connected now - potentially transient state.
@JsonValue(-1)
serviceDisconnected,

/// Success.
@JsonValue(0)
ok,

/// The user pressed back or canceled a dialog.
@JsonValue(1)
userCanceled,

/// The network connection is down.
@JsonValue(2)
serviceUnavailable,

/// The billing API version is not supported for the type requested.
@JsonValue(3)
billingUnavailable,

/// The requested product is not available for purchase.
@JsonValue(4)
itemUnavailable,

/// Invalid arguments provided to the API.
@JsonValue(5)
developerError,

/// Fatal error during the API action.
@JsonValue(6)
error,

/// Failure to purchase since item is already owned.
@JsonValue(7)
itemAlreadyOwned,

/// Failure to consume since item is not owned.
@JsonValue(8)
itemNotOwned,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ part 'enum_converters.g.dart';
/// Use these in `@JsonSerializable()` classes by annotating them with
/// `@BillingResponseConverter()`.
class BillingResponseConverter implements JsonConverter<BillingResponse, int> {
/// Default const constructor.
const BillingResponseConverter();

@override
Expand All @@ -28,6 +29,7 @@ class BillingResponseConverter implements JsonConverter<BillingResponse, int> {
/// Use these in `@JsonSerializable()` classes by annotating them with
/// `@SkuTypeConverter()`.
class SkuTypeConverter implements JsonConverter<SkuType, String> {
/// Default const constructor.
const SkuTypeConverter();

@override
Expand All @@ -52,6 +54,7 @@ class _SerializedEnums {
/// `@PurchaseStateConverter()`.
class PurchaseStateConverter
implements JsonConverter<PurchaseStateWrapper, int> {
/// Default const constructor.
const PurchaseStateConverter();

@override
Expand All @@ -63,6 +66,9 @@ class PurchaseStateConverter
int toJson(PurchaseStateWrapper object) =>
_$PurchaseStateWrapperEnumMap[object];

/// Converts the purchase state stored in `object` to a [PurchaseStatus].
///
/// [PurchaseStateWrapper.unspecified_state] is mapped to [PurchaseStatus.error].
PurchaseStatus toPurchaseStatus(PurchaseStateWrapper object) {
switch (object) {
case PurchaseStateWrapper.pending:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ part 'purchase_wrapper.g.dart';
@JsonSerializable()
@PurchaseStateConverter()
class PurchaseWrapper {
/// Creates a purchase wrapper with the given purchase details.
@visibleForTesting
PurchaseWrapper(
{@required this.orderId,
Expand All @@ -38,6 +39,7 @@ class PurchaseWrapper {
@required this.isAcknowledged,
@required this.purchaseState});

/// Factory for creating a [PurchaseWrapper] from a [Map] with the purchase details.
factory PurchaseWrapper.fromJson(Map map) => _$PurchaseWrapperFromJson(map);

@override
Expand Down Expand Up @@ -132,6 +134,7 @@ class PurchaseWrapper {
// For now, we keep them separated classes to be consistent with Android's BillingClient implementation.
@JsonSerializable()
class PurchaseHistoryRecordWrapper {
/// Creates a [PurchaseHistoryRecordWrapper] with the given record details.
@visibleForTesting
PurchaseHistoryRecordWrapper({
@required this.purchaseTime,
Expand All @@ -142,6 +145,7 @@ class PurchaseHistoryRecordWrapper {
@required this.developerPayload,
});

/// Factory for creating a [PurchaseHistoryRecordWrapper] from a [Map] with the record details.
factory PurchaseHistoryRecordWrapper.fromJson(Map map) =>
_$PurchaseHistoryRecordWrapperFromJson(map);

Expand Down Expand Up @@ -197,11 +201,13 @@ class PurchaseHistoryRecordWrapper {
@JsonSerializable()
@BillingResponseConverter()
class PurchasesResultWrapper {
/// Creates a [PurchasesResultWrapper] with the given purchase result details.
PurchasesResultWrapper(
{@required this.responseCode,
@required this.billingResult,
@required this.purchasesList});

/// Factory for creating a [PurchaseResultWrapper] from a [Map] with the result details.
factory PurchasesResultWrapper.fromJson(Map<String, dynamic> map) =>
_$PurchasesResultWrapperFromJson(map);

Expand Down Expand Up @@ -240,9 +246,11 @@ class PurchasesResultWrapper {
@JsonSerializable()
@BillingResponseConverter()
class PurchasesHistoryResult {
/// Creates a [PurchasesHistoryResult] with the provided history.
PurchasesHistoryResult(
{@required this.billingResult, @required this.purchaseHistoryRecordList});

/// Factory for creating a [PurchasesHistoryResult] from a [Map] with the history result details.
factory PurchasesHistoryResult.fromJson(Map<String, dynamic> map) =>
_$PurchasesHistoryResultFromJson(map);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ part 'sku_details_wrapper.g.dart';
@JsonSerializable()
@SkuTypeConverter()
class SkuDetailsWrapper {
/// Creates a [SkuDetailsWrapper] with the given purchase details.
@visibleForTesting
SkuDetailsWrapper({
@required this.description,
Expand Down Expand Up @@ -47,6 +48,7 @@ class SkuDetailsWrapper {
factory SkuDetailsWrapper.fromJson(Map map) =>
_$SkuDetailsWrapperFromJson(map);

/// Textual description of the product.
final String description;

/// Trial period in ISO 8601 format.
Expand Down Expand Up @@ -78,6 +80,8 @@ class SkuDetailsWrapper {

/// Applies to [SkuType.subs], formatted in ISO 8601.
final String subscriptionPeriod;

/// The product's title.
final String title;

/// The [SkuType] of the product.
Expand Down Expand Up @@ -143,6 +147,7 @@ class SkuDetailsWrapper {
/// Returned by [BillingClient.querySkuDetails].
@JsonSerializable()
class SkuDetailsResponseWrapper {
/// Creates a [SkuDetailsResponseWrapper] with the given purchase details.
@visibleForTesting
SkuDetailsResponseWrapper(
{@required this.billingResult, this.skuDetailsList});
Expand Down
5 changes: 5 additions & 0 deletions packages/in_app_purchase/lib/src/channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@

import 'package:flutter/services.dart';

/// Method channel for the plugin's platform<-->Dart calls (all but the
/// ios->Dart calls which are carried over the [callbackChannel]).
const MethodChannel channel =
MethodChannel('plugins.flutter.io/in_app_purchase');

/// Method channel for the plugin's ios->Dart calls.
// This is in a separate channel due to historic reasons only.
// TODO(cyanglaz): Remove this. https://github.com/flutter/flutter/issues/69225
const MethodChannel callbackChannel =
MethodChannel('plugins.flutter.io/in_app_purchase_callback');
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,25 @@ import '../../billing_client_wrappers.dart';
/// This translates various `StoreKit` calls and responses into the
/// generic plugin API.
class AppStoreConnection implements InAppPurchaseConnection {
/// Returns the singleton instance of the [AppStoreConnection] that should be
/// used across the app.
static AppStoreConnection get instance => _getOrCreateInstance();
static AppStoreConnection _instance;
static SKPaymentQueueWrapper _skPaymentQueueWrapper;
static _TransactionObserver _observer;

/// Creates an [AppStoreConnection] object.
///
/// This constructor should only be used for testing, for any other purpose
/// get the connection from the [instance] getter.
@visibleForTesting
AppStoreConnection();

Stream<List<PurchaseDetails>> get purchaseUpdatedStream =>
_observer.purchaseUpdatedController.stream;

/// Callback handler for transaction status changes.
@visibleForTesting
static SKTransactionObserverWrapper get observer => _observer;

static AppStoreConnection _getOrCreateInstance() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@ class GooglePlayConnection
_purchaseUpdatedController = StreamController.broadcast();
;
}

/// Returns the singleton instance of the [GooglePlayConnection].
static GooglePlayConnection get instance => _getOrCreateInstance();
static GooglePlayConnection _instance;

Stream<List<PurchaseDetails>> get purchaseUpdatedStream =>
_purchaseUpdatedController.stream;
static StreamController<List<PurchaseDetails>> _purchaseUpdatedController;

/// The [BillingClient] that's abstracted by [GooglePlayConnection].
///
/// This field should not be used out of test code.
@visibleForTesting
final BillingClient billingClient;

Expand Down Expand Up @@ -161,6 +166,10 @@ class GooglePlayConnection
'The method <refreshPurchaseVerificationData> only works on iOS.');
}

/// Resets the connection instance.
///
/// The next call to [instance] will create a new instance. Should only be
/// used in tests.
@visibleForTesting
static void reset() => _instance = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,13 @@ abstract class InAppPurchaseConnection {
}

/// Which platform the request is on.
enum IAPSource { GooglePlay, AppStore }
enum IAPSource {
/// Google's Play Store.
GooglePlay,

/// Apple's App Store.
AppStore
}

/// Captures an error from the underlying purchase platform.
///
Expand All @@ -279,6 +285,7 @@ enum IAPSource { GooglePlay, AppStore }
/// * [ProductDetailsResponse] for error when querying product details.
/// * [PurchaseDetails] for error happened in purchase.
class IAPError {
/// Creates a new IAP error object with the given error details.
IAPError(
{@required this.source,
@required this.code,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'in_app_purchase_connection.dart';
/// This class unifies the BillingClient's [SkuDetailsWrapper] and StoreKit's [SKProductWrapper]. You can use the common attributes in
/// This class for simple operations. If you would like to see the detailed representation of the product, instead, use [skuDetails] on Android and [skProduct] on iOS.
class ProductDetails {
/// Creates a new product details object with the provided details.
ProductDetails(
{@required this.id,
@required this.title,
Expand Down Expand Up @@ -66,6 +67,7 @@ class ProductDetails {
///
/// A list of [ProductDetails] can be obtained from the this response.
class ProductDetailsResponse {
/// Creates a new [ProductDetailsResponse] with the provided response details.
ProductDetailsResponse(
{@required this.productDetails, @required this.notFoundIDs, this.error});

Expand Down
Loading