run method
The execution body of the command.
Implementation
@override
Future<void> run(List<String> args, {required Logger logger}) async {
final finder = ProjectFinder();
final projectRoot = finder.findProjectRoot();
final project = FlutterProject(projectRoot);
final configManager = ConfigManager(projectRoot);
if (!configManager.configExists()) {
logger.error('No configuration found. Please run "deeplink init" first.');
return;
}
final config = configManager.load();
// 1. Gather domains
final List<String> domains = [];
if (args.isNotEmpty) {
domains.addAll(
args.join(' ').split(',').map((d) => d.trim().replaceAll(RegExp(r'^https?://'), '')).where((d) => d.isNotEmpty),
);
} else {
final defaultDomains = config.domains.isNotEmpty ? config.domains.join(', ') : 'example.com';
final domainsInput = Console.ask('Enter domain names (comma-separated)', defaultValue: defaultDomains);
domains.addAll(
domainsInput
.split(',')
.map((d) => d.trim().replaceAll(RegExp(r'^https?://'), ''))
.where((d) => d.isNotEmpty),
);
}
if (domains.isEmpty) {
logger.error('At least one domain is required to enable App Links.');
return;
}
final spinner = Spinner('Enabling Android App Links...');
spinner.start();
try {
// 2. Update AndroidManifest.xml
if (FileUtils.exists(project.androidManifestPath)) {
var manifestContent = FileUtils.readAsString(project.androidManifestPath);
manifestContent = AndroidManifestEditor().enableAppLinks(manifestContent, domains);
FileUtils.writeString(project.androidManifestPath, manifestContent);
}
// 3. Update configuration
final updatedConfig = DeepLinkConfig(
schemes: config.schemes,
generateSampleRoutes: config.generateSampleRoutes,
generateDeepLinkManager: config.generateDeepLinkManager,
androidAppLinks: true,
iosUniversalLinks: config.iosUniversalLinks,
domains: domains,
);
configManager.save(updatedConfig);
// 4. Regenerate setup artifacts
final setupDir = PathUtils.join(projectRoot, 'deeplink_setup');
FileUtils.createDirectory(setupDir);
final templateEngine = TemplateEngine();
final packageName = project.getAndroidPackageName();
final renderedAssetLinks = templateEngine.render(
TemplatesBundle.assetLinksJson,
{
'PACKAGE_NAME': packageName,
'SHA256_FINGERPRINT': 'YOUR_SHA256_FINGERPRINT_HERE',
},
);
FileUtils.writeString(PathUtils.join(setupDir, 'assetlinks.json'), renderedAssetLinks);
// Regenerate README.md
final primaryScheme = config.schemes.isNotEmpty ? config.schemes.first : 'myapp';
final renderedInstructions = templateEngine.render(
TemplatesBundle.setupInstructions,
{
'SCHEME': primaryScheme,
'DOMAINS': domains.join(', '),
'PACKAGE_NAME': packageName,
'DOMAIN_1': domains[0],
'DOMAIN_2': domains.length > 1 ? domains[1] : 'your-second-domain.com',
},
);
FileUtils.writeString(PathUtils.join(setupDir, 'README.md'), renderedInstructions);
// Run Flutter generator to keep code constant file in sync
final generator = FlutterGenerator(projectRoot, logger);
generator.generate(updatedConfig);
spinner.stop(success: true, finalMessage: 'Android App Links enabled and assets generated.');
logger.info('Check "deeplink_setup/assetlinks.json" for host-side verification setup.');
} catch (e) {
spinner.stop(success: false, finalMessage: 'Failed to enable App Links.');
logger.error('Failed to enable App Links: ${e.toString()}');
}
}