👓

【Flutter】ユーザーからスクショ付きフィードバック送信機能の実装紹介(feedbackパッケージの使い方)

に公開

要約

アプリ内でユーザーが現在の画面のスクショにペイントが可能で、テキストとともに送信できる仕組みを、feedbackパッケージで最短導入します。
この記事では、以下3段階で実装します。
 ①最小構成でフィードバックダイアログを表示して送信
 ②フィードバックダイアログのUIをカスタム
 ③メールで送信

フィードバックダイアログ初期表示 カスタムフィードバックダイアログ

対象

以下の方を対象にしてます

  • Flutterアプリにアプリ内から送信可能なフィードバック導線を追加したい
  • 再現性の高い不具合報告フローを実装したい

問題設定

文字だけの報告だと情報不足や誤解が生じがちです。スクショが貼れたら言葉で伝える手間が省けるのにということも多々あります。
また、プラットフォーム依存の不具合報告はプラットフォーム側の変更に追従する必要が出てきます。
そのような悩みの一助になりうるのが今回のfeedbackパッケージになればと思います。

解決アプローチ

1. フィードバックダイアログを表示でき、送信ボタン押せるところまでの実装

実際に送信はしませんが、送信契機まで実装します。
feedbackパッケージを追加したら、たった数行でこの機能が実装できます

import 'package:flutter/material.dart';
import 'package:feedback/feedback.dart';

// MaterialAppをBetterFeedbackで囲う
void main() => runApp(const BetterFeedback(child: MyApp()));

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Feedback最小実装')),
        body: Center(
          child: ElevatedButton(
            child: const Text('フィードバックを送る'),
            onPressed: () {
              // フィードバックダイアログを表示する
              BetterFeedback.of(context).show((UserFeedback feedback) {
                // text: ユーザー入力、screenshot: PNGバイト列、extra: 任意情報
                debugPrint('text: ${feedback.text}');
                debugPrint('bytes: ${feedback.screenshot.length}');
                debugPrint('extra: ${feedback.extra}');
              });
            },
          ),
        ),
      ),
    );
  }
}

重要なのは2点だけ!

  • MaterialAppをBetterFeedback()で囲う
  • BetterFeedback.of(context).show()を呼び出す契機を作る

たったこれだけでペイントされたスクショとユーザーの入力したテキストが取得できます。

2. フィードバックダイアログのカスタム方法

フィードバックダイアログが出せたら、次はユーザーに入力してもらうダイアログをカスタムしましょう。
こちらも実装方法はいたってシンプルです。

void main() => runApp(
  BetterFeedback(
    // ダイアログのUIを自作ウィジェットで置き換え
    feedbackBuilder: (context, onSubmit, scrollController) {
      return _CustomFeedbackSheet(onSubmit: onSubmit, scrollController: scrollController);
    },
    // 見た目(背景色や描画色)の指定
    theme: FeedbackThemeData(
      background: Colors.black.withOpacity(0.35),
      feedbackSheetColor: Colors.white,
      drawColors: [Colors.red, Colors.green, Colors.blue],
    ),
    darkTheme: FeedbackThemeData.dark(),
    child: const MyApp(),
  ),
);

BetterFeedback.feedbackBuilder()に実装したいWidgetを実装するだけです。
今回の例だと_CustomFeedbackSheet()がそれにあたります。

3. フィードバック内容をメールで送る方法

アプリ内の挙動としては、

  1. スクショのデータを一時的にファイル化
  2. メールアプリに1のファイル(スクショ)を添付ファイルとして渡す
  3. 入力させたテキストはメールの本文に載せる

上記をemail_senderとpath_providerパッケージを使って実装していく

まずは、スクショのデータを一時的にファイル化する

Future<String> _writePng(Uint8List pngBytes) async {
  final dir = await getTemporaryDirectory(); // path_providerパッケージのメソッド
  final path = '${dir.path}/feedback.png';
  final file = File(path);
  await file.writeAsBytes(pngBytes);
  return path;
}

次に、メールアプリに添付ファイルと本文を渡す部分の実装をemail_senderパッケージで実現します。
以下ボタンを画面から呼び出せば、ファイル化したスクショとフィードバックテキスト、カスタムで追加した情報をメールアプリに渡すことができます。

class EmailSendDemo extends StatelessWidget {
  const EmailSendDemo({super.key});

  
  Widget build(BuildContext context) {
    return ElevatedButton(
      child: const Text('メールで送信'),
      onPressed: () {
        BetterFeedback.of(context).show((UserFeedback feedback) async {
          final screenshotPath = await _writePng(feedback.screenshot);

          final email = Email(
            recipients: ['support@example.com'],
            subject: '[App] ユーザーフィードバック',
            body:
                '''
【本文】${feedback.text}

【メタ】${feedback.extra}
''',
            attachmentPaths: [screenshotPath],
            isHTML: false,
          );
          await FlutterEmailSender.send(email);
        });
      },
    );
  }
}

【注意点】
Androidだと、この実装しても端末によってはメールクライアント検出に失敗すると記事がありました。AndroidManifestに明示的に記載しておくと良いようです。

<!-- android/app/src/main/AndroidManifest.xml -->
<manifest ...>
  <queries>
    <intent>
      <action android:name="android.intent.action.SENDTO" />
      <data android:scheme="mailto" />
    </intent>
  </queries>
  ...
</manifest>

よくあるハマりどころ

PlatformView(WebView/Google Mapsなど)はスクショに写らないようです。こちらはFlutterの既知制約としてあるそう。代替として文字で補足してもらう等、現状は工夫が必要です。
BetterFeedbackの置く位置はルートに置くこと。Navigatorより上に配置しないと、ダイアログが正しく重ならないようです。
機密情報の扱いには要注意です。スクショに個人情報が映る可能性があるため、フィードバックダイアログに注意文を表示し、見えないようペイントしていただく等促す必要があります。

まとめ

ほんの数行実装するだけで、注釈入りスクショとテキストが簡単に取得できます。feedbackBuilderでフォームを拡張し、extraに端末/アプリ情報を載せてメール送信できるという非常にシンプルで強力なツールの紹介でした。feedbackパッケージ作成者がfeedback_jiraというパッケージも出しているようで、Jiraとも連携できるようです。気になる方は、ぜひチェックしてみてください。

参考リンク

Discussion