Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Amplify Flutter を使おうとしたけど微妙な結果に終わった話
Search
hmatsu47
PRO
November 26, 2021
Technology
1
4.8k
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
BuriKaigi2024 にボランティアスタッフとして参加した話
hmatsu47
PRO
0
56
Aurora MySQL と Redshift の zero-ETL 統合のフィルター機能を試してみた
hmatsu47
PRO
0
23
Aurora MySQL 3.06 の ML 機能で Bedrock アクセスを試してみた
hmatsu47
PRO
0
37
RDS Data API と Aurora zero-ETL 統合と BuriKaigi2024 の話
hmatsu47
PRO
0
16
RDS Data API のその後と Aurora zero-ETL 統合のデータ転送処理の話
hmatsu47
PRO
0
42
RDS_Aurora 関連アップデート 2023 版
hmatsu47
PRO
0
70
人工無能たいたん
hmatsu47
PRO
0
62
20 世紀末の地方税理士事務所で IT 導入の 1 → 10 を頑張った話
hmatsu47
PRO
0
38
パソコン通信むかしばなし
hmatsu47
PRO
0
200
Other Decks in Technology
See All in Technology
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Musicを例に~
otanet
0
310
BPStudyの200回を中心にIT業界を振り返る。そしてこれから
haru860
3
420
Cracking the KubeCon CfP
inductor
2
270
M&A戦略を支えるデータマネジメント (MIDAS Tech Study #16 GENDA Komiyama)
kommy339
1
120
Google Cloud Next '24 Recap(Cloud Run/k8s)
mokocm
0
340
M5と自作基板をくっつけてみた〜M5 Japan Tour 2024 Spring 福冈 (Fukuoka|福岡)〜
keropiyo
0
170
非同期推論システムによるコスト削減と信頼性向上
koki_nishihara
1
370
M5stackで使用できるpHセンサの開発
shinrinakamura
0
210
MapLibreとAmazon Location Service
dayjournal
1
190
2023年度にEMとして頑張ったこと
ikefukurou777
0
100
EMとして2023年度に頑張ったこと / What we did well in FY2023 as a EM
pauli
1
260
Cypress or Playwright?
rainerhahnekamp
0
170
Featured
See All Featured
Become a Pro
speakerdeck
PRO
13
4.6k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
660
120k
Optimising Largest Contentful Paint
csswizardry
13
2.4k
A Tale of Four Properties
chriscoyier
152
22k
The Cult of Friendly URLs
andyhume
74
5.7k
The Cost Of JavaScript in 2023
addyosmani
21
3.9k
How to name files
jennybc
65
93k
Docker and Python
trallard
35
2.7k
A Philosophy of Restraint
colly
197
16k
10 Git Anti Patterns You Should be Aware of
lemiorhan
649
58k
Fontdeck: Realign not Redesign
paulrobertlloyd
76
4.9k
The Straight Up "How To Draw Better" Workshop
denniskardys
228
130k
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