Kerangka kerja multi-platform baru Google, Flutter, terus mendapatkan penggemar. Semakin banyak orang tertarik pada teknologi ini dan mencobanya di proyek kesayangan dan komersial. Semakin banyak artikel dan contoh muncul di RuNet, tetapi beberapa waktu lalu saya perhatikan bahwa, tidak seperti Medium, ulasan artikel yang ditujukan untuk teknologi secara keseluruhan dan kelebihan atau hal baru yang disajikan dalam versi terbaru mendominasi HabrΓ©. Ada beberapa teks tentang kasus-kasus tertentu. Karena itu, saya memutuskan bahwa perlu untuk memperbaiki situasi saat ini. Saya akan mulai bukan dengan case yang paling umum, tetapi cukup sering digunakan - Deep Links.

Baru-baru ini, saya mendapat tugas meluncurkan aplikasi Flutter menggunakan tautan dalam. Saya harus menggeledah dokumentasi dan percobaan untuk mendapatkan ide yang memadai tentang bagaimana bekerja dengan mereka di Flutter. Dalam artikel ini, saya telah mengumpulkan hasilnya, sehingga mereka yang dihadapkan dengan tugas yang sama, lebih mudah untuk dipahami.
Deep Links adalah URL yang memberi pengguna kemampuan untuk menavigasi ke konten tertentu dalam aplikasi seluler di iOS atau Android. Ini berarti bahwa kita harus melacak bagaimana aplikasi dibuka: dengan cara standar atau menggunakan tautan, dan di samping itu, aplikasi mungkin sudah terbuka ketika transisi selesai. Jadi, kita perlu melacak klik-tayang dan di latar belakang aplikasi yang sedang berjalan. Mari kita lihat cara terbaik untuk melakukan ini di Flutter.
Hal pertama adalah konfigurasi
Untuk menggunakan Deep Links dalam pengembangan asli, Anda perlu menyiapkan konfigurasi yang sesuai dalam proyek. Untuk aplikasi Flutter, ini dilakukan dengan cara yang persis sama dengan yang asli.
iOS
Ada dua cara untuk membuat tautan seperti itu di ekosistem Apple: "Skema URL khusus" dan "Tautan Universal".
- Skema URL khusus - memungkinkan Anda menggunakan skema khusus, terlepas dari host mana yang ditentukan. Pendekatan ini adalah yang paling sederhana, tetapi ada nuansa: Anda harus yakin bahwa skema itu unik, dan, selain itu, tautannya tidak akan berfungsi tanpa aplikasi yang diinstal. Jika Anda menggunakan skema URL Khusus, Anda dapat menggunakan tautan seperti:
your_scheme://any_host
- Tautan Universal adalah pendekatan yang sedikit lebih kompleks. Mereka memungkinkan Anda untuk bekerja hanya dengan skema https dan dengan host tertentu, tetapi Anda harus mengkonfirmasi hak untuk menggunakan host ini, di mana Anda perlu menempatkan file di server - asosiasi aplikasi-situs-apel. Tautan Universal memberi Anda kesempatan untuk menjalankan aplikasi di URL:
https://your_host
, dan jika tidak ada aplikasi yang terinstal akan menawarkan untuk menginstalnya dari toko atau membuka tautan di browser.
Misalnya, saya menggunakan pendekatan skema URL Khusus, karena lebih sederhana. Tambahkan bagian berikut ke file Info.plist:
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLName</key> <string>deeplink.flutter.dev</string> <key>CFBundleURLSchemes</key> <array> <string>poc</string> </array> </dict> </array>
Android
Ekosistem Android juga memiliki dua cara menghubungkan dengan properti yang kira-kira sama:
- Tautan Dalam - (seperti halnya skema URL Khusus di iOS) memungkinkan Anda untuk menggunakan skema khusus apa pun host yang ditentukan.
- Tautan Aplikasi - memungkinkan Anda untuk bekerja hanya dengan skema https dan dengan host tertentu (seperti Universal Links di iOS), dan Anda juga perlu mengonfirmasi hak untuk menggunakan host ini dengan menempatkan file JSON pada server Digital Asset Links.
Untuk android, saya juga memutuskan untuk tidak menyulitkannya dan menggunakan Deep Links. Tambahkan ini ke AndroidManifest.xml:
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="poc" android:host="deeplink.flutter.dev" /> </intent-filter>
Dengan demikian, kami mengkonfigurasi aplikasi untuk kedua platform untuk skema
poc
dan akan dapat memproses URL
poc://deeplink.flutter.dev
di dalamnya
poc://deeplink.flutter.dev
Saluran Platform Memasak
Jadi, konfigurasi asli untuk setiap platform sudah siap. Namun selain konfigurasi, Anda perlu menyiapkan Platform Channels, berkat bagian asli yang akan berinteraksi dengan Flutter. Dan lagi, Anda perlu menyiapkan implementasi untuk Android dan iOS.
Mari kita mulai dengan Android. Anda tidak perlu melakukan apa-apa - cukup proses Intent yang masuk dalam metode onCreate, buat MethodChannel dan berikan URI padanya jika aplikasi berjalan melalui Deep Link.
private static final String CHANNEL = "poc.deeplink.flutter.dev/channel"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GeneratedPluginRegistrant.registerWith(this); Intent intent = getIntent(); Uri data = intent.getData(); new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler( new MethodChannel.MethodCallHandler() { @Override public void onMethodCall(MethodCall call, MethodChannel.Result result) { if (call.method.equals("initialLink")) { if (startString != null) { result.success(startString); } } } }); if (data != null) { startString = data.toString(); } }
Di iOS, semuanya akan sedikit berbeda, meskipun secara umum hal yang sama: melewatkan URI ke aplikasi melalui MethodChannel. Saya memutuskan untuk mengimplementasikannya di Swift, karena dengan Objecttive-C hal-hal tidak baik untuk saya)). Selanjutnya adalah AppDelegate.swift yang dimodifikasi
@UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { private var methodChannel: FlutterMethodChannel? override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? ) -> Bool { let controller = window.rootViewController as! FlutterViewController methodChannel = FlutterMethodChannel(name: "poc.deeplink.flutter.dev/channel", binaryMessenger: controller) methodChannel?.setMethodCallHandler({ (call: FlutterMethodCall, result: FlutterResult) in guard call.method == "initialLink" else { result(FlutterMethodNotImplemented) return } }) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) }
Jadi kami akan menangani peluncuran aplikasi melalui Deep Link. Tetapi bagaimana jika tautannya diikuti ketika aplikasi sudah berjalan? Penting untuk memperhitungkan momen ini.
Di Android, untuk ini kami akan mengganti metode onNewIntent dan akan memproses setiap maksud yang masuk. Jika ini adalah klik tautan, kami akan melemparkan acara ke dalam EventChannel yang dibuat untuk ini melalui BroadcastReceiver yang dibuat khusus.
private static final String EVENTS = "poc.deeplink.flutter.dev/events"; private BroadcastReceiver linksReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GeneratedPluginRegistrant.registerWith(this); new EventChannel(getFlutterView(), EVENTS).setStreamHandler( new EventChannel.StreamHandler() { @Override public void onListen(Object args, final EventChannel.EventSink events) { linksReceiver = createChangeReceiver(events); } @Override public void onCancel(Object args) { linksReceiver = null; } } ); } @Override public void onNewIntent(Intent intent){ super.onNewIntent(intent); if(intent.getAction() == android.content.Intent.ACTION_VIEW && linksReceiver != null) { linksReceiver.onReceive(this.getApplicationContext(), intent); } } private BroadcastReceiver createChangeReceiver(final EventChannel.EventSink events) { return new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) {
Mari kita lakukan hal yang sama di bagian iOS. Di Swift, kita perlu membuat FlutterStreamHandler dan memproses tautan apa pun yang kita terima saat aplikasi di latar belakang. Sudah waktunya untuk mengubah AppDelegate.segera sedikit lagi
@UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { private var eventChannel: FlutterEventChannel? private let linkStreamHandler = LinkStreamHandler() override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? ) -> Bool { let controller = window.rootViewController as! FlutterViewController eventChannel = FlutterEventChannel(name: "poc.deeplink.flutter.dev/events", binaryMessenger: controller) GeneratedPluginRegistrant.register(with: self) eventChannel?.setStreamHandler(linkStreamHandler) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } override func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { eventChannel?.setStreamHandler(linkStreamHandler) return linkStreamHandler.handleLink(url.absoluteString) } } class LinkStreamHandler:NSObject, FlutterStreamHandler { var eventSink: FlutterEventSink?
Ketika kami menggabungkan kedua bagian: bagian untuk meluncurkan aplikasi dan bagian untuk aplikasi di latar belakang - kami akan mengontrol semua klik pengguna pada Deep Links.
Memproses Tautan Dalam dalam Bergetar
Bagian platform siap untuk ini, sekarang saatnya untuk beralih ke bagian Flutter. Seperti yang mungkin Anda ketahui, Anda dapat membuat aplikasi pada flutter menggunakan pendekatan arsitektur yang berbeda. Banyak artikel telah ditulis tentang topik ini (
misalnya, yang ini ), tetapi secara pribadi saya merasa bahwa BLoC murni adalah pendekatan yang paling cocok. Karenanya, saya akan menyiapkan BLoC terpisah yang akan menangani tautan ini. Akibatnya, kami mendapatkan kode yang sama sekali tidak terikat dengan UI dan dapat menangani tautan penerima di mana pun nyaman.
class DeepLinkBloc extends Bloc {
Khusus untuk mereka yang tidak memiliki pengalaman sebelumnya dengan BLoC dan StreamBuilders, saya akan menyiapkan contoh widget yang akan bekerja dengan BLoC ini. Widget didasarkan pada StreamBuilder, yang membangun kembali UI tergantung pada peristiwa yang diterima dari aliran.
class PocWidget extends StatelessWidget { @override Widget build(BuildContext context) { DeepLinkBloc _bloc = Provider.of<DeepLinkBloc>(context); return StreamBuilder<String>( stream: _bloc.state, builder: (context, snapshot) { if (!snapshot.hasData) { return Container( child: Center( child: Text('No deep link was used '))); } else { return Container( child: Center( child: Padding( padding: EdgeInsets.all(20.0), child: Text('Redirected: ${snapshot.data}')))); } }, ); } }
Tadam! Itu saja. Sekarang semuanya berfungsi!
Untuk menguji, jalankan aplikasi dengan tiga cara berbeda. Secara manual dan melalui Deep Links, pertama dengan
poc://deeplink.flutter.dev
URI
poc://deeplink.flutter.dev
, dan kemudian dengan
poc://deeplink.flutter.dev/parameter
. Berikut screenshot dari apa yang terjadi:

Ada cara lain untuk bekerja dengan Deep Links. Misalnya, Anda dapat menggunakan
Firebase Dynamic Links untuk ini. Ada
artikel yang bagus tentang cara menggunakannya dengan Flutter. Ada juga
pustaka 'uni-link' yang sudah jadi untuk menghubungkan Deep Links - Anda dapat menggunakannya. Dan jika Anda tidak ingin bergantung pada pustaka pihak ketiga, Anda selalu bisa menerapkannya sendiri. Saya harap artikel saya akan membantu Anda dengan ini!
Kode sumber
Kode sumber untuk contoh di atas dapat
dilihat di sini .
Beberapa informasi bermanfaat
Jika Anda membaca artikel hingga saat ini, kemungkinan besar Anda tertarik dengan pengembangan Flutter). Saya ingin berbicara tentang beberapa sumber yang mungkin berguna bagi Anda. Belum lama ini, sepasang podcast berbahasa Rusia dibuat yang terkait langsung dengan pengembangan Flutter. Saya sarankan berlangganan kepada mereka:
Flutter Dev Podcast (
saluran telegram ), tempat kami membahas masalah pembakaran pengembangan Flutter, dan
Mobile People Talks (
saluran telegram ), tempat kami membahas masalah pengembangan seluler pada prinsipnya, dari berbagai sudut pandang. Talks Mobile People Memimpin adalah iOS, Android, ReactNative, dan Flutter.
