Flutterからネイティブアプリ(Kotlin / Swift)の処理を呼び出す

全体のコード

まずは結論から。

kotlinのファイルはこちら(引用元:https://qiita.com/mkosuke/items/b384035e507ad0208c10

package com.example.[プロジェクト名]

import android.content.pm.PackageManager
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.ExperimentalCoroutinesApi

class MainActivity: FlutterActivity() {
    private val CHANNEL = "appInfo"

    @OptIn(ExperimentalCoroutinesApi::class)
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler{
                call, result ->
            println("MethodChannel start")
            if(call.method == "getAppVersion"){
                println("call getAppVersion start")

                try {
                    val pInfo = applicationContext.packageManager.getPackageInfo(context.packageName, 0)
                    var version = pInfo.versionName
                    result.success("${pInfo.versionName}");

                } catch (e: PackageManager.NameNotFoundException) {
                    e.printStackTrace()
                    result.notImplemented()
                }

                println("call getAppVersion end")
            }else{
                result.notImplemented()
            }
        }
    }
}

Flutter(Dart)のファイルはこちら

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'getAppVersion',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

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

class _MyHomePageState extends State<MyHomePage> {
  _MyHomePageState() {
    getAppVersion();
  }
  String _appVersion = '';

  Future<void> getAppVersion() async {
    String appVersion;

    print("getAppVersion start");
    try {
      appVersion = await AppInfo.appVersion ?? 'Unknown App version';
    } on PlatformException {
      appVersion = 'Failed app version';
    }
    print("getAppVersion end");

    setState(() {
      _appVersion = appVersion;
      print("appVersion: $_appVersion");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
          child: Text(_appVersion, style: const TextStyle(fontSize: 20))),
    );
  }
}

class AppInfo {
  static const MethodChannel _channel = MethodChannel('appInfo');

  static Future<String?> get appVersion async {
    print("AppInfoClass: appVersion start");

    final String? version = await _channel.invokeMethod('getAppVersion');

    print("AppInfoClass: appVersion end");
    return version;
  }
}

考察

MainActivity.kt

configureFlutterEngine

以前はonCreateメソッドで実行していたようだが、現在(2022年6月)ではconfigureFlutterEngineメソッドを使うとのこと。

void configureFlutterEngine (@NonNull FlutterEngine flutterEngine)

Configures the given FlutterEngine.
This method is called after the given FlutterEngine has been attached to the owning FragmentActivity.

FragmentActivityにアクセスしたFlutterEngineが与えられた後に呼ばれるメソッドという感じですかね。

setMethodCallHandlerメソッド

Sets a callback for receiving method calls on this channel.

参照

onCreateは現在は使わない
configureFlutterEngineとは(公式ドキュメント)