1
/
5

Flutterでネイティブ画面を呼び出してみよう【株式会社ライトコード】

※弊社エンジニアの記事になります。

前回、OS固有の問題を解決するためにネイティブコードの呼び出し方法を解説しました。

今回はさらなる問題解決のため、ネイティブの画面を呼び出せるようにしましょう。

Flutter側の呼び出し処理

今回はアプリのログイン処理をネイティブで行う、という想定で話を進めていきます。

2023.06.05Flutterでネイティブコードを呼び出してみようiOS、Androidの両方に対応できて便利なFlutterですが、Flutterの仕様、OSの仕様でさまざまな問題が起こることがあります。...

Flutter側はInvokeMethodを使用し呼び出します。詳細は前回の記事で解説しています。


Future<void> _goLoginNative() async {
    const MethodChannel channel = MethodChannel("Channel");
    String? resultText = await channel.invokeMethod("goLogin");
  }


iOSの呼び出し

XCodeを開きiOSのログイン画面を作ります。伝統的なStoryboard+ViewControllerの形式で作ります。ログインボタンを押すと通信し、ログイン結果(トークンなど)をFlutter側に返す、というイメージです。

Swift側のAppDelegate実装です。

override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
 
        let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
        let methodChannel = FlutterMethodChannel(name: "Channel",binaryMessenger: controller as! FlutterBinaryMessenger)
        methodChannel.setMethodCallHandler({
            (call:FlutterMethodCall, result:@escaping FlutterResult) -> Void in
            print("method: \(call.method)")
            switch call.method {
            case "goLogin":
                let nextViewController = UIStoryboard(name: "Login", bundle: nil).instantiateInitialViewController() as! LoginViewController
                nextViewController.modalPresentationStyle = .fullScreen
 
                nextViewController.flutterResult = result
                controller.present(nextViewController, animated: true)
            default :
                result(nil)
            }
          })
 
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

methodChannelのハンドラを設定する段階でFlutterViewControllerを取得しています。FlutterではこのFlutterViewController一枚(正確には内包されているFlutterViewクラス)に各画面のUIを描画する作りになっています。とはいえネイティブアプリ上の扱いはあくまでViewControllerなので、いつも通りpresent等で遷移することができます。

また、flutter側の処理を再開させるにはsetMethodCallHandler()で渡されるFlutterResultを保持しておく必要があります。今回はコードを短くするためLoginViewControllerのメンバ変数に持たせていますが、実際はdelegateなどでやりとりした方が無難でしょう。

class LoginViewController: UIViewController {
    var flutterResult: FlutterResult?
 
    @IBAction func loginTapped(_ sender: UIButton) {
        // ここでログインの処理
        self.flutterResult?("ios_token")
        self.dismiss(animated: true)
    }
}

LoginViewControllerにはボタン押下処理を記述しています。実際は通信し、ログイントークンやjsonを返す事になります。

Androidの呼び出し

Kotlinも同様にAndroid標準の画面遷移で移動します。

<span>var </span><span>result</span>: MethodChannel.Result? = <span>null
</span>
<span>override fun </span>configureFlutterEngine(flutterEngine: FlutterEngine) {
    <span>super</span>.configureFlutterEngine(flutterEngine)
    MethodChannel(flutterEngine.<span>dartExecutor</span>.<span>binaryMessenger</span>, <span>"Channel"</span>).setMethodCallHandler <span>{ </span>call, result <span>-&gt;
</span><span>        </span><span>when </span>(call.<span>method</span>) {
            <span>"goLogin" </span>-&gt; {
                <span>val </span>intent = Intent(<span>this</span>, LoginActivity::<span>class</span>.<span>java</span>)
                <span>if </span>(intent.resolveActivity(<span>packageManager</span>) != <span>null</span>) {
                    <span>this</span>.<span>result </span>= result
                    startActivityForResult(intent, <span>0</span>)
                }
            }
            <span>else </span>-&gt;
                result.success(<span>null</span>)
        }
    <span>}
</span>}
 
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    val token = data?.extras?.getString("token")
    result?.success(token)
}

Activityが終了したことをFlutter側に伝える必要ため今回はstartActivityForResultを使用し、LoginActivity画面から結果を取るようにしています。

class LoginActivity: Activity() {
    lateinit var binding : LoginBinding
 
    override fun onCreate(savedInstanceState: Bundle?) {
        binding =   LoginBinding.inflate(layoutInflater)
        setContentView(binding.root)
 
        binding.loginButton.setOnClickListener {
            // ここにログインの処理
            intent.putExtra("token", "android_token")
            setResult(RESULT_OK, intent)
            finish()
        }
        super.onCreate(savedInstanceState)
    }
}

LoginActivityではiOSアプリと同じく、アクティビティ終了時に情報を渡します。

記事の続きは下のリンクをクリック!

https://rightcode.co.jp/blog/information-technology/flutter-native-syain

【2024年卒】新卒採用エントリー開始しました!

特設ページはこちら:https://rightcode.co.jp/recruit/entry-2024

※募集は終了致しました。次回の募集までもうしばらくお待ちください

インターン募集!未経験ok、チャレンジ精神ある方求む

メディア運営:https://rightcode.co.jp/recruit/intern-media

社長と一杯飲みながらお話しませんか?(転職者向け)

特設ページはこちら: https://rightcode.co.jp/gohan-sake-president-talk

もっとワクワクしたいあなたへ

現在、ライトコードでは「WEBエンジニア」「スマホアプリエンジニア」「ゲームエンジニア」、「デザイナー」「WEBディレクター」「エンジニアリングマネージャー」「営業」などを積極採用中です!

有名WEBサービスやアプリの受託開発などの企画、開発案件が目白押しの状況です。

  • もっと大きなことに挑戦したい!
  • エンジニアとしてもっと成長したい!
  • モダンな技術に触れたい!

現状に満足していない方は、まずは、エンジニアとしても第一線を走り続ける弊社代表と気軽にお話してみませんか?

ネット上では、ちょっとユルそうな会社に感じると思いますが(笑)、
実は技術力に定評があり、沢山の実績を残している会社ということをお伝えしたいと思っております。

  • ライトコードの魅力を知っていただきたい!
  • 社風や文化なども知っていただきたい!
  • 技術に対して熱意のある方に入社していただきたい!

一度、【Wantedly内の弊社ページ】や【コーポレートサイト】をのぞいてみてください。

【コーポレートサイト】https://rightcode.co.jp/

【採用募集】https://rightcode.co.jp/recruit(こちらからの応募がスムーズ)

【wantedlyぺージ】https://www.wantedly.com/companies/rightcode

株式会社ライトコードでは一緒に働く仲間を募集しています
今週のランキング
株式会社ライトコードからお誘い
この話題に共感したら、メンバーと話してみませんか?