Migrasi Firebase Dynamic Links ke App Links menjadi langkah wajib bagi para developer Flutter di tahun 2025. Firebase Dynamic Links (FDL) pernah menjadi solusi andalan untuk deep linking. Dengan satu URL “pintar”, kita bisa mengarahkan pengguna ke tujuan yang berbeda tergantung platform (iOS/Android) dan status aplikasi (sudah ter-install atau belum).
Namun, Google telah menghentikan layanan Firebase Dynamic Links dan akan mematikannya secara total pada 25 Agustus 2025. Setelah tanggal tersebut, semua link FDL akan berhenti berfungsi. Ini artinya, para developer Flutter wajib memigrasikan aplikasi mereka ke metode deep linking lain sebelum tenggat waktu tersebut agar fungsionalitas link tetap berjalan.
Solusi pengganti yang direkomendasikan adalah menggunakan sistem deep link bawaan (native): App Links di Android dan Universal Links di iOS. Keduanya bekerja dengan URL HTTPS biasa pada domain yang kita kontrol sepenuhnya. Tanpa menggunakan pihak ketiga, tanpa risiko dimatikan tiba-tiba, dan tanpa biaya tambahan.
Table of Contents
App Links vs. FDL: Apa yang Hilang & Alternatifnya
1. “Buka App Store → Lanjutkan” (Deferred Deep Link) Otomatis Hilang
Link bawaan akan langsung membuka aplikasi jika sudah terpasang; jika belum, link akan membuka website kita. Untuk meniru alur “lanjutkan setelah instal” seperti FDL, kita bisa menggunakan pendekatan kustom seperti berbasis clipboard.
2. Tidak Ada Link Pendek & Analitik Bawaan
Kita bisa menggunakan struktur domain kita sendiri (misalnya, domainkita.com/invite/ABC123) dan melacaknya dengan analitik web, atau menggunakan layanan pihak ketiga seperti Branch, AppsFlyer, dll.
3. Konfigurasi Awal yang Sedikit Lebih Rumit
Kita perlu menyiapkan dan menempatkan file assetlinks.json (untuk Android) dan apple-app-site-association (untuk iOS) di folder /.well-known/ pada domain kita. Panduan migrasi dari Firebase menyarankan menggunakan Firebase Hosting atau GitHub Pages jika kita butuh solusi hosting yang cepat.
Panduan Migrasi dari Firebase Dynamic Links ke App Links
Langkah 1: Siapkan Domain dan Host File Asosiasi
Pilih domain atau subdomain yang kita kontrol. Pastikan kedua file berikut dapat diakses melalui HTTPS:
Android: https://<domain-kita>/.well-known/assetlinks.json
Gunakan fingerprint dari signing key rilis. Jika menggunakan Play App Signing, dapatkan fingerprint tersebut dari Google Play Console.
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": “com.example.ourapp",
"sha256_cert_fingerprints": ["00:11:22:33:...:FF"]
}
}]iOS: https://<domain-kita>/.well-known/apple-app-site-association (Tanpa ekstensi file)
Nilai appIDs adalah TeamID.BundleID. Kita bisa membatasi paths nanti jika diperlukan
{
"applinks": {
"apps": [],
"details": [{
"appIDs": ["ABCDE12345.com.example.ourapp"],
"paths": ["*"]
}]
}
}Pada Android dengan Digital Asset Links dari Google, kita dapat generate & test assetlinks.json dengan cara mengisi formnya dan menekan tombol generate / test statement
Untuk iOS, pastikan file AASA dapat dijangkau, memiliki content-type yang benar (application/json), dan tidak ada proses redirect.
Sebagai referensi, kita bisa lihat milik facebook di link berikut :
https://facebook.com/.well-known/apple-app-site-association
https://facebook.com/.well-known/assetlinks.json
Langkah 2: Konfigurasi App Links di Android
Tambahkan intent filter di dalam android/app/src/main/AndroidManifest.xml di bawah tag activity:
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="myapp.com"
android:pathPrefix="/" />
</intent-filter>Catatan:
android:autoVerify="true"memerintahkan Android untuk memverifikasi domain Kita terhadap assetlinks.json. Jika berhasil, link akan langsung membuka aplikasi tanpa menampilkan pilihan (chooser).- astikan package name dan signing fingerprint cocok dengan yang Kita deklarasikan di
assetlinks.json. Ingat, key debug dan release berbeda.
Langkah 3: Konfigurasi Universal Links di iOS
Di Xcode, buka target Runner. Di bawah tab Signing and Capabilities, tambahkan kapabilitas Associated Domains :
applinks:ourapp.comJika Kita menggunakan package app_links, nonaktifkan penanganan deep link bawaan Flutter untuk menghindari konflik pada file ios/Runner/Info.plist, tambahkan :
<key>FlutterDeepLinkingEnabled</key>
<false/>Langkah 4: Tangani Link di Flutter dengan app_links
Tambahkan package :
dependencies:
flutter:
sdk: flutter
app_links: ^6.4.1Inisialisasi app_links di awal agar dapat menangkap link saat aplikasi pertama kali dibuka (cold start), dan juga stream untuk link yang masuk saat aplikasi berjalan.
import 'package:flutter/material.dart';
import 'package:app_links/app_links.dart';
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late final AppLinks _appLinks;
@override
void initState() {
super.initState();
_appLinks = AppLinks();
// 1) Cold start
_appLinks.getInitialAppLink().then((uri) {
if (uri != null) _handleUri(uri);
});
// 2) Warm state
_appLinks.uriLinkStream.listen((uri) {
if (uri != null) _handleUri(uri);
});
}
void _handleUri(Uri uri) {
final segs = uri.pathSegments;
// Check pattern /invite/:id
if (segs.isNotEmpty && segs.first == 'invite') {
final code = segs.length > 1 ? segs[1] : null;
if (code != null) {
Navigator.of(context).pushNamed('/invite', arguments: code);
}
return;
}
// Add more patterns here, for example /product/:id
}
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/invite': (c) => const Placeholder(),
},
home: const Scaffold(
body: Center(child: Text('Home')),
),
);
}
}Catatan :
- Cold Start : aplikasi dijalankan dari awal (tidak ada di memori) dan dibuka karena pengguna membuka link (App/Universal Link), notifikasi, atau intent OS.
getInitialAppLink()mengembalikan URI yang membuat aplikasi terbuka. Panggil sekali saat startup untuk menangkap deep link awal. - Warm State : aplikasi telah berjalan (foreground/background) dan tetap hidup. Saat pengguna membuka link baru ketika aplikasi aktif, uriLinkStream akan menangkap URI setiap kali ada link masuk. Gunakan ini untuk menangani deep link tanpa me-restart aplikasi (mis. dari browser atau notifikasi saat app aktif).
Langkah 5: Publish, Test, dan Ganti Link FDL Lama
Ganti semua URL FDL yang telah disebar di email, template push notification, kode QR, dan media sosial dengan link HTTPS baru kita. Untuk aset-aset yang tidak bisa diubah, gunakan redirect di sisi server jika memungkinkan.
Kesimpulan
Migrasi Firebase Dynamic Links ke App Links ini sebagian besar adalah pekerjaan konfigurasi di awal. Kita hanya perlu mengklaim domain, mempublikasikan dua file kecil, mengaktifkan di setiap platform, lalu menangani routing link di dalam Flutter.
Hasilnya, Kita mendapatkan fondasi deep linking yang handal, gratis, dan berada di bawah kendali penuh kita. Jika di kemudian hari membutuhkan link pendek, analitik, atau deferred deep linking, Kita bisa membangunnya di atas sistem ini menggunakan website kita atau penyedia layanan deep link lainnya.

