Android Setup Guide
Complete guide to configure flutter_inapp_purchase for Android with Google Play Billing Client v8.
Prerequisites
- Android API 21+ (Android 5.0+)
- Google Play Console Account with billing enabled
- Android Studio with Android SDK
- Physical device for testing (emulators have limited support)
Project Configuration
Update build.gradle
Ensure your android/app/build.gradle
has the correct configuration:
android {
compileSdkVersion 34
defaultConfig {
applicationId "com.yourapp.example"
minSdkVersion 21 // Required minimum for Billing Client v8
targetSdkVersion 34
versionCode 1
versionName "1.0"
}
buildTypes {
release {
// Signing configuration
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
ProGuard Configuration
If using ProGuard/R8, add these rules to android/app/proguard-rules.pro
:
# Flutter In-App Purchase
-keep class dev.hyo.** { *; }
-keep class com.android.vending.billing.**
-keep class com.google.android.gms.** { *; }
# Preserve billing client classes
-keep class com.android.billingclient.api.** { *; }
-dontwarn com.android.vending.billing.**
-dontwarn com.google.android.gms.**
# Keep annotation classes
-keepattributes *Annotation*
-keepattributes Signature
-keepattributes InnerClasses
-keepattributes EnclosingMethod
Permissions
The plugin automatically adds the required billing permission to your AndroidManifest.xml
:
<!-- This is added automatically by the plugin -->
<uses-permission android:name="com.android.vending.BILLING" />
Google Play Console Setup
Create Your App
- Sign in to Google Play Console
- Create a new app or select existing app
- Complete the app information and store listing
- Set up your app's content rating and target audience
Enable In-App Products
- Go to Monetize → Products → In-app products
- Click Create product to add new products
- Configure your product details:
Product ID: premium_upgrade
Name: Premium Upgrade
Description: Unlock all premium features
Price: $9.99
Product Types
Choose the appropriate product type:
- Managed Products: One-time purchases (non-consumable)
- Consumable Products: Can be purchased multiple times
- Subscriptions: Recurring billing (configured separately)
- Use descriptive, consistent naming:
premium_upgrade
,remove_ads
,coins_large_pack
- Avoid special characters and spaces
- Keep IDs consistent across platforms (iOS/Android)
App Signing & Release
Generate Signing Key
For production releases, you need a signed APK:
# Generate a new keystore (one-time setup)
keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
# Or use Android Studio: Build → Generate Signed Bundle/APK
Configure Signing
Create android/key.properties
:
storePassword=YOUR_STORE_PASSWORD
keyPassword=YOUR_KEY_PASSWORD
keyAlias=upload
storeFile=../upload-keystore.jks
Update android/app/build.gradle
:
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
Upload to Play Console
-
Build a signed app bundle:
flutter build appbundle --release
-
Upload
build/app/outputs/bundle/release/app-release.aab
to Play Console -
Create an Internal Testing track for testing in-app purchases
Testing Setup
Internal Testing
- In Play Console, go to Testing → Internal testing
- Create a new release and upload your signed app bundle
- Add test users by email addresses
- Send the testing link to your testers
License Testing
- Go to Setup → License testing
- Add Gmail accounts that should have testing access
- These accounts can test purchases without being charged
Test Accounts Configuration
Future<void> testAndroidPurchase() async {
try {
// Check connection state
final state = await FlutterInappPurchase.instance.getConnectionStateAndroid();
print('Connection state: $state');
// Initialize connection
await FlutterInappPurchase.instance.initConnection();
print('Billing client connected');
// Get products
final products = await FlutterInappPurchase.instance.getProducts([
'premium_upgrade',
'remove_ads'
]);
print('Found ${products.length} products');
// Test purchase
if (products.isNotEmpty) {
await FlutterInappPurchase.instance.requestPurchaseSimple(
productId: products.first.productId!,
type: PurchaseType.inapp,
);
}
} catch (e) {
print('Android test failed: $e');
}
}
Billing Client v8 Features
Enhanced Error Handling
FlutterInappPurchase.purchaseError.listen((error) {
if (error == null) return;
switch (error.code) {
case ErrorCode.eServiceUnavailable:
// Google Play services unavailable
showDialog('Please update Google Play services');
break;
case ErrorCode.eBillingUnavailable:
// Billing API version not supported
showDialog('In-app purchases not supported on this device');
break;
case ErrorCode.eItemUnavailable:
// Product not found or not available for purchase
showDialog('This item is currently unavailable');
break;
case ErrorCode.eDeveloperError:
// Invalid arguments provided to the API
print('Developer error: Check product configuration');
break;
default:
showDialog('Purchase failed: ${error.message}');
}
});
Connection State Monitoring
// Monitor connection state
Future<void> checkConnectionHealth() async {
final state = await FlutterInappPurchase.instance.getConnectionStateAndroid();
switch (state) {
case BillingClientState.disconnected:
// Reconnect if needed
await FlutterInappPurchase.instance.initConnection();
break;
case BillingClientState.connected:
// Ready for purchases
print('Billing client ready');
break;
case BillingClientState.closed:
// Client was closed, reinitialize
await FlutterInappPurchase.instance.initConnection();
break;
}
}
Common Issues & Solutions
Issue: "Billing service unavailable"
Solutions:
- Test on a real device with Google Play services
- Ensure you're signed in to a Google account
- Check that Google Play is up to date
- Verify your app is properly signed and uploaded
Issue: Products not loading
Solutions:
- Ensure products are active in Play Console
- Verify product IDs match exactly
- Check that your app is published (at least to Internal Testing)
- Wait for product propagation (can take a few hours)
Issue: "Item unavailable" error
Solutions:
- Verify the product exists and is active in Play Console
- Check that your app version includes the product
- Ensure you're testing with the correct account
- Confirm the product is available in your test region
Issue: Testing with wrong account
Solutions:
- Use an account added to License Testing
- Install the app from the Internal Testing link
- Don't use the developer account for testing purchases
- Clear Google Play Store cache if needed
Advanced Configuration
Obfuscated Account IDs
For enhanced security, use obfuscated account IDs:
await FlutterInappPurchase.instance.requestPurchaseSimple(
productId: 'premium_upgrade',
type: PurchaseType.inapp,
obfuscatedAccountId: 'user_account_123',
obfuscatedProfileId: 'profile_456',
);
Purchase Token Validation
Always validate purchases on your server:
FlutterInappPurchase.purchaseUpdated.listen((purchase) async {
if (purchase != null) {
// Send to your server for validation
final isValid = await validatePurchaseOnServer(purchase);
if (isValid) {
// Grant the purchased content
await grantPurchase(purchase);
// Acknowledge the purchase
await FlutterInappPurchase.instance.finishTransaction(
purchase,
isConsumable: false,
);
}
}
});
Next Steps
Need help? Check our troubleshooting guide or open an issue on GitHub.