in_app_subscription_bundle
This plugin provides a reusable, BLoC-based solution for handling in-app purchases and subscriptions in Flutter applications. It simplifies integration with the in_app_purchase
package for both Android and iOS, encapsulating complex subscription logic in an easy-to-use API.
Features
- BLoC-based architecture for clean state management.
- Support for iOS and Android.
- Handles non-consumable purchases.
- Full support for auto-renewable subscriptions.
Installation
Add this to your pubspec.yaml
:
dependencies:
flutter:
sdk: flutter
in_app_subscription_bundle: ^0.0.9
Usage
Step 1: Import the Plugin
import 'package:in_app_subscription_bundle/in_app_subscription_bundle.dart';
Step 2: Provide the BLoC
Wrap your app or screen with BlocProvider
to provide access to SubsBlocNew
:
// main.dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: ProductsView(),
);
}
}
// Expected Product view class
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => SubsBlocNew(
context: context,
checkSubscriptionApi: "",
saveSubscriptionApiUrl: "",
subscriptionProductIds: ["monthly_plan", "yearly_plan"],
subscriptionPlans:SubscriptionPlans(
plans: [
Plans(
planId: "monthly_plan",
planDuration: const Duration(days: 30),
sandBoxDuration: const Duration(minutes: 30),
),
Plans(
planId: "yearly_plan",
planDuration: const Duration(days: 365),
sandBoxDuration: const Duration(hours: 3, minutes: 30),
),
],
),
activePlanSaveInApi: false,
planActiveCheckFromApi: false,
isSandbox: kDebugMode ? true : false,
sharedSecret: ""
),
child: const _ProductsBody(),
);
}
Step 3: Build the UI with BLoC
Use BlocBuilder
and BlocListener
to react to state changes:
class _ProductsBody extends StatefulWidget {
const _ProductsBody({Key? key}) : super(key: key);
@override
State<_ProductsBody> createState() => _ProductsBodyState();
}
class _ProductsBodyState extends State<_ProductsBody> {
@override
void initState() {
super.initState();
// Dispatch here, when Bloc is ready and context is mounted
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<SubsBlocNew>().add(
SubscriptionInitEvent(context: context),
);
});
}
@override
Widget build(BuildContext context) {
final state = context.watch<SubsBlocNew>().state;
return Scaffold(
appBar: AppBar(
toolbarHeight: 50,
title: const Text("Products"),
),
body: SizedBox(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
child: Column(
children: [
ListWidget(
itemCount: state.products.length,
itemBuilder: (p0, p1) {
final product = state.products[p1];
// Skip rendering if it's free
if (product.rawPrice == 0.0) {
return const SizedBox.shrink();
}
return GestureDetector(
onTap: () {
context.read<SubsBlocNew>().add(
ChangeSelectedItemEvent(p1),
);
},
child: Container(
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: state.products[state.selectedItem].id==product.id?
Colors.green : Colors.lightGreenAccent,
borderRadius: BorderRadius.circular(10),
),
child: ListTile(
title: Text(product.title),
subtitle: Text(product.description),
trailing: Text(product.price),
),
),
);
},
),
CustomButton(
width: 50.sw,
text: "Subscribe",
onTap:() {
context.read<SubsBlocNew>().add(
BuyProductEvent(context: context, restore: false),
);
},
)
],
),
),
),
);
}
}
Libraries
- api_calling/api_client
- api_calling/api_repo
- api_calling/response_model
- features/subscripton/bloc/subs_bloc
- features/subscripton/bloc/subscription_event
- features/subscripton/bloc/subscription_state
- features/subscripton/model/cancel_subscroption_request
- features/subscripton/model/check_subscription_response
- features/subscripton/model/subscription_plans
- features/subscripton/model/subscription_products_response
- features/subscripton/model/subscription_request
- features/subscripton/service/subscription_service
- in_app_subscription_bundle
- in_app_subscription_bundle_method_channel
- in_app_subscription_bundle_platform_interface
- subscription_manager
- utills/app_logs
- utills/common_util_methods