I’m trying to integrate the upi_pay package for Flutter, but no UPI apps are being displayed on my device without any error messages. I’ve been implementing this package from https://pub.dev/packages/upi_pay and testing on my personal device, but I’m not seeing any UPI payment applications in the list. How can I resolve this issue and ensure the UPI apps are properly detected?
The upi_pay package for Flutter may fail to detect UPI apps due to Android permission changes, package detection limitations, or missing configuration. To resolve this issue, you’ll need to properly configure Android permissions, add the <queries> element for Android 11+, and potentially use alternative detection methods for custom UPI schemes.
Contents
- Common Causes of UPI App Detection Issues
- Step-by-Step Solutions
- Alternative Detection Methods
- Testing and Debugging Tips
- Best Practices for UPI Integration
Common Causes of UPI App Detection Issues
Several factors can prevent the upi_pay package from detecting UPI apps on your device:
Android Permission Changes
Starting from Android 10 (API 29), Google implemented stricter privacy controls that limit app visibility. For Android 11 (API 30) and above, you must explicitly declare which apps you want to query in your AndroidManifest.xml. Without proper permission declarations, the package cannot detect installed UPI applications.
Package Detection Limitations
The upi_pay package relies on detecting apps that implement the standard “upi” scheme. However, many UPI apps like PhonePe, Paytm, and others use custom schemes (e.g., “phonepe”, “paytm”) that aren’t automatically detected by the package’s standard discovery mechanism.
Missing Configuration Elements
Key configuration elements may be missing from your Flutter project’s Android setup, particularly the <queries> element required for Android 11+ and proper intent filters for UPI scheme handling.
Step-by-Step Solutions
1. Update AndroidManifest.xml with Proper Permissions
Add the following to your android/app/src/main/AndroidManifest.xml:
<manifest ...>
<!-- Add this for Android 11+ app visibility -->
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="upi" />
</intent>
<!-- Add specific UPI app packages you want to detect -->
<package android:name="com.google.android.apps.nbu.paisa.user" /> <!-- Google Pay -->
<package android:name="com.phonepe.app" /> <!-- PhonePe -->
<package android:name="net.one97.paytm" /> <!-- Paytm -->
<package android:name="in.amazon.mShop.android.shopping" /> <!-- Amazon Pay -->
<package android:name="in.org.npci.upiapp" /> <!-- BHIM UPI -->
</queries>
<application ...>
<!-- Your existing application configuration -->
</application>
</manifest>
2. Update Android Gradle Configuration
Ensure your android/build.gradle file has the minimum SDK version set appropriately:
android {
defaultConfig {
minSdkVersion 19
targetSdkVersion 33
// ... other configurations
}
}
3. Use Enhanced Detection Methods
The upi_pay package provides a way to detect both standard and custom UPI schemes. Use the enhanced detection method:
import 'package:upi_pay/upi_pay.dart';
Future<void> fetchUpiApps() async {
try {
// Get all UPI apps including custom schemes
List<UpiApp> apps = await UpiPay.getInstalledUpiApps();
// Check if apps were detected
if (apps.isEmpty) {
print("No UPI apps found. Please install a UPI app.");
return;
}
// Filter to show only detected apps
List<UpiApp> detectedApps = apps.where((app) => app.appInstalled).toList();
print("Detected UPI apps: ${detectedApps.length}");
for (var app in detectedApps) {
print("- ${app.appName} (${app.appPackageName})");
}
} on PlatformException catch (e) {
print("Error fetching UPI apps: ${e.message}");
}
}
4. Handle Custom UPI Schemes
For UPI apps using custom schemes, implement direct deep linking as a fallback:
Future<void> launchUpiPayment({
required String upiId,
required String amount,
required String name,
}) async {
// Try package detection first
List<UpiApp> apps = await UpiPay.getInstalledUpiApps();
UpiApp? selectedApp = apps.firstWhere(
(app) => app.appInstalled && app.appName.toLowerCase().contains('gpay'),
orElse: () => apps.firstWhere(
(app) => app.appInstalled,
orElse: () => UpiApp(appName: 'Unknown', appPackageName: '', upiScheme: 'upi'),
),
);
if (selectedApp.appInstalled) {
// Use the detected app
bool success = await UpiPay.initiateTransaction(
app: selectedApp,
payeeUpiId: upiId,
payeeName: name,
amount: amount,
transactionRefId: 'txn_${DateTime.now().millisecondsSinceEpoch}',
transactionNote: 'Payment',
);
if (!success) {
// Fallback to direct URL scheme
await _launchDirectUpiLink(upiId, amount, name);
}
} else {
// Direct deep linking as primary method
await _launchDirectUpiLink(upiId, amount, name);
}
}
Future<void> _launchDirectUpiLink(String upiId, String amount, String name) async {
final url = 'upi://pay?pa=$upiId&pn=$name&am=$amount&cu=INR&tn=Payment';
final uri = Uri.parse(url);
if (await canLaunchUrl(uri)) {
await launchUrl(uri);
} else {
// Handle case where no UPI app can handle the URL
print('No UPI app found to handle the payment request');
}
}
Alternative Detection Methods
1. Use Alternative UPI Packages
Consider using alternative packages that may have better detection capabilities:
- flutter_upi_india: Offers enhanced UPI app detection with custom scheme support
- upi_payment_flutter: Provides comprehensive UPI payment integration
- easy_upi_payment: Simplified UPI payment with better error handling
2. Manual Package Detection
For complete control, implement manual UPI app detection:
Future<List<String>> getUpiApps() async {
final List<String> upiApps = [];
// Common UPI app package names
final List<String> upiAppPackages = [
'com.google.android.apps.nbu.paisa.user', // Google Pay
'com.phonepe.app', // PhonePe
'net.one97.paytm', // Paytm
'in.amazon.mShop.android.shopping', // Amazon Pay
'in.org.npci.upiapp', // BHIM UPI
'com.sbi.upi', // SBI Pay
'com.ybl', // Yono SBI
];
for (String packageName in upiAppPackages) {
try {
final bool isInstalled = await _isAppInstalled(packageName);
if (isInstalled) {
upiApps.add(packageName);
}
} catch (e) {
print('Error checking $packageName: $e');
}
}
return upiApps;
}
Future<bool> _isAppInstalled(String packageName) async {
final packageManager = PackageName();
try {
final isInstalled = await packageManager.isAppInstalled(packageName);
return isInstalled;
} catch (e) {
return false;
}
}
Testing and Debugging Tips
1. Verify UPI App Installation
Before testing, ensure you have UPI apps installed on your device:
- Google Pay (com.google.android.apps.nbu.paisa.user)
- PhonePe (com.phonepe.app)
- Paytm (net.one97.paytm)
- BHIM UPI (in.org.npci.upiapp)
2. Check Device Compatibility
Some devices may have restrictions on UPI app detection:
- Test on multiple devices: Issues may be device-specific
- Check Android version: Android 11+ requires proper
<queries>configuration - Verify internet connection: Some UPI apps require internet for initialization
3. Debugging Steps
Add comprehensive logging to debug the detection process:
Future<void> debugUpiDetection() async {
print("=== UPI Detection Debug ===");
// Check device capabilities
print("Device info:");
print("Platform: ${Platform.operatingSystem}");
print("Android version: ${await _getAndroidVersion()}");
// Test UPI URL scheme support
final upiUrl = 'upi://pay?pa=test@upi&pn=Test&am=1.0&cu=INR';
final canLaunch = await canLaunchUrl(Uri.parse(upiUrl));
print("Can launch UPI URL: $canLaunch");
// Test package detection
final apps = await UpiPay.getInstalledUpiApps();
print("Detected apps: ${apps.length}");
for (var app in apps) {
print("- ${app.appName}: installed=${app.appInstalled}, scheme=${app.upiScheme}");
}
}
Future<int> _getAndroidVersion() async {
if (Platform.isAndroid) {
final androidInfo = await DeviceInfoPlugin().androidInfo;
return androidInfo.version.sdkInt;
}
return 0;
}
Best Practices for UPI Integration
1. Implement Fallback Mechanisms
Always provide multiple payment options:
Future<void> initiatePayment() async {
try {
// Try UPI package detection
final upiApps = await UpiPay.getInstalledUpiApps();
if (upiApps.isNotEmpty && upiApps.any((app) => app.appInstalled)) {
// Proceed with UPI payment
await _launchUpiPayment();
} else {
// Show alternative payment options
_showAlternativePaymentOptions();
}
} catch (e) {
// Handle gracefully and show alternatives
_showAlternativePaymentOptions();
}
}
2. Handle Transaction Responses Properly
Implement comprehensive transaction handling:
Future<void> handleUpiResponse() async {
try {
final response = await UpiPay.startTransaction(
amount: '10.0',
payeeName: 'Merchant Name',
payeeUpiId: 'merchant@upi',
transactionRefId: 'txn_${DateTime.now().millisecondsSinceEpoch}',
);
switch (response.status) {
case UpiPaymentStatus.success:
print('Payment successful: ${response.transactionId}');
// Verify payment with server
await _verifyPayment(response.transactionId!);
break;
case UpiPaymentStatus.failure:
print('Payment failed: ${response.error}');
break;
case UpiPaymentStatus.cancelled:
print('Payment cancelled by user');
break;
}
} on PlatformException catch (e) {
print('UPI payment error: ${e.message}');
}
}
3. User Experience Considerations
- Clear feedback: Inform users when no UPI apps are detected
- Multiple options: Provide alternative payment methods
- Error handling: Gracefully handle all possible error scenarios
- Testing: Thoroughly test on different devices and Android versions
Sources
- upi_pay | Flutter package - pub.dev
- flutter_upi_india | Flutter package - pub.dev
- GitHub - drenther/upi_pay: Flutter plugin for UPI
- Stack Overflow - Trying to integrate this upi_pay package for flutter but not getting any apps displayed
- UPI apps are not detecting · GitHub Issue #29
- flutter - UPI transaction not working (error) - Stack Overflow
- How to invoke UPI payment Apps from URL - Stack Overflow
- upi_payment_plugin | Flutter package - pub.dev
Conclusion
The upi_pay package detection issue can be resolved through proper Android configuration, enhanced detection methods, and fallback mechanisms. Key takeaways include:
- Configure Android 11+ permissions by adding the
<queries>element to your AndroidManifest.xml - Use enhanced detection methods that check both standard and custom UPI schemes
- Implement fallback mechanisms using direct deep linking when package detection fails
- Test thoroughly on multiple devices and Android versions
- Consider alternative packages like flutter_upi_india if detection issues persist
By following these solutions, you should be able to properly detect UPI apps and provide a seamless payment experience for your users. Remember to always handle errors gracefully and provide alternative payment options when UPI apps are not available.