nfc_wallet_suppression 1.0.0-dev.1
nfc_wallet_suppression: ^1.0.0-dev.1 copied to clipboard
Lightweight plugin to handle NFC wallet suppression in Flutter
Flutter NFC Wallet Suppression Plugin #
A lightweight Flutter plugin that suppresses NFC wallet presentation — preventing Apple Wallet, Google Wallet, and other payment apps from automatically popping up when your NFC-enabled device detects contactless payment terminals or NFC tags.
🎯 Problem This Solves: When users with NFC-enabled phones (iPhone 7+, most modern Android devices) approach an NFC reader while your app is open, the system automatically shows wallet/payment apps. This plugin gives your app exclusive control over NFC interactions instead.
⚠️ Important Notes:
- Only needed for NFC-enabled devices - Phones without NFC hardware don't have this issue
- Suppression only - This plugin does NOT read or write NFC tags
- Best for: Loyalty cards, ticketing, access control, and custom NFC experiences
📋 Table of Contents #
- Key Features
- Installation
- Platform Setup
- API Usage
- Testing
- Troubleshooting
- Example App
- Contributing
- License
Key Features #
- ✅ Suppress NFC wallet presentation - Stop Apple Wallet/Google Wallet from auto-appearing on NFC-enabled devices
- ✅ Simple API - Three methods: request, release, and check suppression status
- ✅ Cross-platform - Works on iOS (PassKit) and Android (NFC Adapter)
- ✅ All platforms supported - Graceful fallback on web/desktop (returns
notSupported) - ✅ Lifecycle-aware - Automatic cleanup when app backgrounds
- ✅ Type-safe status - Detailed status enum for handling different scenarios
Build Status #
Installation #
flutter pub add nfc_wallet_suppression
Platform Setup #
Android #
Minimum: Android 5.0+ (API 21)
Setup: None required! NFC permission is automatically added. App must be in foreground when requesting suppression.
Note: Only suppresses wallet on devices with NFC hardware. Non-NFC devices don't need suppression.
iOS #
Minimum: iOS 13.0+ (this plugin's floor; the PassKit suppression API is available from iOS 9.0+)
Your app's actual minimum is whichever is higher — this plugin's floor or the one your Flutter version requires. Flutter 3.47, for example, requires iOS 15.0.
Note: Only suppresses wallet on devices with NFC hardware (iPhone 7+). Older iPhones without NFC don't need suppression.
Setup Required:
-
Request Apple Entitlement
- Email apple-pay-inquiries@apple.com
- Request
com.apple.developer.passkit.pass-presentation-suppression - Explain your use case (may take several days for approval)
-
Configure Developer Portal
- Enable
Pass Presentation Suppressionin your App ID - Regenerate provisioning profiles
- Enable
-
Add Entitlement File (
ios/Runner/Runner.entitlements):<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.developer.passkit.pass-presentation-suppression</key> <true/> </dict> </plist>
⚠️ Without the approved entitlement, calls will fail on real iOS devices.
API Usage #
Quick Example #
import 'package:nfc_wallet_suppression/nfc_wallet_suppression.dart';
// Request NFC wallet suppression
try {
SuppressionStatus status = await NfcWalletSuppression.requestSuppression();
if (status == SuppressionStatus.suppressed) {
print('✓ Suppression active - you can now handle NFC interactions');
} else {
print('⚠ Suppression status: ${status.name}');
}
} catch (error) {
print('Error requesting NFC wallet suppression: $error');
}
// Check if NFC wallet is currently suppressed
try {
bool isSuppressed = await NfcWalletSuppression.isSuppressed();
print('Is NFC wallet suppressed? $isSuppressed');
} catch (e) {
print('Error checking suppression status: $e');
}
// Release NFC wallet suppression when done
try {
SuppressionStatus status = await NfcWalletSuppression.releaseSuppression();
print('Suppression released: ${status.name}');
} catch (e) {
print('Error releasing NFC wallet suppression: $e');
}
API Methods #
| Method | Returns | Description |
|---|---|---|
requestSuppression() |
Future<SuppressionStatus> |
Request wallet suppression |
releaseSuppression() |
Future<SuppressionStatus> |
Release suppression |
isSuppressed() |
Future<bool> |
Check if currently suppressed |
SuppressionStatus Values #
The SuppressionStatus enum represents the result of suppression operations:
| Status | Description |
|---|---|
suppressed |
Suppression is active |
notSuppressed |
Suppression is not active (e.g. successfully released) |
unavailable |
No active suppression to release; or, during requestSuppression on Android, NFC is turned off or no activity is attached (recoverable) |
denied |
Permission denied — iOS: by the user or system; Android: a SecurityException on the NFC call |
cancelled |
User cancelled the permission prompt (iOS only) |
notSupported |
Suppression isn't supported — Android: no NFC hardware; iOS: PassKit reports it unsupported |
alreadyPresenting |
Wallet is already presenting a pass (iOS only) |
unknown |
An unexpected error occurred |
Important Notes:
- ✅ Only affects NFC-enabled devices (iPhone 7+, most modern Android phones)
- ✅ Auto-releases when app backgrounds or closes
- ❌ Does NOT read/write NFC tags
- ❌ Does NOT persist across app restarts
- ⚠️ Best-effort (not guaranteed on all devices due to manufacturer customizations)
Troubleshooting #
Common Issues:
| Issue | Platform | Solution |
|---|---|---|
| Entitlement not found | iOS | Ensure Apple approved the entitlement and it's in your provisioning profile |
| NFC not available | Android | Enable NFC in device settings |
| Auto-released | Both | Use WidgetsBindingObserver to re-request on app resume |
| Doesn't work on device | iOS | Test on physical iPhone 7+, verify entitlement in Xcode |
| Payment apps still appear | Android | Some manufacturers override behavior, test on multiple devices |
FAQ:
- Does this read NFC tags? No, it only suppresses wallet presentation.
- How long does suppression last? Until released or app backgrounds.
- Works in simulator? Limited - always test on physical devices with NFC.
Testing #
This plugin includes comprehensive testing utilities. See the TESTING.md guide for:
- Using
FakeNfcWalletSuppressionfor unit tests - Pre-configured test scenarios
- Widget testing examples
- Integration testing guidance
Quick example:
import 'package:nfc_wallet_suppression/testing.dart';
final fake = NfcWalletSuppressionTestScenarios.supportedDevice();
NfcWalletSuppressionPlatform.instance = fake;
// Now your tests use the fake implementation
Example App #
See the example/ directory for a complete working example with lifecycle management and error handling.
cd example && flutter run
Privacy #
This plugin includes a privacy manifest (ios/nfc_wallet_suppression/Sources/nfc_wallet_suppression/PrivacyInfo.xcprivacy) that declares:
- No tracking (NSPrivacyTracking: false)
- No data collection (NSPrivacyCollectedDataTypes: empty)
- No required reason APIs (NSPrivacyAccessedAPITypes: empty)
- No tracking domains (NSPrivacyTrackingDomains: empty)
The PassKit APIs used for NFC wallet suppression do not access sensitive user data, do not track users, and do not fall under Apple's required reason API categories. The privacy manifest is included as a best practice for App Store compliance.
Contributing #
Contributions welcome! See CONTRIBUTING.md for guidelines.
Additional Resources #
API Docs • Report Issues • CHANGELOG • Apple PassKit • Android NFC
License #
BSD 3-Clause License - See LICENSE for details.