Flutter应用内评论插件in_app_review_plugin的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter应用内评论插件in_app_review_plugin的使用

描述

此插件提供了一个包含两个选项的对话窗口:

  • 在Google Play/应用商店中评价应用程序
  • 提交反馈并发送到指定邮箱

应用程序评分

该插件在Android上使用In-App Review API,在iOS/macOS上使用SKStoreReviewController。

感谢

  • Android: 在应用上传至Play市场后才能测试应用内评论。可以使用开发者账户进行测试和内部应用共享。
  • iOS: 应用内评论UI无需上传即可测试,但提交按钮仅在通过App Store下载应用时可用(也可以使用TestFlight)。

发送反馈

插件允许通过一个方法发送邮件。调用InAppReviewPlugin.send_email并传递所需参数:

  • message
  • name
  • service id
  • template id
  • public token

它使用的是EmailJS服务,可以通过API调用来触发邮件发送。你需要创建一个免费帐户,并连接一个实际的电子邮件帐户作为发件人。

使用

requestReview()

以下代码会触发应用内评论提示。请注意,这不应频繁使用,因为底层API对这一功能有严格的配额限制,以提供良好的用户体验。

import 'package:in_app_review_plugin/in_app_review_plugin.dart';

final _inAppReviewPlugin = InAppReviewPlugin();

...

_inAppReviewPlugin.requestReview();

...
建议
  • 在用户使用您的应用足够长时间以提供有用反馈之后再使用此功能,例如在完成游戏关卡或几天后使用。
  • 尽量少用此功能,否则不会出现弹窗。
避免
  • 通过按钮触发此功能,因为它只有在底层API的配额未被超出时才会工作。
  • 中断用户正在进行的任务。

测试

Android

必须将您的应用上传到Play Store才能测试requestReview()。一种简便的方法是构建APK/APP Bundle并通过内部应用共享上传。

测试过程中无法创建真实评论,并且提交按钮会被禁用以强调这一点。

更多详情请参见 Android官方文档

iOS

requestReview()可以通过iOS模拟器或物理设备进行测试。

注意,通过TestFlight测试时,requestReview()不会产生任何效果。

测试过程中无法创建真实评论,并且提交按钮会被禁用以强调这一点。

要求

Android

需要Android 5 Lollipop(API 21)或更高版本,并且需要安装Google Play商店。

iOS

需要iOS版本10.3。


完整示例代码

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

import 'package:email_validator/email_validator.dart';
import 'package:in_app_review_plugin/in_app_review_plugin.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _inAppReviewPlugin = InAppReviewPlugin();
  final navigatorKey = GlobalKey<NavigatorState>();

  [@override](/user/override)
  void initState() {
    super.initState();
    initPlatformState();
  }

  // 平台消息是异步的,因此我们在异步方法中初始化。
  Future<void> initPlatformState() async {

    // 如果在异步平台消息仍在飞行时从树中删除了小部件,则我们想要丢弃回复而不是调用
    // setState来更新我们的不存在的外观。
    if (!mounted) return;

  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '应用内评论',
      navigatorKey: navigatorKey,
      home: Scaffold(
        appBar: AppBar(title: const Text('示例项目')),
        body: Builder(builder: (context) =>
          Center(
              child: TextButton(
                onPressed: (){
                  ReviewDialog(
                      context: context,
                      btnRateOnPress: (){
                        Navigator.of(context).pop();
                        _inAppReviewPlugin.requestReview();
                      },
                      btnFeedbackOnPress: (){
                        Navigator.of(context).pop();
                        Navigator.push(
                          context,
                          MaterialPageRoute(builder: (context) => EmailRoute()),
                        );
                      }
                  ).show();
                },
                child: const Text('显示对话框'),
              )
          ),
        ),
      ),
    );
  }
}

class EmailRoute extends StatelessWidget {
  EmailRoute({super.key});

