import 'dart:io' show Platform; import 'package:android_intent_plus/android_intent.dart'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:url_launcher/url_launcher.dart'; typedef AndroidIntentLauncher = Future Function(AndroidIntent intent); abstract final class AppLinkUtil { static final _androidPackageNamePattern = RegExp( r'^[A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z][A-Za-z0-9_]*)+$', ); static String targetAppFromUrl(String urlString) { final value = Uri.tryParse(urlString)?.queryParameters['targetApp']?.trim(); if (value == null || !_androidPackageNamePattern.hasMatch(value)) return ''; return value; } static Future openExternal(Uri uri, {String packageName = ''}) => AppLinkLauncher( isAndroid: () => !kIsWeb && Platform.isAndroid, launchAndroidIntent: (intent) => intent.launch(), ).openExternal(uri, packageName: packageName); } class AppLinkLauncher { const AppLinkLauncher({ required this.isAndroid, required this.launchAndroidIntent, this.launchExternal, }); final bool Function() isAndroid; final AndroidIntentLauncher launchAndroidIntent; final Future Function(Uri uri)? launchExternal; Future openExternal(Uri uri, {String packageName = ''}) async { if (uri.host.isEmpty || (uri.scheme.toLowerCase() != 'http' && uri.scheme.toLowerCase() != 'https')) { return false; } if (isAndroid() && packageName.trim().isNotEmpty) { try { await launchAndroidIntent( AndroidIntent( action: 'action_view', data: uri.toString(), package: packageName.trim(), ), ); return true; } catch (_) {} } final launcher = launchExternal; if (launcher != null) return launcher(uri); return launchUrl(uri, mode: LaunchMode.externalApplication); } }