Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Amplify Flutter を使おうとしたけど微妙な結果に終わった話
hmatsu47
PRO
November 26, 2021
Technology
1
3.1k
Amplify Flutter を使おうとしたけど微妙な結果に終わった話
JAWS-UG 浜松 AWS 勉強会 2021#11 2021/11/26
hmatsu47
PRO
November 26, 2021
Tweet
Share
More Decks by hmatsu47
See All by hmatsu47
SolidJS で Supabase の Row Level Security を試してみた
hmatsu47
PRO
0
160
Aurora MySQL v1 → v3 の移行(調査・計画編)
hmatsu47
PRO
0
44
社内でスピードアップコンテスト開催に挑戦した話
hmatsu47
PRO
0
210
Aurora MySQL v1 → v3 の移行を準備する
hmatsu47
PRO
1
580
Javaのレガシーな Web アプリを ECS Fargate を使って段階的に作り直し/マイグレーションする話
hmatsu47
PRO
1
230
モノレポのGitHub(Enterprise)からCodePipelineを呼び出す小ネタ
hmatsu47
PRO
0
44
コミュニティとのゆるいつながりの中での恩送り
hmatsu47
PRO
0
31
FlutterでSupabaseのPostgreSQL with PostGISを試してみた
hmatsu47
PRO
0
340
RDS/Aurora関連アップデート(2021年版)
hmatsu47
PRO
0
75
Other Decks in Technology
See All in Technology
Meet passkeys
satotakeshi
1
130
The Fractal Geometry of Software Design
vladikk
1
1.3k
Introduction To Technical Writing
olawanle_joel
0
100
【個人的】オブジェクト指向の現在地
toranoana
0
190
データエンジニアと作るデータ文化
yuki_saito
4
1.7k
Apple M1 CPUの脆弱性「PACMAN」について解説する
kuzushiki
0
110
Laravel.shibuyaで改善してきた IRT勉強会の運営方法について / IRT Study Session Improved Through Laravel Shibuya
fendo181
0
120
Building smarter apps with machine learning, from magic to reality
picardparis
4
3.2k
XRとシビックテック
satoshirobatofujimoto
0
100
雑な攻撃からELBを守る一工夫 +おまけ / Know-how to protect servers from miscellaneous attacks
hiroga
0
620
Data in Google I/O - IO Extended GDG Seoul
kennethanceyer
0
160
ソフトウェアテスト自動化、一歩前へ
yoshikiito
6
1.1k
Featured
See All Featured
The Cult of Friendly URLs
andyhume
68
4.8k
What's in a price? How to price your products and services
michaelherold
229
9.4k
Design by the Numbers
sachag
271
17k
The MySQL Ecosystem @ GitHub 2015
samlambert
238
11k
YesSQL, Process and Tooling at Scale
rocio
157
12k
How GitHub (no longer) Works
holman
296
140k
Typedesign – Prime Four
hannesfritz
34
1.4k
A designer walks into a library…
pauljervisheath
196
16k
Principles of Awesome APIs and How to Build Them.
keavy
113
15k
Fontdeck: Realign not Redesign
paulrobertlloyd
73
4.1k
Rails Girls Zürich Keynote
gr2m
86
12k
The Invisible Side of Design
smashingmag
290
48k
Transcript
Amplify Flutter を使おうとしたけれど 微妙な結果に終わった話 JAWS-UG 浜松 AWS 勉強会 2021#11 2021/11/26 まつひさ(hmatsu47)
自己紹介 松久裕保(@hmatsu47) https://qiita.com/hmatsu47 名古屋で Web インフラのお守り係をしています (ほかに書くことがなくなったので省略) 2
おことわり • ここに書いた内容は私が実際に試した時点の情報です ◦ 2021/05 〜 2021/10 頃の話です ◦ その後
Amplify CLI のバージョンアップが入っているので、すで に解消されている問題があるかもしれません ◦ 実際、最初に書いた「iOS で DataStore のレコード削除をすると 落ちる」問題はその後解消されていました 3
Flutter を試そうと思ったきっかけ • 以前 Qiita でバズったこのサイト ◦ https://korette.jp/ 4
Flutter を試そうと思ったきっかけ • 以前 Qiita でバズったこのサイト ◦ https://korette.jp/ ◦ サポーターズの一員として大量にクイズ投稿
5
Flutter を試そうと思ったきっかけ • 以前 Qiita でバズったこのサイト ◦ https://korette.jp/ ◦ サポーターズの一員として大量にクイズ投稿
◦ その後、コロナ禍で観光地の状況が一変 ◦ コロナが落ち着いた隙をみながら問題メンテナンスの旅へ 6
Flutter を試そうと思ったきっかけ • 以前 Qiita でバズったこのサイト ◦ https://korette.jp/ ◦ サポーターズの一員として大量にクイズ投稿
◦ その後、コロナ禍で観光地の状況が一変 ◦ コロナが落ち着いた隙をみながら問題メンテナンスの旅へ ◦ 旅のお供として、情報収集・整理のためのアプリが欲しい ◦ 作ることにした 7
余談ですが • ご本人は起業されて・・・ ◦ https://ambirise.jp/ 8
Amplify Flutter を試そうと思った動機 • 普通に考えたら Firebase ◦ Flutter も Google
謹製 9
Amplify Flutter を試そうと思った動機 • 普通に考えたら Firebase ◦ Flutter も Google
謹製 ◦ ありがちで面白くない ◦ どうせなら普段使っている AWS で 10
Amplify Flutter を試してみた • まずはチュートリアルから(英語版) ◦ https://docs.amplify.aws/start/getting-started/installation/q/integration/flutter/ ◦ Android で
DataStore を使った DynamoDB 同期が成功 ◦ iOS ではなぜかレコード削除で落ちる 11
Amplify Flutter を試してみた • まずはチュートリアルから(英語版) ◦ https://docs.amplify.aws/start/getting-started/installation/q/integration/flutter/ ◦ Android で
DataStore を使った DynamoDB 同期が成功 ◦ iOS ではなぜかレコード削除で落ちる ◦ しばらく放置 12
その後 • AWS へのデータ同期は一旦置いて、 ◦ アプリ本体の開発に着手 ◦ https://github.com/hmatsu47/maptool ◦ ローカルへのデータ保存に
SQLite(sqflite)を使用 13
その後 • AWS へのデータ同期は一旦置いて、 ◦ アプリ本体の開発に着手 ◦ https://github.com/hmatsu47/maptool ◦ ローカルへのデータ保存に
SQLite(sqflite)を使用 ◦ ある程度骨格ができたところで、まずは DataStore を導入 ◦ 問題発覚 14
自動生成されたデータモデルがエラーに • 原因は Null Safety ◦ Flutter 2.0 で導入されたもの ▪
この時点ではエラーにはならず ◦ Flutter 2.2 以降で非 Null Safety なデータモデルはエラーに ▪ 仕方なく温かみのある手作業で修正 15
自動生成されたデータモデルがエラーに • 原因は Null Safety ◦ Flutter 2.0 で導入されたもの ▪
この時点ではエラーにはならず ◦ Flutter 2.2 以降で非 Null Safety なデータモデルはエラーに ▪ 仕方なく温かみのある手作業で修正 ◦ ほどなくして Amplify CLI のバージョンアップ通知が ▪ バージョンアップでエラーは解消(ワーニング多くて気持ち悪いけど) 16
自動生成されたデータモデルがエラーに • 原因は Null Safety ◦ Flutter 2.0 で導入されたもの ▪
この時点ではエラーにはならず ◦ Flutter 2.2 以降で非 Null Safety なデータモデルはエラーに ▪ 仕方なく温かみのある手作業で修正 ◦ ほどなくして Amplify CLI のバージョンアップ通知が ▪ バージョンアップでエラーは解消(ワーニング多くて気持ち悪いけど) ◦ そして事件が発生 17
SQLite のテーブルが消失😱 • DataStore のローカルデータ保存 : SQLite を使用 ◦ アプリで実装している
DB は DataStore のローカルストアが 初期化される都度、巻き添えをくらって削除される 18
SQLite のテーブルが消失😱 • DataStore のローカルデータ保存 : SQLite を使用 ◦ アプリで実装している
DB は DataStore のローカルストアが 初期化される都度、巻き添えをくらって削除される ◦ たまたまコピーしてあった SQLite のファイルからローカル DB を復活させた ◦ DataStore 使うなら別のローカル DB を使うこともないか・・・ 19
SQLite のテーブルが消失😱 • DataStore のローカルデータ保存 : SQLite を使用 ◦ アプリで実装している
DB は DataStore のローカルストアが 初期化される都度、巻き添えをくらって削除される ◦ たまたまコピーしてあった SQLite のファイルからローカル DB を復活させた ◦ DataStore 使うなら別のローカル DB を使うこともないか・・・ ◦ しかし 20
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG 21
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない 22
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない 23
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない 24
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない 25
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない ◦ 諦めた 26
REST API に変えてみた • CLI で amplify add api して
REST を選んで・・・ ◦ API Gateway 経由で Node.js の DynamoDB 保存用 Lambda を 使ってチャレンジ→失敗 ▪ JavaScript 版の Amplify ではうまく行くのに・・・ 27
REST API に変えてみた • CLI で amplify add api して
REST を選んで・・・ ◦ API Gateway 経由で Node.js の DynamoDB 保存用 Lambda を 使ってチャレンジ→失敗 ▪ JavaScript 版の Amplify ではうまく行くのに・・・ ◦ Lambda の環境変数名と Node.js に書かれた環境変数を参照して いる部分の記述がなぜか違う ▪ REGION と TABLE_REGION(なお、直しても動かず) 28
REST API に変えてみた • CLI で amplify add api して
REST を選んで・・・ ◦ API Gateway 経由で Node.js の DynamoDB 保存用 Lambda を 使ってチャレンジ→失敗 ▪ JavaScript 版の Amplify ではうまく行くのに・・・ ◦ Lambda の環境変数名と Node.js に書かれた環境変数を参照して いる部分の記述がなぜか違う ▪ REGION と TABLE_REGION(なお、直しても動かず) ◦ 諦めた 29
結局、 • API Gateway & Lambda Python で回避 ◦ これ↓を参考に
https://business.ntt-east.co.jp/content/cloudsolution/column-try-20.html ◦ コード的には RESTful ではなくなったけどヨシ!! ▪ パスパラメータなし ▪ 全部 POST ◦ クライアント側だけ Amplify Flutter のライブラリを使用 30
結局、 • API Gateway & Lambda Python で回避 ◦ これ↓を参考に
https://business.ntt-east.co.jp/content/cloudsolution/column-try-20.html ◦ コード的には RESTful ではなくなったけどヨシ!! ▪ パスパラメータなし ▪ 全部 POST ◦ クライアント側だけ Amplify Flutter のライブラリを使用 31 // バックアップ情報を登録 Future<bool> backupSet( AmplifyClass amplify, String backupTitle, String describe) async { try { final RestOptions options = RestOptions( path: '/backupsets', body: const Utf8Encoder() .convert(('{"OperationType": "PUT", "Keys": {"items": [' ' {"title": ${jsonEncode(backupTitle)}' ', "describe": ${jsonEncode(describe)}}' ']}}'))); final RestOperation restOperation = amplify.API.post(restOptions: options); await restOperation.response; // ignore: avoid_print print('POST call (/backupsets) succeeded'); return true; } on ApiException catch (e) { // ignore: avoid_print print('POST call (/backupsets) failed: $e'); return false; } }
結局、 • API Gateway & Lambda Python で回避 ◦ これ↓を参考に
https://business.ntt-east.co.jp/content/cloudsolution/column-try-20.html ◦ コード的には RESTful ではなくなったけどヨシ!! ▪ パスパラメータなし ▪ 全部 POST ◦ クライアント側だけ Amplify Flutter のライブラリを使用 32 // バックアップ情報リストを AWS から取得 Future<List<BackupSet>> fetchBackupSets(AmplifyClass amplify) async { final List<BackupSet> resultList = []; try { final RestOptions options = RestOptions( path: '/backupsets', body: const Utf8Encoder().convert(('{"OperationType": "SCAN"}'))); final RestOperation restOperation = amplify.API.post(restOptions: options); final RestResponse response = await restOperation.response; final Map<String, dynamic> body = json.decode(response.body); final List<dynamic> items = body['Items']; for (dynamic item in items) { resultList.add(BackupSet(item['title'] as String, item['describe'])); } resultList.sort((a, b) => b.title.compareTo(a.title)); // ignore: avoid_print print('POST call (/backupsets) succeeded'); } catch (e) { // ignore: avoid_print print('POST call (/backupsets) failed: $e'); } return resultList; }
S3 も・・・ • 個人で使うアプリにわざわざ Cognito を入れたくない ◦ Amplify Flutter では
Storage(S3)だけ API KEY 認証がない ▪ 面倒臭い ◦ MinIO の非公式クライアント(minio)で回避 ▪ Amplify はどこへ・・・? 33
S3 も・・・ • 個人で使うアプリにわざわざ Cognito を入れたくない ◦ Amplify Flutter では
Storage(S3)だけ API KEY 認証がない ▪ 面倒臭い ◦ MinIO の非公式クライアント(minio)で回避 ▪ Amplify はどこへ・・・? 34 // 画像ファイルを S3 アップロード _uploadS3( Minio minio, Picture picture, String imagePath, String s3Bucket) async { final int pathIndexOf = picture.filePath.lastIndexOf('/'); final String fileName = (pathIndexOf == -1 ? picture.filePath : picture.filePath.substring(pathIndexOf + 1)); final String filePath = '$imagePath/$fileName'; try { await minio.fPutObject(s3Bucket, fileName, filePath); // ignore: avoid_print print('S3 upload $fileName succeeded'); return fileName; } catch (e) { // ignore: avoid_print print('S3 upload $fileName failed: $e'); return false; } }
トドメ • 距離計測と絡めてデータを取得したい ◦ DynamoDB ではできない ◦ DocumentDB は最近できるようになったようだけど高い ◦
PostGIS 使いたい 35
トドメ • 距離計測と絡めてデータを取得したい ◦ DynamoDB ではできない ◦ DocumentDB は最近できるようになったようだけど高い ◦
PostGIS 使いたい ◦ Supabase 使えばいいじゃん、PostgREST 使えるし https://supabase.com/ ▪ Amplify はどこへ・・・?(2 回目) 36
トドメ • 距離計測と絡めてデータを取得したい ◦ DynamoDB ではできない ◦ DocumentDB は最近できるようになったようだけど高い ◦
PostGIS 使いたい ◦ Supabase 使えばいいじゃん、PostgREST 使えるし https://supabase.com/ ▪ Amplify はどこへ・・・?(2 回目) 37 Future<List<SpotData>> searchNearSpot( SupabaseClient client, LatLng latLng, int distLimit) async { final PostgrestResponse selectResponse = await client.rpc('get_spots', params: { 'point_latitude': latLng.latitude, 'point_longitude': latLng.longitude, 'dist_limit': distLimit }).execute(); final List<dynamic> items = selectResponse.data; final List<SpotData> resultList = []; for (dynamic item in items) { final SpotData spotData = SpotData( item['distance'] as num, item['category_name'] as String, item['title'] as String, item['describe'] as String, LatLng((item['latitude'] as num).toDouble(), (item['longitude'] as num).toDouble()), PrefMuni(item['prefecture'] as String, item['municipality'] as String)); resultList.add(spotData); } return resultList; }
まとめ • Amplify : 頻出構成を最速で作るためのもの ◦ 自分専用の個人開発アプリとはユースケースが合わなくて当然 ◦ ユースケースが合わないものに対して無理に使うと、かえって 開発がつらくなる
◦ Flutter 以外の環境と比較するとまだ開発途上→うまく使えなく ても仕方がない 38
おまけ • 作っているアプリ(maptool) 39 Google Maps Platform ではなく Mapbox の地図を使用
←訪問(予定)先にピンを立てて、ピンに関連づけて写真撮影
おまけ • 作っているアプリ(maptool) 40 ←地図スタイル切り替え可
おまけ • 作っているアプリ(maptool) 41 ←地図スタイル切り替え可
おまけ 42 • 作っているアプリ(maptool)
おまけ 43 • 作っているアプリ(maptool) ←10km 以内にあるスポットを表示 (ほかにもいくつか機能あり)
おまけ 44 • 関連ブログ記事 ◦ https://qiita.com/hmatsu47/items/b98ef4c1a87cc0ec415d ◦ https://zenn.dev/hmatsu47/articles/846c3186f5b4fe ◦ https://zenn.dev/hmatsu47/articles/9102fb79a99a98
◦ https://zenn.dev/hmatsu47/articles/e81bf3c2bf00f8 ◦ https://qiita.com/hmatsu47/items/e4f7e310e88376d54009 ◦ https://qiita.com/hmatsu47/items/86a9c028bb5b3beeebdd ◦ https://qiita.com/hmatsu47/items/53ea68769c4fc2d76450