[Flutter] Hướng Dẫn Tạo Plugin Và Gọi Thư Viện Native (Phần Cuối)
Có thể bạn quan tâm
Xem thêm Phần 1-2 Xem thêm Phần 3
Phần 4: Hướng dẫn thêm thư viện native
Trong phần này, mình sẽ demo việc gửi 1 DateTime từ flutter xuống native code để kiểm tra xem có phải ngày hiện tại hay không? Mình sẽ sử dụng thư viện Tempo của tác giả cesarferreira cho Android và SwiftDate của tác giả Daniele Margutti cho iOS.
Vì flutter và native không giao tiếp với nhau bằng biến loại DateTime được, nên mình sẽ cần chuyển DateTime sang dạng string UTC để xử lý nhé.
Thêm code flutter để hiển thị kết quả
Trong file lib/src/sample_call_native.dart các bạn thêm 1 hàm như sau:
static Future isToday(DateTime dateTime) async { final date = dateTime.toUtc().toIso8601String(); final bool? isSuccess = await _channel.invokeMethod( 'isToday', { 'dateTime': date, }, ); return isSuccess; }Trong file example/lib/main.dart bạn đổi lại code như sau:
import 'package:flutter/material.dart'; import 'package:sample_plugin_flutter/sample_plugin_flutter.dart'; void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('Plugin example app'), ), body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ /// Phần 2. Hướng dẫn tạo Widget với plugin SampleButton( text: "Sample Button", onPressed: () { print("Sample Button Click"); }, ), /// Phần 3. Hướng dẫn gọi native code từ plugin FutureBuilder( future: SampleCallNativeFlutter.platformVersion, builder: (_, snapshoot) { return Text(snapshoot.data ?? ''); }, ), /// Phần 4. Hướng dẫn gọi native code từ plugin FutureBuilder( future: SampleCallNativeFlutter.isToday(DateTime.now()), builder: (_, snapshoot) { return Text('isToDay: ${DateTime.now()} is ${snapshoot.data}'); }, ), FutureBuilder( future: SampleCallNativeFlutter.isToday(DateTime(2021,01,01)), builder: (_, snapshoot) { return Text('isToDay: ${DateTime(2021,01,01)} is ${snapshoot.data}'); }, ), ], ), ), ), ); } }Thêm thư viện cho iOS
Thường khi thêm 1 thư viện vào code iOS, bạn cần sử dụng Cocoapods thêm nó vào Podfile. Nhưng với plugin thì bạn sẽ thêm dependency nó vào ios/sample_plugin_flutter.podspec.
File này cũng giúp bạn khai báo s.static_framework = true(1 số thư viện native cần phải khai báo biến này) hay s.ios.deployment_target = ‘9.0’ (để giới hạn version build iOS).
(Nếu bạn chưa biết Cocoapods là gì, bạn có thể tham khảo tại đây)
# # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. # Run `pod lib lint sample_plugin_flutter.podspec` to validate before publishing. # Pod::Spec.new do |s| s.name = 'sample_plugin_flutter' s.version = '0.0.1' s.summary = 'A new flutter plugin project.' s.description = < '../LICENSE' } s.author = { 'Your Company' => '[email protected]' } s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' s.dependency 'SwiftDate' # Khai báo thư viện iOS tại đây s.platform = :ios, '8.0' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.swift_version = '5.0' endSau đó bạn cần chạy pod install cho thư mục example/ios và vào Xcode chọn menu Product/Clean Build Folder. Trong file SwiftSamplePluginFlutterPlugin bạn đổi lại code như sau:
import Flutter import UIKit import SwiftDate public class SwiftSamplePluginFlutterPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "sample_plugin_flutter", binaryMessenger: registrar.messenger()) let instance = SwiftSamplePluginFlutterPlugin() registrar.addMethodCallDelegate(instance, channel: channel) } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "getPlatformVersion": result("iOS " + UIDevice.current.systemVersion) case "isToday": isToday(call, result) default: result(nil) } } private func isToday(_ call: FlutterMethodCall,_ result: @escaping FlutterResult) { let arguments = call.arguments as! Dictionary let dateTime = arguments["dateTime"] as! String; // Convert to local let localDate = dateTime.toDate(nil, region: Region.current) // Check isToday let checkToday = localDate?.isToday result(checkToday) } }Thế là xong bên iOS, giờ qua phần của Android.
Thêm thư viện cho Android
Trong Gradle Scripts/build.gradle(Module: android.sample_plugin_flutter) bạn thêm dòng bên dưới ở cuối file và nhấn Sync now
dependencies { implementation 'com.github.cesarferreira:tempo:+' }Trong file android/src/main/kotlin/com/example/sample_plugin_flutter/SamplePluginFlutterPlugin.kt bạn đổi lại code như sau:
package com.example.sample_plugin_flutter import androidx.annotation.NonNull import com.cesarferreira.tempo.Tempo import com.cesarferreira.tempo.isToday import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result import java.text.SimpleDateFormat import java.util.* /** SamplePluginFlutterPlugin */ class SamplePluginFlutterPlugin: FlutterPlugin, MethodCallHandler { /// The MethodChannel that will the communication between Flutter and native Android /// /// This local reference serves to register the plugin with the Flutter Engine and unregister it /// when the Flutter Engine is detached from the Activity private lateinit var channel : MethodChannel override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { channel = MethodChannel(flutterPluginBinding.binaryMessenger, "sample_plugin_flutter") channel.setMethodCallHandler(this) } override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { when (call.method) { "getPlatformVersion" -> result.success("Android ${android.os.Build.VERSION.RELEASE}") "isToday" -> isToday(call, result) else -> { result.notImplemented() } } } private fun isToday(@NonNull call: MethodCall, @NonNull result: Result) { var arguments = call.arguments as Map var dateTime = arguments["dateTime"] as String var localDate = dateTime.toDate() var checkToday = localDate.isToday // library Tempo check isToday result.success(checkToday) } private fun String.toDate(dateFormat: String = "yyyy-MM-dd'T'HH:mm:ss", timeZone: TimeZone = TimeZone.getTimeZone("UTC")): Date { val parser = SimpleDateFormat(dateFormat, Locale.getDefault()) parser.timeZone = timeZone return parser.parse(this) } override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { channel.setMethodCallHandler(null) } }Xong rồi, giờ chạy flutter run để xem thành quả cuối cùng thôi nào.
Kết thúc
Hi vọng qua bài viết của mình giúp ích cho các bạn phần nào việc làm qua viết plugin cho Flutter. Mình để link Github ở đây để các bạn tham khảo nha.
Nguồn tham khảo:
- Developing packages & plugins
- Bảng mapping các loại biến giữa các nền tảng
- Thư viện Tempo
- Thư viện SwiftDate
- Cocoapods
Bài viết đầy đủ tại Viblo Cảm ơn các bạn đã xem bài viết.
Tác giả
Phạm Tiến Dũng [email protected]
Từ khóa » Thư Viện Flutter
-
Các Thư Viện Flutter Sẽ Giúp Bạn Làm Việc Dễ Dàng Hơn 2021
-
Nạp Thư Viện Lib Quản Lý Các Gói Package Trong Dart
-
[Flutter] Hướng Dẫn Tạo Plugin Và Gọi Thư Viện Native - Viblo
-
Flutter Sẽ Dễ Dàng Hơn Nếu Bạn Biết Các Thư Viện Này | Academy
-
[Flutter] Hướng Dẫn Tạo Plugin Và Gọi Thư Viện Native
-
Tổng Hợp Các Tài Liệu Học Flutter - Tự Học | By Lê Thành Trung | F8
-
Dart Libraries - Thư Viện Dart - W3seo Cách Import Thư Viện Trong Dart
-
Material Library - Dart API - Flutter API
-
Foundation Library Null Safety - Flutter API
-
Tích Hợp Thư Viện C/C++ Vào Một Dự án Flutter Như Thế Nào? - 2KVN
-
Bài 16: Giới Thiệu Về Package - Học Lập Trình Flutter Cơ Bản
-
Flutter Gallery Is A Resource To Help Developers Evaluate ... - GitHub
-
Có Gì Mới Trong Năm 2020 Tập 4: Thư Viện định Dạng Tệp