  final _formKey = GlobalKey<FormState>();
  final nameController = TextEditingController();
  final emailController = TextEditingController();
  final messageController = TextEditingController();
  final _messangerKey = GlobalKey<ScaffoldMessengerState>();
  final _inAppReviewPlugin = InAppReviewPlugin();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
        title: '应用内评论',
        scaffoldMessengerKey: _messangerKey,
        home: Scaffold(
          backgroundColor: const Color(0xfff5f5fd),
          body: Center(
            child: Container(
              height: 450,
              width: 400,
              margin: const EdgeInsets.symmetric(
                horizontal: 40,
                vertical: 20,
              ),
              padding: const EdgeInsets.symmetric(
                horizontal: 40,
                vertical: 20,
              ),
              decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(10),
                  boxShadow: [
                    BoxShadow(
                        offset: const Offset(0, 5),
                        blurRadius: 10,
                        spreadRadius: 1,
                        color: Colors.grey[300]!)
                  ]),
              child: Form(
                key: _formKey,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    const Text('反馈邮件',
                        style:
                        TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                    TextFormField(
                      controller: nameController,
                      decoration: const InputDecoration(hintText: '姓名'),
                      validator: (value) {
                        if (value == null || value.isEmpty) {
                          return '*Required';
                        }
                        return null;
                      },
                    ),
                    TextFormField(
                      controller: emailController,
                      decoration: const InputDecoration(hintText: '电子邮件'),
                      validator: (email) {
                        if (email == null || email.isEmpty) {
                          return 'Required*';
                        } else if (!EmailValidator.validate(email)) {
                          return '请输入有效的电子邮件';
                        }
                        return null;
                      },
                    ),
                    TextFormField(
                      controller: messageController,
                      decoration: const InputDecoration(hintText: '消息'),
                      maxLines: 5,
                      validator: (value) {
                        if (value == null || value.isEmpty) {
                          return '*Required';
                        }
                        return null;
                      },
                    ),
                    SizedBox(
                      height: 45,
                      width: 110,
                      child: TextButton(
                        style: TextButton.styleFrom(
                            primary: Colors.white,
                            backgroundColor: const Color(0xff151534),
                            shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(40))),
                        onPressed: () async {
                          if (_formKey.currentState!.validate()) {
                            final response = await _inAppReviewPlugin.sendEmail(
                                nameController.value.text,
                                'artur.rakhmatullin@gmail.com',
                                messageController.value.text,
                                'your service name',
                                'your template id',
                                'your public token',
                            );
                            _messangerKey.currentState!.showSnackBar(
                              response == 200
                                  ? const SnackBar(
                                  content: Text('消息已发送!'),
                                  backgroundColor: Colors.green)
                                  : const SnackBar(
                                  content: Text('发送消息失败!'),
                                  backgroundColor: Colors.red),
                            );
                            nameController.clear();
                            emailController.clear();
                            messageController.clear();
                          }
                        },
                        child: const Text(
                            '发送', style: TextStyle(fontSize: 16)),
                      ),
                    ),
                    SizedBox(
                        height: 45,
                        width: 110,
                        child: TextButton(
                            style: TextButton.styleFrom(
                                primary: Colors.white,
                                backgroundColor: const Color(0xff151534),
                                shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(40))),
                            onPressed: () {
                              Navigator.pop(context);
                            },
                            child: const Text('返回')
                        )
                    )
                  ],
                ),
              ),
            ),
          ),)
    );
  }
}

更多关于Flutter应用内评论插件in_app_review_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter应用内评论插件in_app_review_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter应用中,in_app_review 插件可以帮助你直接在应用内请求用户评分和评论,而无需让用户跳转到应用商店页面。这对于提升应用的评分和用户反馈非常有帮助。以下是如何使用 in_app_review 插件的详细步骤。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 in_app_review 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  in_app_review: ^2.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装依赖。

2. 导入插件

在你的 Dart 文件中导入 in_app_review 插件:

import 'package:in_app_review/in_app_review.dart';

3. 初始化 InAppReview

你可以通过 InAppReview.instance 来获取 InAppReview 的实例:

final InAppReview inAppReview = InAppReview.instance;

4. 请求应用内评论

你可以使用 requestReview 方法来请求用户评分和评论:

void requestReview() async {
  if (await inAppReview.isAvailable()) {
    inAppReview.requestReview();
  } else {
    // 如果应用内评论不可用,可以跳转到应用商店页面
    inAppReview.openStoreListing();
  }
}

isAvailable() 方法用于检查设备是否支持应用内评论功能。如果支持,调用 requestReview() 方法会显示一个系统弹窗,提示用户评分和评论。如果不支持,你可以通过 openStoreListing() 方法直接打开应用商店页面。

5. 监听用户操作

在某些情况下,你可能需要知道用户是否完成了评分或评论。in_app_review 插件目前没有直接提供回调功能,但你可以通过其他方式(如 Firebase Analytics 或自定义事件)来跟踪用户行为。

6. 处理权限和限制

  • iOS: 在 iOS 上,requestReview() 方法会显示一个系统弹窗,提示用户评分和评论。每个应用在一年内只能显示 3 次系统弹窗,超过次数后,requestReview() 将不会显示弹窗。
  • Android: 在 Android 上,requestReview() 方法会显示一个系统弹窗,提示用户评分和评论。Google Play 会限制弹窗的显示频率,通常不会在短时间内多次显示。

7. 测试

在开发过程中,你可以通过以下方式进行测试:

  • iOS: 在 iOS 模拟器上,requestReview() 方法不会显示弹窗,但会记录调用。
  • Android: 在 Android 模拟器上,requestReview() 方法会显示弹窗。

完整示例代码

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('In-App Review Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              requestReview();
            },
            child: Text('Request Review'),
          ),
        ),
      ),
    );
  }

  void requestReview() async {
    final InAppReview inAppReview = InAppReview.instance;

    if (await inAppReview.isAvailable()) {
      inAppReview.requestReview();
    } else {
      inAppReview.openStoreListing();
    }
  }
}
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!