はじめに
Rustでデスクトップアプリを作るためのフレームワークであるTauri 2.0が正式リリースされました(https://v2.tauri.app/blog/tauri-20/)。
目新しい機能として次のようなものがあります。
- モバイル対応
- プラグイン機能と権限回りの強化
今回、この2つの機能に触ってみたいと思います。 具体的には「現在の位置情報を取得して表示するAndroidアプリ」です。
では早速作り始めましょう。
必要なもののインストール
必要なものは次の通りです。
- Rust(https://www.rust-lang.org/learn/get-started)
- お好きなJavaScriptのパッケージ管理システム
- Android Studioとそれに付随するSDK(https://v2.tauri.app/start/prerequisites/#android)
詳しくはこちらを読んでください。
プロジェクトの作成
お好きなパッケージ管理システムを使ってお好きなフレームワークと言語を使ってプロジェクトを構築してください。
今回自分はnpm + React + TypeScriptで作りました。
npm create tauri-app@latest
cd tauri-gps
npm install
このままビルドするとスマホからアクセスできない旨のエラーが出るので、src-tauri/tauri.conf.json
のbuild.beforeDevCommand
の項目に--host
引数を渡すように修正し、このようにします。:"npm run dev -- --host"
こちら(https://v2.tauri.app/start/prerequisites/#android)で挙げられている環境変数の設定ができたらAndroid用のバイナリのビルドを行います。
npm run tauri android init npm run tauri android dev
これでアプリが立ち上がるはずです。
プラグインの追加
位置情報を取得するためのプラグインを追加します。
Tauriのプラグインで公式の物はhttps://github.com/tauri-apps/plugins-workspace/tree/v2/pluginsにあります。グッとにらむとどうやらgeolocation
というやつがあるようです。これを探していくとcratesやdoc.rsなどのサイトが見つかります。
- https://crates.io/crates/tauri-plugin-geolocation
- https://docs.rs/tauri-plugin-geolocation/2.0.0/tauri_plugin_geolocation/index.html
- https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/geolocation
これらのドキュメントを元にプラグインを追加します。
npm add @tauri-apps/plugin-geolocation
cd src-tauri
cargo add tauri-plugin-geolocation
次にRustのファイルを変更します。src-tauri/src/lib.rs
に次の一行を加えます。
#[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_geolocation::init()) .invoke_handler(tauri::generate_handler![]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }
これでプラグインが有効化されます。
位置情報を取得する機能を実装する
フロントエンド側で位置情報を取得する機能を実装します。 ここでは簡単に、ボタンを押すと位置情報を取得して緯度経度を丸めて表示するコードを書きます。
import { useState } from "react"; +import { + checkPermissions, + requestPermissions, + getCurrentPosition, + Position +} from '@tauri-apps/plugin-geolocation' import "./App.css"; function App() { + const [phonePos, setPhonePos] = useState<Position | null>(null); + async function getPos() { + let permissions = await checkPermissions() + if ( + permissions.location === 'prompt' || + permissions.location === 'prompt-with-rationale' + ) { + permissions = await requestPermissions(['location']) + } + + if (permissions.location === 'granted') { + const pos = await getCurrentPosition() + setPhonePos(pos); + } + } return ( <div className="container"> + <button onClick={getPos}>位置情報を取得</button> + <p>{phonePos ? <>({Math.round(phonePos.coords.latitude)}, {Math.round(phonePos.coords.longitude)})</>: null}</p> </div> ); } export default App;
簡単に解説を書くと、
checkPermissions()
関数で現在の位置情報に関する権限を取得する- 位置情報取得の権限が許可されていなかった場合は
requestPermissions(['location'])
でユーザーに権限をリクエストする - 権限がある場合は
getCurrentPosition()
で位置情報を取得し、値を更新する - 位置情報を表示する
となります。
位置情報の値はPosition
型で表されます。この型の定義はdoc.rsに書いてあるものを自動変換しているようです。:https://docs.rs/tauri-plugin-geolocation/2.0.0/tauri_plugin_geolocation/struct.Position.html
権限の許可
これで表示されている「位置情報を取得する」ボタンを押してみると現在位置の緯度経度が表示される、かと思いきや表示されません。 それどころかターミナルには「権限が許可されていないよ」と出てきます。
この原因は2.0になって強化された権限回りにあります。1.0ではI/Oなどの操作ごとにallowlist
で権限の許可を行っていましたが、2.0からはプラグインの各機能ごとに許可の有無を制御できるようになりました(https://v2.tauri.app/learn/security/using-plugin-permissions/)。
権限の許可はsrc-tauri/capabilities/default.json
ファイルで行います。
"permissions"
プロパティに、このプラグインで追加された権限を追加します。
今回watchPosition
という関数を使っていないので、この権限は許可していません。
{ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "Capability for the main window", "windows": ["main"], "permissions": [ "core:default", "shell:allow-open", + "geolocation:allow-check-permissions", + "geolocation:allow-clear-permissions", + "geolocation:allow-get-current-position", + "geolocation:allow-request-permissions", + "geolocation:deny-watch-position", + "geolocation:deny-clear-watch" ] }
動作結果
これで動くようになりました。位置情報を丸める前の結果が驚くほど正確でびっくりしました。凄いですね。
まとめ
モバイルアプリも作れるようになったのは嬉しいですね。
これらのコードはGitHubで公開しています(https://github.com/puripuri2100/tauri-gps)。