平台特定代碼是指在使用像 Flutter 這樣的跨平台框架時,如果要使用 Android 或 iOS 系統自帶的功能,就需要寫一些專門給這些平台用的原生代碼。雖然 Flutter 本身已經能處理很多功能,但有些特定的功能,像是相機、定位服務等等,還是得靠寫 Android 或 iOS 的原始程式碼來實現。
我們以相機來舉例
iOS
在 iOS 上,通常使用 UIImagePickerController 來打開相機拍照。這是一個 iOS 原始的套件,可以在 Objective-C 或 Swift 來使用設備的相機。
Android
在 Android 上,使用 Intent 來調用相機應用並拍照。
Flutter
在 Flutter 中,可以使用我們之前介紹過的插件(例如 image_picker)來處理相機功能。但是,如果需要更多特殊功能,就需要自己撰寫平台特定代碼。
編寫平台特定代碼
首先,在 Android 的 MainActivity.kt 或 iOS 的 AppDelegate.swift 中編寫相應的原始程式碼。
package com.example.myapp
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.MethodChannel
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.example.myapp/native"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "getNativeData") {
val data = getNativeData()
result.success(data)
} else {
result.notImplemented()
}
}
}
private fun getNativeData(): String {
return "Native Android Data"
}
}
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let nativeChannel = FlutterMethodChannel(name: "com.example.myapp/native",
binaryMessenger: controller.binaryMessenger)
nativeChannel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
if call.method == "getNativeData" {
result(self.getNativeData())
} else {
result(FlutterMethodNotImplemented)
}
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func getNativeData() -> String {
return "Native iOS Data"
}
}
import 'package:flutter/services.dart';
class CameraAccess {
static const platform = MethodChannel('com.example/camera');
Future<void> openCamera() async {
try {
final result = await platform.invokeMethod('openCamera');
print('Camera opened: $result');
} on PlatformException catch (e) {
print("Failed to open camera: '${e.message}'.");
}
}
}
我們明天見~