MST
星途 面试题库

面试题:Flutter平台插件开发之iOS与Android基本功能定制

在Flutter插件开发中,简述如何为iOS和Android分别定制一个简单的本地通知功能插件,包括基本的Flutter与原生代码的交互流程。
24.5万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

Flutter 端

  1. 定义方法通道:在Flutter项目的lib目录下,创建一个用于与原生代码交互的方法通道。
import 'package:flutter/services.dart';

const MethodChannel _channel = MethodChannel('com.example.notification_plugin');
  1. 定义通知相关方法:提供在Flutter中调用原生通知功能的方法。
Future<void> showNotification(String title, String body) async {
  try {
    await _channel.invokeMethod('showNotification', {
      'title': title,
      'body': body
    });
  } on PlatformException catch (e) {
    print('Failed to show notification: ${e.message}');
  }
}

iOS 端

  1. 创建Flutter插件项目:在终端中运行flutter create --template=plugin -i swift -a kotlin notification_plugin创建一个Flutter插件项目。
  2. 配置Info.plist:在ios/Runner/Info.plist文件中添加通知权限配置。
<key>NSUserNotificationUsageDescription</key>
<string>$(PRODUCT_NAME) would like to send you notifications.</string>
  1. 实现原生通知功能:在ios/Classes/NotificationPlugin.swift文件中实现与Flutter交互及通知展示逻辑。
import Flutter
import UIKit
import UserNotifications

public class NotificationPlugin: NSObject, FlutterPlugin {
  public static func register(with registrar: FlutterPluginRegistrar) {
    let channel = FlutterMethodChannel(name: "com.example.notification_plugin", binaryMessenger: registrar.messenger())
    let instance = NotificationPlugin()
    registrar.addMethodCallDelegate(instance, channel: channel)
  }

  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    if call.method == "showNotification" {
      guard let args = call.arguments as? [String: Any],
            let title = args["title"] as? String,
            let body = args["body"] as? String else {
        result(FlutterMethodNotImplemented)
        return
      }
      showLocalNotification(title: title, body: body)
      result(nil)
    } else {
      result(FlutterMethodNotImplemented)
    }
  }

  func showLocalNotification(title: String, body: String) {
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
      if granted {
        let content = UNMutableNotificationContent()
        content.title = title
        content.body = body
        content.sound = UNNotificationSound.default

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
        let request = UNNotificationRequest(identifier: "localNotification", content: content, trigger: trigger)

        center.add(request, withCompletionHandler: nil)
      }
    }
  }
}

Android 端

  1. 配置权限:在android/app/src/main/AndroidManifest.xml文件中添加通知权限。
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  1. 实现原生通知功能:在android/src/main/kotlin/com/example/notification_plugin/NotificationPlugin.kt文件中实现与Flutter交互及通知展示逻辑。
package com.example.notification_plugin

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
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

class NotificationPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
  private lateinit var channel : MethodChannel
  private var context: Context? = null
  private var activity: android.app.Activity? = null

  override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "com.example.notification_plugin")
    channel.setMethodCallHandler(this)
    context = flutterPluginBinding.applicationContext
  }

  override fun onMethodCall(call: MethodCall, result: Result) {
    if (call.method == "showNotification") {
      val title = call.argument<String>("title")
      val body = call.argument<String>("body")
      showNotification(title, body)
      result.success(null)
    } else {
      result.notImplemented()
    }
  }

  private fun showNotification(title: String?, body: String?) {
    val notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    val channelId = "my_channel_01"
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      val name = "My Channel"
      val descriptionText = "This is my channel"
      val importance = NotificationManager.IMPORTANCE_DEFAULT
      val channel = NotificationChannel(channelId, name, importance).apply {
        description = descriptionText
      }
      notificationManager.createNotificationChannel(channel)
    }

    val intent = Intent(context, activity?.javaClass).apply {
      flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val pendingIntent: PendingIntent? = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)

    val builder = NotificationCompat.Builder(context!!, channelId)
      .setSmallIcon(R.drawable.ic_launcher_background)
      .setContentTitle(title)
      .setContentText(body)
      .setPriority(NotificationCompat.PRIORITY_DEFAULT)
      .setContentIntent(pendingIntent)
      .setAutoCancel(true)

    notificationManager.notify(1, builder.build())
  }

  override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
  }

  override fun onAttachedToActivity(binding: ActivityPluginBinding) {
    activity = binding.activity
  }

  override fun onDetachedFromActivityForConfigChanges() {
    activity = null
  }

  override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
    activity = binding.activity
  }

  override fun onDetachedFromActivity() {
    activity = null
  }
}

通过上述步骤,即可在Flutter插件开发中为iOS和Android分别定制简单的本地通知功能插件,并实现Flutter与原生代码的交互。