in_app_purchase 0.3.1+2

  • Readme
  • Changelog
  • Example
  • Installing
  • 95

In App Purchase #

A Flutter plugin for in-app purchases. Exposes APIs for making in-app purchases through the App Store (on iOS) and Google Play (on Android).

Features #

Add this to your Flutter app to:

  1. Show in app products that are available for sale from the underlying shop. Includes consumables, permanent upgrades, and subscriptions.
  2. Load in app products currently owned by the user according to the underlying shop.
  3. Send your user to the underlying store to purchase your products.

Getting Started #

This plugin is in beta. Please use with caution and file any potential issues you see on our issue tracker.

This plugin relies on the App Store and Google Play for making in app purchases. It exposes a unified surface, but you'll still need to understand and configure your app with each store to handle purchases using them. Both have extensive guides:

You can check out the example app README for steps on how to configure in app purchases in both stores.

Once you've configured your in app purchases in their respective stores, you're able to start using the plugin. There's two basic options available to you to use.

  1. in_app_purchase.dart, the generic idiommatic Flutter API. This exposes the most basic IAP-related functionality. The goal is that Flutter apps should be able to use this API surface on its own for the vast majority of cases. If you use this you should be able to handle most use cases for loading and making purchases. If you would like a more platform dependent approach, we also provide the second option as below.

  2. Dart APIs exposing the underlying platform APIs as directly as possible: store_kit_wrappers.dart and billing_client_wrappers.dart. These API surfaces should expose all the platform-specific behavior and allow for more fine-tuned control when needed. However if you use this you'll need to code your purchase handling logic significantly differently depending on which platform you're on.

Initializing the plugin #

// Subscribe to any incoming purchases at app initialization. These can
// propagate from either storefront so it's important to listen as soon as
// possible to avoid losing events.
class _MyAppState extends State<MyApp> {
  StreamSubscription<List<PurchaseDetails>> _subscription;

