FlutterからTerminalコマンドを実行する方法

2022-06-21

はじめに

登場人物がみんなパチンコを打つクズ娘なのですが、とても愛らしく愛おしい漫画です。 毎回更新が楽しみです。 名古屋はパチンコ会社の直営店があるとか、三重県はオールナイトパチンコという文化があるとか、旅行先でパチンコを打ちに行って負けるという話があるのですが何かいいなと思います。

ぱちん娘。

推してます。

Flutterからコマンド実行したいんだけど

LinuxやWindows向けのアプリ開発をするにあたって、FlutterアプリからTerminalコマンドやShell Scriptなどを立ち上げて簡易的に情報取得したいニーズってあると思うんですね。

ipアドレス取得したり、Flutterで作るのがしんどいソフトを裏で動かすためにコマンド実行したり用途は多々あります。

今回の開発対象は、スマホアプリ向けの機能と、デスクトップ向けの機能で完全に切れてるのでこういう各OSで使えるコマンドを活用していきたいなと思ってます。

process_run

process_run

ProcessをLinux/Windows/Macから呼び出すのを支援するパッケージです。 今回はこのパッケージを使います。

インストールはこうです。

flutter pub add process_run

コード例

サンプルコードを削ってコマンド実行出来る関数を用意しました。 文字列で実行したいコマンドを引数に渡すような作りになってます。

import 'package:process_run/shell.dart';

Future<void> executeProcess(String cmd) async {
  var shell = Shell();
  await shell.run(cmd);
}

呼び出し元はこんな書き方をします。

executeProcess('echo Hello,World');

ボタンが押されたら指定されたコマンドが実行されるようにします。

TextButton(
  onPressed: () {
    executeProcess('echo Hello,World');
  },
  child: const Text('click here'),
)

前回記事で作っていたコードにこのコマンド実行機能を追加したコードがこちらです。 長いので一部のみ掲載しています。

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextButton(
              onPressed: () {
                executeProcess('echo Hello,World');
              },
              child: const Text('click here'),
            ),
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            QrImage(
              data: 'https://kenpos.dev',
              version: QrVersions.auto,
              size: 350.0,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).push(MaterialPageRoute(
            builder: (context) => const QRViewExample(),
          ));
        },
        tooltip: 'Increment',
        child: const Icon(Icons.search),
      ),
    );
  }
}

実行結果

画面レイアウトはこうなります。今回追加したのは、click hereとなっているテキストボタンです。

ボタンを押してコマンドを実行するとFlutterを実行しているTerminalに表示されます。

Performing hot reload...                                                
Reloaded 0 libraries in 53ms.
$ echo Hello,World
Hello,World

コマンドが実行されていることが確認できました。

実行結果を取得して、Textに反映する

process_run package documentation

戻り値付きで取得するさいに、ProcessResultというconstructorsに入ってくるようです。

今回は実行結果が欲しいだけなのでProcessResultのoutTextを取得します。

Future<String> getExecuteProcessResult(String cmd) async {
  var shell = Shell();
  var result = await shell.run(cmd);
  setState(() {});
  return result.outText;
}

Future型で関数は返ってくるので、そこからString型に詰め直して表示する必要があります。 このように書きました。

TextButton(
  onPressed: () async {
    // executeProcess('echo Hello,World');
    _cmdresults = await getExecuteProcessResult('echo Hello,World');
  },
  child: const Text('click here'),
),
Text(
  '$_cmdresults',
  style: Theme.of(context).textTheme.headline4,
),

実行結果

click here実行前

click here実行後

まとめ

CLIツール郡の資産をFlutterから享受できるようになりました。 別ツールを立ち上げて処理をして戻ってくるとかそういった使い方に期待できます。

今日はここまで