Flutter Templates
FlutterとBack4Appを使用してAIメール応答アプリを構築する方法
40 分
はじめに このチュートリアルでは、フロントエンドに flutter を使用し、バックエンドに back4app を使用して、ai駆動のメール応答アプリを構築します。このアプリは、gmailやoutlookなどのメールサービスと統合し、aiモデル(openaiのgpt 3など)を使用して受信メールを分析し、パーソナライズされた応答を生成します。このチュートリアルの終わりまでには、メールを管理し、自動応答を生成し、ユーザーがメールのやり取りをパーソナライズできる機能を持つアプリが完成します。 このアプリは、ユーザー認証、データストレージ、クラウド機能を処理するためにback4appのparse serverの力を活用し、サーバーインフラを管理する必要のないスケーラブルなバックエンドソリューションを提供します。ai機能とメールサービスを統合することで、flutter開発スキルが向上し、高度なデータ駆動型アプリケーションを構築するための基盤が提供されます。 前提条件 このチュートリアルを完了するには、次のものが必要です back4appアカウント が必要です。 back4app https //www back4app com/ で無料アカウントにサインアップしてください。 flutter sdk がローカルマシンにインストールされていること。公式の flutterインストールガイド https //flutter dev/docs/get started/install に従って、オペレーティングシステムに合わせてインストールしてください。 dart と flutter 開発の基本的な知識。flutterが初めての場合は、進む前に flutterドキュメント https //flutter dev/docs を確認することをお勧めします。 rest api と 非同期プログラミング に関する知識。 aiサービスプロバイダー (例:openai)とのアカウント。aiモデルにアクセスするためのapiキーにサインアップしてください。 メールアカウント (gmailまたはoutlook)を統合テスト用に用意してください。 ステップ1 — back4appバックエンドの設定 このステップでは、新しいback4appアプリケーションを作成し、データクラスを設定し、flutterアプリと連携するようにバックエンドを構成します。 1 1 back4appで新しいアプリケーションを作成する あなたの back4app ダッシュボード https //dashboard back4app com/ にログインします。 "新しいアプリを作成" をクリックします。 アプリ名を入力します。 アプリ名 (例:"aiメール応答者")と、あなたの アプリアイコン を選択します。 プロンプトが表示された場合は、サーバーの場所を選択します。 "作成" をクリックします。 1 2 アプリケーションキーを取得する アプリのダッシュボードで、 アプリ設定 > セキュリティとキー に移動します。 アプリケーションid と クライアントキー をメモします。flutterアプリの設定に必要です。 1 3 データモデルクラスを定義する 次のクラスをback4appで作成します ユーザー (デフォルト) emailaccount emailtemplate responsehistory 1 3 1 emailaccountクラスを作成する 「 データベース 」に移動し、 「ブラウザ」 を選択します。 「 クラスを作成する 」をクリックします。 「 カスタム 」を選択し、名前を emailaccount にします。 「 クラスを作成する 」をクリックします。 次の列を追加します emailaccount ユーザー (pointer< user>) user オブジェクトを指します。 emailaddress (string) accounttype (string) 例:gmail、outlook。 authtoken (string) 暗号化されたトークンを保存します。 1 3 2 emailtemplateクラスを作成する 新しいクラスを作成する手順を繰り返します emailtemplate 次の列を追加します emailtemplate ユーザー (pointer< user>) templatename (string) templatecontent (string) templatetype (string) 例:正式、カジュアル、フォローアップ。 1 3 3 responsehistoryクラスを作成する 新しいクラスを作成します responsehistory 次の列を追加します responsehistory ユーザー (pointer< user>) originalemailsummary (string) 生成された応答 (string) ユーザー編集済み応答 (string) 節約された時間 (number) 1 4 クラスレベルの権限を設定する 認証されたユーザーのみが自分のデータにアクセスできることを確認してください 各クラスで、 セキュリティ セクションに移動します。 クラスレベルの権限 (clp)を設定して、認証されたユーザーのみが読み書きアクセスできるようにします。 ステップ2 — flutterプロジェクトの初期化 このステップでは、flutterプロジェクトを設定し、back4appに接続するように構成します。 2 1 新しいflutterプロジェクトを作成する ターミナルを開いて、次のコマンドを実行します flutter create ai email responder プロジェクトディレクトリに移動します cd ai email responder 2 2 必要な依存関係を追加する 次の依存関係を追加するために、 pubspec yaml を開きます dependencies flutter sdk flutter parse server sdk flutter ^4 0 1 flutter email sender ^5 0 2 http ^0 13 4 provider ^6 0 2 fl chart ^0 45 1 パッケージをインストールするには、 flutter pub get を実行します。 2 3 アプリでparseを初期化する 新しいファイルを作成します lib/config/back4app config dart // lib/config/back4app config dart const string keyapplicationid = 'your application id'; const string keyclientkey = 'your client key'; const string keyparseserverurl = 'https //parseapi back4app com'; 「 'your application id' 」と 'your client key' をback4appからのキーに置き換えてください。 「 lib/main dart 」でparseを初期化します // lib/main dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'config/back4app config dart'; import 'app dart'; void main() async { widgetsflutterbinding ensureinitialized(); await parse() initialize( keyapplicationid, keyparseserverurl, clientkey keyclientkey, autosendsessionid true, debug true, ); runapp(myapp()); } 「 lib/app dart 」を作成します // lib/app dart import 'package\ flutter/material dart'; import 'screens/home screen dart'; class myapp extends statelesswidget { @override widget build(buildcontext context) { return materialapp( title 'ai email responder', theme themedata( primaryswatch colors blue, ), home homescreen(), ); } } ステップ3 — ユーザー認証の実装 これからparse serverを使用してユーザー登録とログインを実装します。 3 1 認証画面を作成する 作成する lib/screens/login screen dart と lib/screens/signup screen dart 簡潔にするために、ログイン機能に焦点を当てます。 // lib/screens/login screen dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'home screen dart'; class loginscreen extends statefulwidget { @override loginscreenstate createstate() => loginscreenstate(); } class loginscreenstate extends state\<loginscreen> { final texteditingcontroller usernamecontroller = texteditingcontroller(); final texteditingcontroller passwordcontroller = texteditingcontroller(); future\<void> douserlogin() async { final username = usernamecontroller text trim(); final password = passwordcontroller text trim(); final user = parseuser(username, password, null); final response = await user login(); if (response success) { navigator pushreplacement( context, materialpageroute(builder (context) => homescreen()), ); } else { showerror(response error! message); } } void showerror(string message) { scaffoldmessenger of(context) showsnackbar(snackbar(content text('error $message'))); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('login'), ), body padding( padding const edgeinsets all(16), child column( children \[ textfield( controller usernamecontroller, decoration inputdecoration(labeltext 'username', icon icon(icons person)), ), textfield( controller passwordcontroller, decoration inputdecoration(labeltext 'password', icon icon(icons lock)), obscuretext true, ), sizedbox(height 20), elevatedbutton( onpressed douserlogin, child text('login'), ), ], ), ), ); } } 3 2 ホーム画面のナビゲーションを更新する 修正する lib/app dart して、ユーザーが認証されていない場合はログイン画面にリダイレクトします。 // lib/app dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'screens/home screen dart'; import 'screens/login screen dart'; class myapp extends statelesswidget { future\<bool> hasuserloggedin() async { final currentuser = await parseuser currentuser() as parseuser?; return currentuser != null; } @override widget build(buildcontext context) { return futurebuilder\<bool>( future hasuserloggedin(), builder (context, snapshot) { if (snapshot hasdata && snapshot data == true) { return materialapp( title 'ai email responder', theme themedata(primaryswatch colors blue), home homescreen(), ); } else { return materialapp( title 'ai email responder', theme themedata(primaryswatch colors blue), home loginscreen(), ); } }, ); } } ステップ 4 — メールサービスの統合 このステップでは、 flutter email sender パッケージを使用してメール統合を設定します。 4 1 メール送信者の設定 androidおよびiosの設定に必要な権限を追加します。 android用 , android/app/src/main/androidmanifest xml \<uses permission android\ name="android permission internet"/> ios用 , info plist に以下を含めることを確認してください \<key>nsapptransportsecurity\</key> \<dict> \<key>nsallowsarbitraryloads\</key> \<true/> \</dict> 4 2 メール送信機能の実装 lib/services/email service dart // lib/services/email service dart import 'package\ flutter email sender/flutter email sender dart'; class emailservice { future\<void> sendemail(string subject, string body, list\<string> recipients) async { final email email = email( body body, subject subject, recipients recipients, ishtml false, ); await flutteremailsender send(email); } } 4 3 メール取得の実装 (プレースホルダー) gmailのようなプロバイダーからのメール取得にはoauthとapi統合が必要で、複雑になる可能性があります。このチュートリアルでは、メール取得をシミュレートします。 作成する lib/models/email dart // lib/models/email dart class email { final string sender; final string subject; final string body; final datetime date; email({ required this sender, required this subject, required this body, required this date, }); } 作成する lib/services/email service dart (ダミーデータで更新) // lib/services/email service dart import ' /models/email dart'; class emailservice { future\<list\<email>> fetchemails() async { // simulate network delay await future delayed(duration(seconds 2)); return \[ email( sender 'john doe\@example com', subject 'meeting reminder', body 'don\\'t forget about our meeting tomorrow at 10 am ', date datetime now() subtract(duration(hours 1)), ), // add more dummy emails ]; } // existing sendemail method } ステップ5 — 応答生成のためのaiサービスの統合 これからai統合を設定して、メール応答を生成します。 5 1 ai apiへのhttpリクエストを設定する 「 http 」パッケージをインストールします(すでに追加されています)。 「 lib/services/ai service dart 」を作成します。 // lib/services/ai service dart import 'dart\ convert'; import 'package\ http/http dart' as http; class aiservice { final string apikey = 'your openai api key'; final string apiurl = 'https //api openai com/v1/engines/davinci/completions'; future\<string> generateresponse(string emailcontent) async { final response = await http post( uri parse(apiurl), headers { 'authorization' 'bearer $apikey', 'content type' 'application/json', }, body jsonencode({ 'prompt' 'reply to the following email \n$emailcontent', 'max tokens' 150, }), ); if (response statuscode == 200) { final data = jsondecode(response body); return data\['choices']\[0]\['text'] trim(); } else { throw exception('failed to generate response'); } } } 注意: 「 'your openai api key' 」を実際のapiキーに置き換えてください。 5 2 応答エディタウィジェットを実装する 「 lib/widgets/response editor dart 」を作成します。 // lib/widgets/response editor dart import 'package\ flutter/material dart'; class responseeditor extends statelesswidget { final string initialresponse; final texteditingcontroller controller; responseeditor({required this initialresponse}) controller = texteditingcontroller(text initialresponse); @override widget build(buildcontext context) { return textfield( controller controller, maxlines null, decoration inputdecoration( hinttext 'edit your response here ', border outlineinputborder(), ), ); } } 5 3 ai生成応答の表示 「 lib/screens/email detail screen dart 」で、aiサービスを統合します。 // lib/screens/email detail screen dart import 'package\ flutter/material dart'; import ' /models/email dart'; import ' /services/ai service dart'; import ' /widgets/response editor dart'; import ' /services/email service dart'; class emaildetailscreen extends statefulwidget { final email email; emaildetailscreen({required this email}); @override emaildetailscreenstate createstate() => emaildetailscreenstate(); } class emaildetailscreenstate extends state\<emaildetailscreen> { final aiservice aiservice = aiservice(); final emailservice emailservice = emailservice(); string? airesponse; bool isloading = false; future\<void> generateresponse() async { setstate(() { isloading = true; }); try { final response = await aiservice generateresponse(widget email body); setstate(() { airesponse = response; }); } catch (e) { scaffoldmessenger of(context) showsnackbar(snackbar(content text('ai error $e'))); } finally { setstate(() { isloading = false; }); } } void sendresponse(string responsetext) { emailservice sendemail( 're ${widget email subject}', responsetext, \[widget email sender], ); scaffoldmessenger of(context) showsnackbar(snackbar(content text('email sent'))); } @override void initstate() { super initstate(); generateresponse(); } @override widget build(buildcontext context) { final responseeditor = airesponse != null ? responseeditor(initialresponse airesponse!) null; return scaffold( appbar appbar( title text('email from ${widget email sender}'), ), body padding( padding const edgeinsets all(16), child isloading ? center(child circularprogressindicator()) column( children \[ text(widget email body), sizedbox(height 20), responseeditor != null ? expanded(child responseeditor) container(), elevatedbutton( onpressed () { if (responseeditor != null) { sendresponse(responseeditor controller text); } }, child text('send response'), ), ], ), ), ); } } ステップ6 — メールテンプレートの管理 これからback4appを使用してメールテンプレート管理を実装します。 6 1 メールテンプレートモデルを定義する 作成する lib/models/email template dart // lib/models/email template dart import 'package\ parse server sdk flutter/parse server sdk dart'; class emailtemplate extends parseobject implements parsecloneable { emailtemplate() super('emailtemplate'); emailtemplate clone() this(); @override emailtemplate clone(map\<string, dynamic> map) => emailtemplate clone() fromjson(map); string? get templatename => get\<string>('templatename'); set templatename(string? value) => set\<string>('templatename', value); string? get templatecontent => get\<string>('templatecontent'); set templatecontent(string? value) => set\<string>('templatecontent', value); string? get templatetype => get\<string>('templatetype'); set templatetype(string? value) => set\<string>('templatetype', value); } 6 2 テンプレートサービスを実装する 作成する lib/services/template service dart // lib/services/template service dart import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /models/email template dart'; class templateservice { future\<list\<emailtemplate>> fetchtemplates() async { final query = querybuilder\<emailtemplate>(emailtemplate()); final response = await query find(); if (response success && response results != null) { return response results as list\<emailtemplate>; } else { return \[]; } } future\<void> addtemplate(emailtemplate template) async { await template save(); } } 6 3 テンプレート管理画面を作成する 作成する lib/screens/template management screen dart // lib/screens/template management screen dart import 'package\ flutter/material dart'; import ' /models/email template dart'; import ' /services/template service dart'; class templatemanagementscreen extends statefulwidget { @override templatemanagementscreenstate createstate() => templatemanagementscreenstate(); } class templatemanagementscreenstate extends state\<templatemanagementscreen> { final templateservice templateservice = templateservice(); list\<emailtemplate> templates = \[]; bool isloading = true; future\<void> loadtemplates() async { final fetchedtemplates = await templateservice fetchtemplates(); setstate(() { templates = fetchedtemplates; isloading = false; }); } @override void initstate() { super initstate(); loadtemplates(); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('email templates'), ), body isloading ? center(child circularprogressindicator()) listview\ builder( itemcount templates length, itembuilder (context, index) { final template = templates\[index]; return listtile( title text(template templatename ?? 'unnamed'), subtitle text(template templatetype ?? 'no type'), ); }, ), floatingactionbutton floatingactionbutton( onpressed () { // implement template creation }, child icon(icons add), )); } } ステップ 7 — 応答履歴の追跡を実装する これから、aiが生成した応答とユーザーの編集を分析のためにback4appに保存します。 7 1 responsehistoryモデルを定義する 作成する lib/models/response history dart // lib/models/response history dart import 'package\ parse server sdk flutter/parse server sdk dart'; class responsehistory extends parseobject implements parsecloneable { responsehistory() super('responsehistory'); responsehistory clone() this(); @override responsehistory clone(map\<string, dynamic> map) => responsehistory clone() fromjson(map); string? get originalemailsummary => get\<string>('originalemailsummary'); set originalemailsummary(string? value) => set\<string>('originalemailsummary', value); string? get generatedresponse => get\<string>('generatedresponse'); set generatedresponse(string? value) => set\<string>('generatedresponse', value); string? get usereditedresponse => get\<string>('usereditedresponse'); set usereditedresponse(string? value) => set\<string>('usereditedresponse', value); int? get timesaved => get\<int>('timesaved'); set timesaved(int? value) => set\<int>('timesaved', value); } 7 2 メール送信後のレスポンス履歴を保存する 更新する lib/screens/email detail screen dart の sendresponse メソッド import ' /models/response history dart'; // void sendresponse(string responsetext) async { await emailservice sendemail( 're ${widget email subject}', responsetext, \[widget email sender], ); // save response history final responsehistory = responsehistory() set('originalemailsummary', widget email body) set('generatedresponse', airesponse) set('usereditedresponse', responsetext) set('timesaved', calculatetimesaved()); await responsehistory save(); scaffoldmessenger of(context) showsnackbar(snackbar(content text('email sent'))); navigator pop(context); } int calculatetimesaved() { // placeholder implementation return 5; // assume 5 minutes saved } ステップ 8 — チャートを使った分析の追加 これから fl chart を使って基本的な分析ダッシュボードを実装します。 8 1 分析サービスの実装 作成する lib/services/analytics service dart // lib/services/analytics service dart import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /models/response history dart'; class analyticsservice { future\<list\<responsehistory>> fetchresponsehistories() async { final query = querybuilder\<responsehistory>(responsehistory()); final response = await query find(); if (response success && response results != null) { return response results as list\<responsehistory>; } else { return \[]; } } future\<int> calculatetotaltimesaved() async { final histories = await fetchresponsehistories(); return histories fold(0, (sum, item) => sum + (item timesaved ?? 0)); } } 8 2 アナリティクスダッシュボードを作成する 作成する lib/screens/analytics screen dart // lib/screens/analytics screen dart import 'package\ flutter/material dart'; import 'package\ fl chart/fl chart dart'; import ' /services/analytics service dart'; class analyticsscreen extends statefulwidget { @override analyticsscreenstate createstate() => analyticsscreenstate(); } class analyticsscreenstate extends state\<analyticsscreen> { final analyticsservice analyticsservice = analyticsservice(); int totaltimesaved = 0; future\<void> loadanalytics() async { final timesaved = await analyticsservice calculatetotaltimesaved(); setstate(() { totaltimesaved = timesaved; }); } @override void initstate() { super initstate(); loadanalytics(); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('analytics'), ), body center( child text('total time saved $totaltimesaved minutes'), )); } } ステップ 9 — オフラインサポートの実装 これから、parseのローカルデータストアを使用してアプリにオフライン機能を追加します。 9 1 ローカルデータストアを有効にする に lib/main dart , ローカルデータストアを有効にします await parse() initialize( keyapplicationid, keyparseserverurl, clientkey keyclientkey, autosendsessionid true, debug true, corestore await corestoresembastimp getinstance(), ); 9 2 データモデルのピン留めの修正 あなたのモデル(例: responsehistory )に、オブジェクトをピン留めおよびピン留め解除するメソッドを追加します future\<void> pin() async { await this pin(); } future\<void> unpin() async { await this unpin(); } 9 3 オフラインマネージャーの実装 作成する lib/utils/offline manager dart // lib/utils/offline manager dart import ' /models/email dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; class offlinemanager { future\<void> cacheemails(list\<email> emails) async { for (var email in emails) { final parseobject = parseobject('email') set('sender', email sender) set('subject', email subject) set('body', email body) set('date', email date); await parseobject pin(); } } future\<list\<email>> getcachedemails() async { final query = querybuilder\<parseobject>(parseobject('email')); final response = await query frompin() find(); if (response success && response results != null) { return response results! map((e) { return email( sender e get\<string>('sender') ?? '', subject e get\<string>('subject') ?? '', body e get\<string>('body') ?? '', date e get\<datetime>('date') ?? datetime now(), ); }) tolist(); } else { return \[]; } } } 9 4 接続がないときにオフラインデータを使用する メール取得ロジックで接続を確認し、オフラインの場合はキャッシュデータを使用してください。 結論 このチュートリアルでは、flutterとback4appを使用してaiメール応答アプリを構築しました。あなたは 必要なデータモデルとセキュリティ設定を持つback4appバックエンドを設定しました。 flutterプロジェクトを初期化し、back4appに接続しました。 parse serverを使用してユーザー認証を実装しました。 メール送信を統合し、メール取得をシミュレートしました。 aiサービスを統合してメール応答を生成しました。 メールテンプレートを管理し、back4appに保存しました。 分析のために応答履歴を追跡しました。 基本的な分析を追加しました。 fl chart を使用して。 parseのローカルデータストアを使用してオフラインサポートを実装しました。 このアプリは、oauthを使用した実際のメール統合、高度なai機能、改善されたui/uxデザインなど、より高度な機能を構築するための基盤を提供します。 次のステップ メール統合 oauth認証を使用してgmailまたはoutlook apiから実際のメールを取得します。 強化されたai機能 より良い応答のためにaiプロンプトを微調整し、ユーザーデータに基づいてパーソナライズを実装します。 ui/uxの改善 より良いユーザー体験のためにアプリのインターフェースを強化します。 テストとデプロイメント ユニットテストと統合テストを作成し、アプリをアプリストアにデプロイする準備をします。 セキュリティの強化 機密データを暗号化し、堅牢なエラーハンドリングと入力検証を実装します。 flutterでback4appを使用する方法についての詳細は、 back4app flutterガイド https //www back4app com/docs/flutter/parse sdk/ を参照してください。