NeuroAgent

Fix UPI Apps Not Detected in Flutter upi_pay Package

Resolve UPI app detection issues in Flutter with our comprehensive guide. Fix Android permissions, configure <queries> element, and implement alternative detection methods for seamless UPI integration.

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?

NeuroAgent

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

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:

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:

gradle
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:

dart
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:

dart
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:

dart
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:

  1. Test on multiple devices: Issues may be device-specific
  2. Check Android version: Android 11+ requires proper <queries> configuration
  3. Verify internet connection: Some UPI apps require internet for initialization

3. Debugging Steps

Add comprehensive logging to debug the detection process:

dart
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:

dart
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:

dart
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

  1. upi_pay | Flutter package - pub.dev
  2. flutter_upi_india | Flutter package - pub.dev
  3. GitHub - drenther/upi_pay: Flutter plugin for UPI
  4. Stack Overflow - Trying to integrate this upi_pay package for flutter but not getting any apps displayed
  5. UPI apps are not detecting · GitHub Issue #29
  6. flutter - UPI transaction not working (error) - Stack Overflow
  7. How to invoke UPI payment Apps from URL - Stack Overflow
  8. 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:

  1. Configure Android 11+ permissions by adding the <queries> element to your AndroidManifest.xml
  2. Use enhanced detection methods that check both standard and custom UPI schemes
  3. Implement fallback mechanisms using direct deep linking when package detection fails
  4. Test thoroughly on multiple devices and Android versions
  5. 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.