  void initState() {
    final Stream purchaseUpdates =
    _subscription = purchaseUpdates.listen((purchases) {

  void dispose() {

Connecting to the Storefront #

final bool available = await InAppPurchaseConnection.instance.isAvailable();
if (!available) {
  // The store cannot be reached or accessed. Update the UI accordingly.

Loading products for sale #

// Set literals require Dart 2.2. Alternatively, use `Set<String> _kIds = <String>['product1', 'product2'].toSet()`.
const Set<String> _kIds = {'product1', 'product2'};
final ProductDetailsResponse response = await InAppPurchaseConnection.instance.queryProductDetails(_kIds);
if (!response.notFoundIDs.isEmpty) {
    // Handle the error.
List<ProductDetails> products = response.productDetails;

Loading previous purchases #

final QueryPurchaseDetailsResponse response = await InAppPurchaseConnection.instance.queryPastPurchases();
if (response.error != null) {
    // Handle the error.
for (PurchaseDetails purchase in response.pastPurchases) {
    _verifyPurchase(purchase);  // Verify the purchase following the best practices for each storefront.
    _deliverPurchase(purchase); // Deliver the purchase to the user in your app.
    if (Platform.isIOS) {
        // Mark that you've delivered the purchase. Only the App Store requires
        // this final confirmation.

Note that the App Store does not have any APIs for querying consumable products, and Google Play considers consumable products to no longer be owned once they're marked as consumed and fails to return them here. For restoring these across devices you'll need to persist them on your own server and query that as well.

Making a purchase #

Both storefronts handle consumable and non-consumable products differently. If you're using InAppPurchaseConnection, you need to make a distinction here and call the right purchase method for each type.

final ProductDetails productDetails = ... // Saved earlier from queryPastPurchases().
final PurchaseParam purchaseParam = PurchaseParam(productDetails: productDetails);
if (_isConsumable(productDetails)) {
    InAppPurchaseConnection.instance.buyConsumable(purchaseParam: purchaseParam);
} else {
    InAppPurchaseConnection.instance.buyNonConsumable(purchaseParam: purchaseParam);

// From here the purchase flow will be handled by the underlying storefront.
// Updates will be delivered to the `InAppPurchaseConnection.instance.purchaseUpdatedStream`.

Development #

This plugin uses json_serializable for the many data structs passed between the underlying platform layers and Dart. After editing any of the serialized data structs, rebuild the serializers by running flutter packages pub run build_runner build --delete-conflicting-outputs. flutter packages pub run build_runner watch --delete-conflicting-outputs will watch the filesystem for changes.

0.3.1+2 #

  • Fix potential casting crash on Android v1 embedding when registering life cycle callbacks.
  • Remove hard-coded legacy xcode build setting.

0.3.1+1 #

  • Add pedantic to dev_dependency.

0.3.1 #

  • Android: Fix a bug where the BillingClient is disconnected when app goes to the background.
  • Android: Make sure the BillingClient object is disconnected before the activity is destroyed.
  • Android: Fix minor compiler warning.
  • Fix typo in CHANGELOG.

0.3.0+3 #

  • Fix pendingCompletePurchase flag status to allow to complete purchases.

0.3.0+2 #

  • Update te example app to avoid using deprecated api.

0.3.0+1 #

  • Fixing usage example. No functional changes.

0.3.0 #

  • Migrate the Google Play Library to 2.0.3.
    • Introduce a new class BillingResultWrapper which contains a detailed result of a BillingClient operation.
      • [Breaking Change]: All the BillingClient methods that previously return a BillingResponse now return a BillingResultWrapper, including: launchBillingFlow, startConnection and consumeAsync.
      • [Breaking Change]: The SkuDetailsResponseWrapper now contains a billingResult field in place of billingResponse field.
      • A billingResult field is added to the PurchasesResultWrapper.
    • Other Updates to the "billing_client_wrappers":
      • Updates to the PurchaseWrapper: Add developerPayload, purchaseState and isAcknowledged fields.
      • Updates to the SkuDetailsWrapper: Add originalPrice and originalPriceAmountMicros fields.
      • [Breaking Change]: The BillingClient.queryPurchaseHistory is updated to return a PurchasesHistoryResult, which contains a list of PurchaseHistoryRecordWrapper instead of PurchaseWrapper. A PurchaseHistoryRecordWrapper object has the same fields and values as A PurchaseWrapper object, except that a PurchaseHistoryRecordWrapper object does not contain isAutoRenewing, orderId and packageName.
      • Add a new BillingClient.acknowledgePurchase API. Starting from this version, the developer has to acknowledge any purchase on Android using this API within 3 days of purchase, or the user will be refunded. Note that if a product is "consumed" via BillingClient.consumeAsync, it is implicitly acknowledged.
      • [Breaking Change]: Added enablePendingPurchases in BillingClientWrapper. The application has to call this method before calling BillingClientWrapper.startConnection. See enablePendingPurchases for more information.
    • Updates to the "InAppPurchaseConnection":
      • [Breaking Change]: InAppPurchaseConnection.completePurchase now returns a Future<BillingResultWrapper> instead of Future<void>. A new optional parameter {String developerPayload} has also been added to the API. On Android, this API does not throw an exception anymore, it instead acknowledge the purchase. If a purchase is not completed within 3 days on Android, the user will be refunded.
      • [Breaking Change]: InAppPurchaseConnection.consumePurchase now returns a Future<BillingResultWrapper> instead of Future<BillingResponse>. A new optional parameter {String developerPayload} has also been added to the API.
      • A new boolean field pendingCompletePurchase has been added to the PurchaseDetails class. Which can be used as an indicator of whether to call InAppPurchaseConnection.completePurchase on the purchase.
      • [Breaking Change]: Added enablePendingPurchases in InAppPurchaseConnection. The application has to call this method when initializing the InAppPurchaseConnection on Android. See enablePendingPurchases for more information.
    • Misc: Some documentation updates reflecting the BillingClient migration and some documentation fixes.
    • Refer to Google Play Billing Library Release Note for a detailed information on the update.

0.2.2+6 #

  • Correct a comment.

0.2.2+5 #

  • Update version of json_annotation to ^3.0.0 and json_serializable to ^3.2.0. Resolve conflicts with other packages e.g. flutter_tools from sdk.

0.2.2+4 #

  • Remove the deprecated author: field from pubspec.yaml
  • Migrate the plugin to the pubspec platforms manifest.
  • Require Flutter SDK 1.10.0 or greater.

0.2.2+3 #

  • Fix failing pedantic lints. None of these fixes should have any change in functionality.

0.2.2+2 #

  • Include lifecycle dependency as a compileOnly one on Android to resolve potential version conflicts with other transitive libraries.

0.2.2+1 #

  • Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in build.gradle to support apps that has not been migrated to AndroidX.

0.2.2 #

  • Support the v2 Android embedder.
  • Update to AndroidX.
  • Migrate to using the new e2e test binding.
  • Add a e2e test.

0.2.1+5 #

  • Define clang module for iOS.
  • Fix iOS build warning.

0.2.1+4 #

  • Update and migrate iOS example project.

0.2.1+3 #

  • Android : Improved testability.

0.2.1+2 #

  • Android: Require a non-null Activity to use the launchBillingFlow method.

0.2.1+1 #

  • Remove skipped driver test.

0.2.1 #

  • iOS: Add currencyCode to priceLocale on productDetails.

0.2.0+8 #

  • Add dependency on androidx.annotation:annotation:1.0.0.

0.2.0+7 #

  • Make Gradle version compatible with the Android Gradle plugin version.

0.2.0+6 #

  • Add missing hashCode implementations.

0.2.0+5 #

  • iOS: Support unsupported UserInfo value types on NSError.

0.2.0+4 #

  • Fixed code error in and adjusted links to work on Pub.

0.2.0+3 #

  • Update the so that the code samples compile with the latest Flutter/Dart version.

0.2.0+2 #

  • Fix a google_play_connection purchase update listener regression introduced in 0.2.0+1.

0.2.0+1 #

  • Fix an issue the type is not casted before passing to PurchasesResultWrapper.fromJson.

0.2.0 #

  • [Breaking Change] Rename 'PurchaseError' to 'IAPError'.
  • [Breaking Change] Rename 'PurchaseSource' to 'IAPSource'.

0.1.1+3 #

  • Expanded description in pubspec.yaml and fixed typo in

0.1.1+2 #

  • Add missing template type parameter to invokeMethod calls.
  • Bump minimum Flutter version to 1.5.0.
  • Replace invokeMethod with invokeMapMethod wherever necessary.

0.1.1+1 #

  • Make AdditionalSteps(Used in the unit test) a void function.

0.1.1 #

  • Some error messages from iOS are slightly changed.
  • ProductDetailsResponse returned by queryProductDetails() now contains an PurchaseError object that represents any error that might occurred during the request.
  • If the device is not connected to the internet, queryPastPurchases() on iOS now have the error stored in the response instead of throwing.
  • Clean up minor iOS warning.
  • Example app shows how to handle error when calling queryProductDetails() and queryProductDetails().

0.1.0+4 #

  • Change the buy methods to return Future<bool> instead of void in order to propagate launchBillingFlow failures up through google_play_connection.

0.1.0+3 #

  • Guard against multiple onSetupFinished() calls.

0.1.0+2 #

  • Fix bug where error only purchases updates weren't propagated correctly in google_play_connection.dart.

0.1.0+1 #

  • Add more consumable handling to the example app.

0.1.0 #

Beta release.

  • Ability to list products, load previous purchases, and make purchases.
  • Simplified Dart API that's been unified for ease of use.
  • Platform specific APIs more directly exposing StoreKit and BillingClient.


  • 5ba657dc [in_app_purchase] Remove extraneous download logic (#1560)
  • 01bb8796 [in_app_purchase] Minor doc updates (#1555)
  • 1a4d493f [in_app_purchase] Only fetch owned purchases (#1540)
  • d63c51cf [in_app_purchase] Add auto-consume errors to PurchaseDetails (#1537)
  • 959da97f [in_app_purchase] Minor doc updates (#1536)
  • b82ae1a6 [in_app_purchase] Rename the unified API (#1517)
  • d1ad723a [in_app_purchase]remove SKDownloadWrapper and related code. (#1474)
  • 7c1e8b8a [in_app_purchase]make payment unified APIs (#1421)
  • 80233db6 [in_app_purchase] Add references to the original object for PurchaseDetails and ProductDetails (#1448)
  • 8c180f0d [in_app_purchase]load purchase (#1380)
  • e9f141bc [in_app_purchase] Iap refactor (#1381)
  • d3b3d60c add driver test command to cirrus (#1342)
  • aee12523 [in_app_purchase] refactoring and tests (#1322)
  • 6d7b4592 [in_app_purchase] Adds Dart BillingClient APIs for loading purchases (#1286)
  • 5567a9c8 [in_app_purchase]retrieve receipt (#1303)
  • 3475f1b7 [in_app_purchase]restore purchases (#1299)
  • a533148d [in_app_purchase] payment queue dart ios (#1249)
  • 10030840 [in_app_purchase] Minor bugfixes and code cleanup (#1284)
  • 347f508d [in_app_purchase] Fix CI formatting errors. (#1281)
  • fad02d87 [in_app_purchase] Java API for querying purchases (#1259)
  • bc501915 [In_app_purchase]SKProduct related fixes (#1252)
  • f92ba3a1 IAP make payment objc (#1231)
  • 62b82522 [IAP] Add the Dart API for launchBillingFlow (#1232)
  • b40a4acf [IAP] Add Java call for launchBillingFlow (#1230)
  • 4ff06cd1 [In_app_purchase]remove categories (#1222)
  • 0e72ca56 [In_app_purchase]fix requesthandler crash (#1199)
  • 81dff2be Iap getproductlist basic draft (#1169)
  • db139b28 Iap iOS add payment dart wrappers (#1178)
  • 2e5fbb9b Fix the param map passed down to the platform channel when calling querySkuDetails (#1194)
  • 4a84bac1 Mark some packages as unpublishable (#1193)
  • 51696552 Add a gradle warning to the AndroidX plugins (#1138)
  • 832ab832 Iap add payment objc translators (#1172)
  • d0e615cf Revert "IAP add payment translators in objc (#1126)" (#1171)
  • 09a5a36e IAP add payment translators in objc (#1126)
  • a100fbf9 Expose nslocale and expose currencySymbol instead of currencyCode to match android (#1162)
  • 1c982efd Using json serializer for skproduct wrapper and related classes (#1147)
  • 3039a261 Iap productlist ios (#1068)
  • 2a1593da [IAP] Update dev deps to match flutter_driver (#1118)
  • 9f87cbe5 [IAP] Update README (#1112)
  • 59e84d85 Migrate independent plugins to AndroidX (#1103)
  • a027ccd6 [IAP] Generate boilerplate serializers (#1090)
  • 909cf1c2 [IAP] Fetch SkuDetails from Google Play (#1084)
  • 6bbaa7e5 [IAP] Add missing license headers (#1083)
  • 5347e877 [IAP] Clean up Dart unit tests (#1082)
  • fe03e407 [IAP] Check if the payment processor is available (#1057)
  • 43ee28cf Fix Manifest versionCode not found (#1076)
  • 4d702ad7 Supress strong_mode_implicit_dynamic_method for invokeMethod calls. (#1065)
  • 809ccde7 Doc and build script updates to the IAP plugin (#1024)
  • 052b71a9 Update the IAP README (#933)
  • 54f9c4e2 Upgrade Android Gradle Plugin to 3.2.1 (#916)
  • ced3e99d Set all gradle-wrapper versions to 4.10.2 (#915)
  • eaa1388b Reconfigure Cirrus to use clang 7 (#905)
  • 9b153920 Update gradle dependencies. (#881)
  • 1aef7d92 Enable lint unnecessary_new (#701)

0.0.2 #

  • Added missing flutter_test package dependency.
  • Added missing flutter version requirements.

0.0.1 #

  • Initial release.


// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'consumable_store.dart';

void main() {
  // For play billing library 2.0 on Android, it is mandatory to call
  // [enablePendingPurchases](
  // as part of initializing the app.

const bool kAutoConsume = true;

const String _kConsumableId = 'consumable';
const List<String> _kProductIds = <String>[

class MyApp extends StatefulWidget {
  _MyAppState createState() => _MyAppState();

class _MyAppState extends State<MyApp> {
  final InAppPurchaseConnection _connection = InAppPurchaseConnection.instance;
  StreamSubscription<List<PurchaseDetails>> _subscription;
  List<String> _notFoundIds = [];
  List<ProductDetails> _products = [];
  List<PurchaseDetails> _purchases = [];
  List<String> _consumables = [];
  bool _isAvailable = false;
  bool _purchasePending = false;
  bool _loading = true;
  String _queryProductError;

  void initState() {
    Stream purchaseUpdated =
    _subscription = purchaseUpdated.listen((purchaseDetailsList) {
    }, onDone: () {
    }, onError: (error) {
      // handle error here.

  Future<void> initStoreInfo() async {
    final bool isAvailable = await _connection.isAvailable();
    if (!isAvailable) {
      setState(() {
        _isAvailable = isAvailable;
        _products = [];
        _purchases = [];
        _notFoundIds = [];
        _consumables = [];
        _purchasePending = false;
        _loading = false;

    ProductDetailsResponse productDetailResponse =
        await _connection.queryProductDetails(_kProductIds.toSet());
    if (productDetailResponse.error != null) {
      setState(() {
        _queryProductError = productDetailResponse.error.message;
        _isAvailable = isAvailable;
        _products = productDetailResponse.productDetails;
        _purchases = [];
        _notFoundIds = productDetailResponse.notFoundIDs;
        _consumables = [];
        _purchasePending = false;
        _loading = false;

    if (productDetailResponse.productDetails.isEmpty) {
      setState(() {
        _queryProductError = null;
        _isAvailable = isAvailable;
        _products = productDetailResponse.productDetails;
        _purchases = [];
        _notFoundIds = productDetailResponse.notFoundIDs;
        _consumables = [];
        _purchasePending = false;
        _loading = false;

    final QueryPurchaseDetailsResponse purchaseResponse =
        await _connection.queryPastPurchases();
    if (purchaseResponse.error != null) {
      // handle query past purchase error..
    final List<PurchaseDetails> verifiedPurchases = [];
    for (PurchaseDetails purchase in purchaseResponse.pastPurchases) {
      if (await _verifyPurchase(purchase)) {
    List<String> consumables = await ConsumableStore.load();
    setState(() {
      _isAvailable = isAvailable;
      _products = productDetailResponse.productDetails;
      _purchases = verifiedPurchases;
      _notFoundIds = productDetailResponse.notFoundIDs;
      _consumables = consumables;
      _purchasePending = false;
      _loading = false;

  void dispose() {

  Widget build(BuildContext context) {
    List<Widget> stack = [];
    if (_queryProductError == null) {
          children: [
    } else {
        child: Text(_queryProductError),
    if (_purchasePending) {
          children: [
              opacity: 0.3,
              child: const ModalBarrier(dismissible: false, color: Colors.grey),
              child: CircularProgressIndicator(),

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('IAP Example'),
        body: Stack(
          children: stack,

  Card _buildConnectionCheckTile() {
    if (_loading) {
      return Card(child: ListTile(title: const Text('Trying to connect...')));
    final Widget storeHeader = ListTile(
      leading: Icon(_isAvailable ? Icons.check : Icons.block,
          color: _isAvailable ? : ThemeData.light().errorColor),
      title: Text(
          'The store is ' + (_isAvailable ? 'available' : 'unavailable') + '.'),
    final List<Widget> children = <Widget>[storeHeader];

    if (!_isAvailable) {
          title: Text('Not connected',
              style: TextStyle(color: ThemeData.light().errorColor)),
          subtitle: const Text(
              'Unable to connect to the payments processor. Has this app been configured correctly? See the example README for instructions.'),
    return Card(child: Column(children: children));

  Card _buildProductList() {
    if (_loading) {
      return Card(
          child: (ListTile(
              leading: CircularProgressIndicator(),
              title: Text('Fetching products...'))));
    if (!_isAvailable) {
      return Card();
    final ListTile productHeader = ListTile(title: Text('Products for Sale'));
    List<ListTile> productList = <ListTile>[];
    if (_notFoundIds.isNotEmpty) {
          title: Text('[${_notFoundIds.join(", ")}] not found',
              style: TextStyle(color: ThemeData.light().errorColor)),
          subtitle: Text(
              'This app needs special configuration to run. Please see example/ for instructions.')));

    // This loading previous purchases code is just a demo. Please do not use this as it is.
    // In your app you should always verify the purchase data using the `verificationData` inside the [PurchaseDetails] object before trusting it.
    // We recommend that you use your own server to verity the purchase data.
    Map<String, PurchaseDetails> purchases =
        Map.fromEntries( purchase) {
      if (purchase.pendingCompletePurchase) {
      return MapEntry<String, PurchaseDetails>(purchase.productID, purchase);
      (ProductDetails productDetails) {
        PurchaseDetails previousPurchase = purchases[];
        return ListTile(
            title: Text(
            subtitle: Text(
            trailing: previousPurchase != null
                ? Icon(Icons.check)
                : FlatButton(
                    child: Text(productDetails.price),
                    textColor: Colors.white,
                    onPressed: () {
                      PurchaseParam purchaseParam = PurchaseParam(
                          productDetails: productDetails,
                          applicationUserName: null,
                          sandboxTesting: true);
                      if ( == _kConsumableId) {
                            purchaseParam: purchaseParam,
                            autoConsume: kAutoConsume || Platform.isIOS);
                      } else {
                            purchaseParam: purchaseParam);

    return Card(
            Column(children: <Widget>[productHeader, Divider()] + productList));

  Card _buildConsumableBox() {
    if (_loading) {
      return Card(
          child: (ListTile(
              leading: CircularProgressIndicator(),
              title: Text('Fetching consumables...'))));
    if (!_isAvailable || _notFoundIds.contains(_kConsumableId)) {
      return Card();
    final ListTile consumableHeader =
        ListTile(title: Text('Purchased consumables'));
    final List<Widget> tokens = id) {
      return GridTile(
        child: IconButton(
          icon: Icon(
            size: 42.0,
          splashColor: Colors.yellowAccent,
          onPressed: () => consume(id),
    return Card(
        child: Column(children: <Widget>[
        crossAxisCount: 5,
        children: tokens,
        shrinkWrap: true,
        padding: EdgeInsets.all(16.0),

  Future<void> consume(String id) async {
    await ConsumableStore.consume(id);
    final List<String> consumables = await ConsumableStore.load();
    setState(() {
      _consumables = consumables;

  void showPendingUI() {
    setState(() {
      _purchasePending = true;

  void deliverProduct(PurchaseDetails purchaseDetails) async {
    // IMPORTANT!! Always verify a purchase purchase details before delivering the product.
    if (purchaseDetails.productID == _kConsumableId) {
      List<String> consumables = await ConsumableStore.load();
      setState(() {
        _purchasePending = false;
        _consumables = consumables;
    } else {
      setState(() {
        _purchasePending = false;

  void handleError(IAPError error) {
    setState(() {
      _purchasePending = false;

  Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) {
    // IMPORTANT!! Always verify a purchase before delivering the product.
    // For the purpose of an example, we directly return true.
    return Future<bool>.value(true);

  void _handleInvalidPurchase(PurchaseDetails purchaseDetails) {
    // handle invalid purchase here if  _verifyPurchase` failed.

  void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
    purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
      if (purchaseDetails.status == PurchaseStatus.pending) {
      } else {
        if (purchaseDetails.status == PurchaseStatus.error) {
        } else if (purchaseDetails.status == PurchaseStatus.purchased) {
          bool valid = await _verifyPurchase(purchaseDetails);
          if (valid) {
          } else {
        if (Platform.isAndroid) {
          if (!kAutoConsume && purchaseDetails.productID == _kConsumableId) {
            await InAppPurchaseConnection.instance
        if (purchaseDetails.pendingCompletePurchase) {
          await InAppPurchaseConnection.instance

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  in_app_purchase: ^0.3.1+2

2. Install it

You can install packages from the command line:

with Flutter:

$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:in_app_purchase/in_app_purchase.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Mar 27, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Health suggestions

Fix lib/src/store_kit_wrappers/sk_product_wrapper.g.dart. (-2.48 points)

Analysis of lib/src/store_kit_wrappers/sk_product_wrapper.g.dart reported 5 hints:

line 20 col 22: The declaration '_$SkProductResponseWrapperToJson' isn't referenced.

line 35 col 22: The declaration '_$SKProductSubscriptionPeriodWrapperToJson' isn't referenced.

line 97 col 22: The declaration '_$SKProductDiscountWrapperToJson' isn't referenced.

line 134 col 22: The declaration '_$SKProductWrapperToJson' isn't referenced.

line 153 col 22: The declaration '_$SKPriceLocaleWrapperToJson' isn't referenced.

Fix lib/src/billing_client_wrappers/enum_converters.g.dart. (-1.99 points)

Analysis of lib/src/billing_client_wrappers/enum_converters.g.dart reported 4 hints:

line 9 col 18: The declaration '_$_SerializedEnumsFromJson' isn't referenced.

line 9 col 18: Name non-constant identifiers using lowerCamelCase.

line 17 col 22: The declaration '_$_SerializedEnumsToJson' isn't referenced.

line 17 col 22: Name non-constant identifiers using lowerCamelCase.

Fix lib/src/billing_client_wrappers/purchase_wrapper.g.dart. (-1.99 points)

Analysis of lib/src/billing_client_wrappers/purchase_wrapper.g.dart reported 4 hints:

line 26 col 22: The declaration '_$PurchaseWrapperToJson' isn't referenced.

line 53 col 22: The declaration '_$PurchaseHistoryRecordWrapperToJson' isn't referenced.

line 75 col 22: The declaration '_$PurchasesResultWrapperToJson' isn't referenced.

line 93 col 22: The declaration '_$PurchasesHistoryResultToJson' isn't referenced.

Fix additional 4 files with analysis or formatting issues. (-4.48 points)

Additional issues in the following files:

  • lib/src/store_kit_wrappers/enum_converters.g.dart (4 hints)
  • lib/src/billing_client_wrappers/sku_details_wrapper.g.dart (3 hints)
  • lib/src/in_app_purchase/google_play_connection.dart (1 hint)
  • lib/src/store_kit_wrappers/sk_payment_queue_wrapper.g.dart (1 hint)


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.3.0 <3.0.0
async ^2.0.8 2.4.1
collection ^1.14.11 1.14.11 1.14.12
flutter 0.0.0
json_annotation ^3.0.0 3.0.1
meta ^1.1.6 1.1.8
Transitive dependencies
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
build_runner ^1.0.0
e2e ^0.2.0
json_serializable ^3.2.0
pedantic ^1.8.0
shared_preferences ^0.5.2
test ^1.5.2