【Gemini】モールス信号変換アプリを作ってみた
本記事の目的について
この度、コミュニティのテクニカルインフルエンサー企画である「技術の観点でこんなことをしているメンバーが関西にいる」という外部発信を目的とした活動に参加いたしました。
そのため、これから様々なアプリ開発を行いながら記事として投稿していければと思います。
今回はいつか無人島に流された時のために「モールス信号変換アプリ」を開発したのでそちらをご紹介します。
また、今回はGemini2.0 Flashを使いながらアプリ開発を行いました。
世間がo3やo4-miniで賑わっているなか、今更感もありますが使い心地もちょこちょこ書いていこうかと思います。
アプリ開発の背景
昨今の技術コミュニティでは、機械学習やAIといった分野に注目が集まることが多いですが、一方で、より基礎的でありながらも興味深い技術も存在します。モールス信号はその一つであり、デジタルな現代においても、その原理や応用には学ぶべき点があると考えました。
このアプリ開発を通じて、古典的な通信技術と現代のモバイル技術を組み合わせる試みを行い、その過程を共有することで、技術的な興味の幅広さや、身近なツールを用いた技術探求の可能性を感じていただければ幸いです。
開発するアプリの概要
今回開発した「モールス信号変換アプリ」は、以下の機能を備えたシンプルなアプリケーションです。
- テキスト入力: ユーザーが変換したいテキストをアプリ内の入力フォームに入力します。
- モールス信号変換: アプリケーションが入力されたテキストに対応するモールス信号(「・」と「ー」のシーケンス)に変換します。
- ライト出力: 変換されたモールス信号に基づき、スマートフォンのカメラのフラッシュライトを点滅させることで、視覚的な情報伝達を行います。
これをGeminiと対話しながら作っていきます。
技術的側面の紹介と実装の過程
アプリ開発には、クロスプラットフォーム開発フレームワークであるFlutterを採用しました。これにより、iOSとAndroidの両プラットフォームに対応したアプリケーションを比較的効率的に開発することができます。
1. モールス信号対応データの設計
アプリケーション内で文字とモールス信号を対応付けるために、Dartの Map データ構造を使用しました。英語のアルファベット、数字に加え、日本語のひらがなとカタカナにも対応させるように、データ定義を行いました。
final Map<String, String> _morseCodeMap = {
'A': '.-', 'B': '-...', /* ... */
};
final Map<String, String> _japaneseMorseCodeMap = {
'ア': '.-.-', 'イ': '.-..', 'あ': '.-.-', 'い': '.-..', /* ... */
};
2. スマートフォンライトの制御
スマートフォンのフラッシュライトを制御するために、Flutterの公式プラグインである camera パッケージを利用しました。このパッケージを通じて、カメラデバイスへのアクセスとフラッシュモードの設定を行うことができます。
今回の開発は基本的にGemini任せだったのですがこのパッケージ周りが一番詰まりました。
こちらの環境を細かくは知らないため当然ですが、最終的に新しく環境を作り直したので、今後アプリ開発をするのであればGenAIとの認識の差異を減らすために環境作成から出力してもらうべきかもしれません。
import 'package:camera/camera.dart';
import 'dart:async';
// ...
Future<void> _toggleFlash(bool on) async {
try {
if (on) {
await _controller.setFlashMode(FlashMode.torch);
} else {
await _controller.setFlashMode(FlashMode.off);
}
setState(() {
_isFlashOn = on;
});
} catch (e) {
// エラーハンドリング
}
}
モールス信号の「・」と「ー」の長さを表現するために、非同期処理を提供する Future.delayed を利用し、_toggleFlash 関数の呼び出し間隔を調整しました。
小難しいことを言っているように思えますが、やりたいことをGeminiに投げれば勝手に非同期処理を実装してくれます。非常にありがたいです。
Future<void> _playMorseCode(String text) async {
// ...
for (int i = 0; i < morseCode.length; i++) {
String signal = morseCode[i];
if (signal == '.') {
await _toggleFlash(true);
await Future.delayed(Duration(milliseconds: _dotDuration));
await _toggleFlash(false);
await Future.delayed(Duration(milliseconds: _dotDuration));
} else if (signal == '-') {
await _toggleFlash(true);
await Future.delayed(Duration(seconds: 1)); // 例
await _toggleFlash(false);
await Future.delayed(Duration(milliseconds: _dotDuration));
}
// 文字間のスペース処理
}
// ...
}
3. ユーザーインターフェースの設計
アプリケーションのUIについては今回は特にこだわらずにシンプルな構成のまま実装しました。テキスト入力フィールド、変換開始ボタン、そして変換されたモールス信号の表示領域を配置しています。
TextField(
controller: _textController,
decoration: InputDecoration(labelText: '変換するテキストを入力'),
),
ElevatedButton(
onPressed: () {
_playMorseCode(_textController.text);
},
child: Text('スタート'),
),
Text('モールス信号: $_morseCodeDisplay'),
今後の展望とコミュニティへの貢献
このアプリ開発は、個人的な興味の一環として実施しましたが、その過程や成果をコミュニティ内で共有することで、新たなアイデアの創出に繋がればと考えています。
今後は、UIの変更や漢字への対応(現在はひらがな、カタカナ、英語のみ)など、改善を進めていく予定です。
また、次回以降のアプリ開発についてのZenn記事を書く際には、今話題のo3などを使うことで今回のGemini2.0 Flashとの使用感の違いなども記載できればなと思います。
最後に、関西TfLSコミュニティでは多様な技術に関心を持つメンバーが、それぞれの興味に基づいた活動を行っています。これからもよろしくお願いします。
Discussion