Closed6

「MethodChannel」の技術調査

Ryo24Ryo24

バッテリー残量を確認するサンプル

Dart側(main.dart)

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/cupertino.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const platform = const MethodChannel('samples.flutter.dev/battery');
  String _batteryLevel = 'Battery Level';

  Future<void> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level at $result % .';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }

    setState(() {
      _batteryLevel = batteryLevel;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ElevatedButton(
              child: Text('Get Battery Level'),
              onPressed: _getBatteryLevel,
            ),
            Text(_batteryLevel),
          ],
        ),
      ),
    );
  }
}

Swift側(AppDelegate.swift)

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 batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/battery",
                                               binaryMessenger: controller.binaryMessenger)
                                               
      batteryChannel.setMethodCallHandler({
        [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
        // Note: this method is invoked on the UI thread.
        guard call.method == "getBatteryLevel" else {
          result(FlutterMethodNotImplemented)
          return
        }
        
        self?.receiveBatteryLevel(result: result)
        })
        
        GeneratedPluginRegistrant.register(with: self) 

     return super.application(application, didFinishLaunchingWithOptions: launchOptions) 
  } 
  
  private func receiveBatteryLevel(result: FlutterResult) {
    let device = UIDevice.current
    device.isBatteryMonitoringEnabled = true
    if device.batteryState == UIDevice.BatteryState.unknown {
      result(FlutterError(code: "UNAVAILABLE",
                          message: "Battery info unavailable",
                          details: nil))
    } else {
      result(Int(device.batteryLevel * 100))
    }
  }
}

実行結果



⚠️エミュレーターだと、バッテリー残量を確認できないよ!

参考文献

https://www.appsdeveloperblog.com/calling-ios-native-code-in-flutter/

Ryo24Ryo24

MethodChannelのザックリな解釈

Dart ⇆ ネイティブ(Java/Kotlin/Objective-C/Swift)間での非同期通信処理。

Dart(Flutter)側

import 'package:flutter/services.dart';

...

Future<void> _getBatteryLevel() async {
    String methodText;
    try {
      final int result = await platform.invokeMethod('getMethodText', 10);
    } on PlatformException catch (e) {
      print(e.message);
    }
}

Swift(ネイティブ)側

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let methodChannel = FlutterMethodChannel(name: "samples.flutter.dev/function",  binaryMessenger: controller.binaryMessenger)
                                     
methodChannel.setMethodCallHandler(
  {
    [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
    // Note: this method is invoked on the UI thread.
    guard call.method == "getMethodText" else {
      result(FlutterMethodNotImplemented)
      return
    }

    // Note: this arguments is invoked on the UI thread.
    let parameters = call.arguments as? Int
    self?.receiveBatteryLevel(result: result, dartInt: parameters ?? 0)
  }
)
このスクラップは2021/11/01にクローズされました