Flutter日记或笔记管理插件journify_flutter的使用
Flutter日记或笔记管理插件journify_flutter的使用
journify
警告
该项目目前仅处于Beta阶段,并受Journify的抢先体验条款约束。我们鼓励您尝试此新库。请通过GitHub问题/PR反馈您的意见,并随时提交拉取请求。
journify 是一种轻松将Journify添加到您的Flutter应用中的方法。
支持以下平台:
- Android
- iOS
- MacOS
- Web
某些目标插件可能不支持所有平台功能。请参阅其各自的平台SDK以获取更多详细信息。
目录
安装
运行以下命令:
flutter pub add journify
导入所需的包:
import 'package:journify/client.dart';
从Pilot升级
在Pilot阶段,我们将此库的包名从analytics重命名为journify。升级到v1版本后需要进行一些更改:
在pubspec.yaml文件中,移除analytics包并替换为journify:
- analytics:
- git:
- url: https://github.com/journify/journify-flutter-sdk
- ref: main
- path: packages/core
+ journify: ^1.0.1
在Dart文件中,将导入语句从package:journify改为package:journify:
- import 'package:journify/client.dart';
+ import 'package:journify/client.dart';
权限
Android
在应用的AndroidManifest.xml文件中,添加以下行:
<uses-permission android:name="android.permission.INTERNET"/>
使用
设置客户端
该包提供了一个名为createClient的方法,可以用来创建Journify客户端。此中央客户端管理所有跟踪事件。建议将其作为主应用程序状态类的属性添加。
示例代码:
const writeKey = 'JOURNIFY_API_KEY';
final analytics = createClient(Configuration(writeKey));
必须至少传递writeKey。以下是其他配置选项的列表:
客户端选项
| 名称 | 默认值 | 描述 |
|---|---|---|
writeKey(必需) |
‘’ | 您的Journify API密钥。 |
debug |
false | 设置为false时,不会生成任何信息日志。 |
collectDeviceId |
false | 设置为true以自动从DRM API收集Android设备上的设备ID。 |
flushPolicies |
count=30,time=20s | 控制何时将事件批次发送到插件的刷新策略列表。 |
apiHost |
“t.journify.dev/v1” | 用于指定区域性的Journify事件端点。 |
cdnHost |
“cdn-settings.journify.com/v1” | 用于指定区域性的Journify设置端点。 |
errorHandler |
null | 自定义错误处理器。默认情况下会将错误记录到标准的Flutter日志中。 |
trackApplicationLifecycleEvents |
false | 启用自动跟踪应用程序生命周期事件:安装、打开、更新、后台化)。 |
trackDeeplinks |
false | 启用自动跟踪用户通过深度链接打开应用的行为。*注意:发送此标志时,sdk插件_appsflyer将忽略onAppOpenAttribution。 |
autoAddJournifyDestination |
true | 设置为false以跳过添加JournifyDestination插件。 |
defaultIntegrationSettings |
null | 如果请求从Journify获取设置失败时使用的插件设置。 |
maxBatchSize |
true | 一次向API发送的最大事件数量。 |
appStateStream |
null | 用于覆盖应用程序前台或后台事件流。 |
requestFactory |
true | 用于覆盖生成HTTP请求的工厂。类型:RequestFactory。 |
storageJson |
true | 启用或禁用自动为序列化库生成JSON文件。 |
客户端方法
跟踪(Track)
track 方法用于记录用户的任何操作,以及描述这些操作的属性。
方法签名:
Future track(String event: string, {Map<String, dynamic>? properties});
示例使用:
journify.track("View Product", properties: {
"productId": 123,
"productName": "Striped trousers"
});
屏幕(Screen)
screen 方法用于记录用户在移动应用中看到的每个屏幕,以及关于屏幕的任何属性。
方法签名:
Future screen(String name: string, {Map<String, dynamic>? properties});
示例使用:
journify.screen("ScreenName", properties: {
"productSlug": "example-product-123",
});
对于自动屏幕跟踪的设置,请参见下方说明。
标识(Identify)
identify 方法用于将用户与其操作联系起来,并记录有关他们的特征。这包括唯一的用户ID以及您知道的任何可选特征,如电子邮件、姓名等。特性选项可以包含您希望与用户关联的任何信息,但在使用任何保留的用户特征时,请确保仅将其用于其预期含义。所有保留特征均由UserTraits类强类型定义。当使用未列为保留用户特征的特性时,这些特性将归入custom属性下。
方法签名:
Future identify({String? userId, UserTraits? userTraits});
示例使用:
journify.identify(userId: "testUserId", userTraits: UserTraits(
username: "MisterWhiskers",
email: "hello@test.com",
custom: {
"plan": "premium"
}
);
组(Group)
group API调用是将个人用户与组关联起来的方式——无论是公司、组织、账户、项目、团队还是其他您想到的类似概念!这包括唯一的组ID以及您了解的任何可选组特征,如公司名称、行业、员工人数等。特性选项可以包含您希望与组关联的任何信息,但在使用任何保留的组特征时,请确保仅将其用于其预期含义。所有保留特征均由GroupTraits类强类型定义。当使用未列为保留用户特征的特性时,这些特性将归入custom属性下。
方法签名:
Future group(String groupId, {GroupTraits? groupTraits});
示例使用:
journify.group("some-company", groupTraits: GroupTraits(
name: 'journify',
custom: {
"region": "UK"
}
);
别名(Alias)
alias 方法用于合并两个用户身份,有效连接两组用户数据。这是一个高级方法,但在某些目的地成功管理用户身份时是必需的。
方法签名:
Future alias(String newUserId);
示例使用:
journify.alias("user-123");
重置(Reset)
reset 方法清除当前用户和组的库内部状态。这对于允许用户在不同身份之间切换的应用程序非常有用。
注意:每次调用reset时,都会自动生成一个新的匿名ID。
方法签名:
void reset();
示例使用:
journify.reset();
刷新(Flush)
默认情况下,分析数据将在30秒后或当20个事件累积时发送到API,以先发生者为准。如果用户关闭应用后有事件未发送,则会在应用恢复时触发刷新。这些值可以通过flushAt和flushInterval配置选项进行修改。您也可以手动触发刷新事件。
方法签名:
Future flush();
示例使用:
journify.flush();
高级清理(Advanced Cleanup)
您可能不需要这个!
如果您需要重新初始化客户端,即在应用程序生命周期中多次调用createClient以创建同一客户端,请在旧客户端上调用此方法以清除任何订阅和计时器。
示例代码:
var analytics = createClient(Configuration(writeKey));
journify.cleanup();
analytics = createClient(Configuration(writeKey));
如果不这样做,旧客户端实例仍然存在并保留计时器,导致所有事件触发两次。
理想情况下,您不应该需要这样做,且journify客户端应在应用程序生命周期中只初始化一次。
自动屏幕跟踪
为每个导航操作发送screen()事件很快就会变得乏味,因此您可能希望全局跟踪导航。为此,您需要将分析导航观察器添加到应用程序的导航观察器中。例如,如果您使用的是MaterialApp类,则可以添加以下内容:
return MaterialApp(navigatorObservers: [
ScreenObserver()
]);
插件+时间线架构
您可以完全控制事件在上传到journify API之前如何被处理。
为了自定义事件创建后的处理方式,您可以在事件通过的处理管道中创建和放置各种插件。此管道称为时间线。
插件类型
| 插件类型 | 描述 |
|---|---|
| before | 在事件处理开始前执行。 |
| enrichment | 作为事件处理的第一层执行。 |
| destination | 在事件开始传递到目的地时执行。 |
| after | 在所有事件处理完成后执行。可用于执行清理操作等。 |
| utility | 仅在手动调用时执行,如日志记录。 |
插件可以有自己的本地代码(如iOS独有的analytics_plugin_idfa),也可以包装底层库(如analytics_plugin_firebase,它在幕后使用firebase_core和firebase_analytics)。
目的地插件
journify作为DestinationPlugin已内置。您可以添加任意多个其他目的地插件,并将事件和数据上传到它们,而不仅仅是journify。
或者,如果您更喜欢,可以在设置客户端时传递autoAddSegmentDestination = false。这会阻止SegmentDestination插件自动为您添加。
添加插件
您可以在任何时候通过add()方法添加插件。
示例代码:
import 'package:journify/client.dart';
import 'package:journify/event.dart';
import 'package:journify/state.dart';
import 'package:journify_plugin_advertising_id/plugin_advertising_id.dart';
import 'package:journify_plugin_idfa/plugin_idfa.dart';
import 'package:journify_plugin_firebase/plugin_firebase.dart' show FirebaseDestination;
const writeKey = 'Journify_API_KEY';
class _MyAppState extends State<MyApp> {
final analytics = createClient(Configuration(writeKey));
@override
void initState() {
super.initState();
initPlatformState();
analytics
.addPlugin(FirebaseDestination(DefaultFirebaseOptions.currentPlatform));
journify.addPlugin(PluginAdvertisingId());
journify.addPlugin(PluginIdfa());
}
}
编写自己的插件
插件通过扩展提供的插件类之一来实现。可用的插件类如下:
PluginEventPluginDestinationPluginUtilityPluginPlatformPlugin
任何插件都必须是这些类的扩展。
您可以通过覆盖基类的不同方法来自定义功能。例如,这是一个简单的Logger插件:
import 'dart:convert';
import 'package:journify/journify.dart';
import 'package:journify/event.dart';
import 'package:journify/plugin.dart';
import 'package:journify/logger.dart';
class EventLogger extends DestinationPlugin {
var logKind = LogFilterKind.debug;
EventLogger() : super("event_logger");
@override
void configure(Analytics analytics) {
pAnalytics = analytics;
}
@override
Future<RawEvent?>? execute(RawEvent event) async {
log("${event.type.toString().toUpperCase()} event${event is TrackEvent ? " (${event.event})" : ''} saved: \n${jsonEncode(event.toJson())}",
kind: logKind);
return event;
}
}
由于它覆盖了execute()方法,此Logger将在时间线上每经过一个事件时调用log。
支持的插件
以下表格列出了您可以使用的插件以满足您的跟踪需求:
| 插件 | 包名 |
|---|---|
| Adjust | analytics_plugin_adjust |
| AppsFlyer | analytics_plugin_appsflyer |
| Firebase | analytics_plugin_firebase |
| IDFA | analytics_plugin_idfa |
| Android Advertising ID | analytics_plugin_advertising-id |
控制上传的刷新策略
要更细粒度地控制事件的上传时间,您可以使用FlushPolicies。
刷新策略定义了决定何时刷新的策略,可以基于间隔、特定时间、接收到一定数量的事件甚至接收到特定事件。这为您提供了更多的灵活性来决定何时将事件发送到journify。
要使用刷新策略,可以在客户端配置中设置它们:
import 'package:journify/flush_policies/count_flush_policy.dart';
import 'package:journify/flush_policies/timer_flush_policy.dart';
final analytics = createClient(Configuration(/*...*/, flushPolicies: [
CountFlushPolicy(10),
TimerFlushPolicy(100000)
]));
您可以同时设置多个策略。每当其中任何一个策略决定是时候刷新时,它将触发事件上传。其余策略将重置,以便在每次刷新后重新启动逻辑。
这意味着只有第一个达到shouldFlush的策略能够触发刷新。在上述示例中,事件计数达到5或计时器达到500毫秒,无论哪个先发生,都将触发刷新。
我们有一些标准的刷新策略:
CountFlushPolicy:当达到一定数量的事件时触发。TimerFlushPolicy:按毫秒间隔触发。StartupFlushPolicy:仅在客户端启动时触发。
添加或移除策略
刷新策略的主要优点之一是您可以在运行时添加和删除策略。当您想要减少或增加刷新次数时,这非常强大。
例如,如果您检测到用户没有网络连接,您可以禁用刷新:
if (isConnected) {
journify.addFlushPolicy(policiesIfNetworkIsUp);
} else {
journify.removeFlushPolicy(policiesIfNetworkIsUp)
}
创建自己的刷新策略
您可以通过实现FlushPolicy接口或扩展FlushPolicyBase类(它已经创建并处理了shouldFlush值的重置)来为您的应用程序需求创建自定义刷新策略。
FlushPolicy只需要实现一个方法:
onEvent(RawEvent event):在您的客户端跟踪的每个事件上被调用。
并且可以选择实现以下方法:
reset():在刷新触发后调用(由您的策略、另一个策略或手动触发)。start():在刷新策略启用并添加到客户端时执行。这是开始后台操作、进行异步调用、配置执行前事情的好地方。
它们还有一个shouldFlush布尔值。当此值设置为true时,客户端将尝试上传事件。每个策略应根据自己的逻辑将此值重置为false,尽管通常在reset方法中这样做。
示例代码:
import 'package:journify/event.dart';
import 'package:journify/flush_policies/flush_policy.dart';
class FlushOnScreenEventsPolicy extends FlushPolicy {
@override
onEvent(RawEvent event) {
// 仅在发生屏幕事件时刷新
if (event is ScreenEvent) {
this.shouldFlush = true;
}
}
@override
reset() {
// 超类将重置shouldFlush值,以便下一个屏幕事件再次触发刷新
// 但您可以在其他事件到来或超时时重置值
super.reset();
}
}
自定义日志记录
默认情况下,任何日志记录都是通过标准的Flutter日志机制完成的。要自定义日志记录,您可以构建自己的日志记录器,它必须实现LogTarget混合类。例如:
import 'package:journify/logger.dart';
void customDebugLog(String msg) {
// ...
}
void customWarningLog(String msg) {
// ...
}
void customErrorLog(String msg) {
// ...
}
class CustomLogger with LogTarget {
@override
void parseLog(LogMessage log) {
switch (log.kind) {
case LogFilterKind.debug:
customDebugLog("journify: ${log.message}");
break;
case LogFilterKind.warning:
customWarningLog("journify: ${log.message}");
break;
case LogFilterKind.error:
customErrorLog("journify: ${log.message}");
break;
}
}
}
// 将默认日志记录器设置为使用CustomLogger
LogFactory.logger = CustomLogger();
处理错误
您可以通过errorHandler选项处理分析客户端错误。
错误处理程序配置接收一个函数,该函数将在分析客户端发生错误时调用。它将接收一个异常,该异常将扩展来自errors.dart的错误之一。
您可以使用此错误处理程序在出现问题时触发客户端的不同行为。例如,如果客户端受到速率限制,您可以使用错误处理程序来切换刷新策略以减少激进性:
import 'package:journify/errors.dart';
//...
final flushPolicies = [CountFlushPolicy(5), TimerFlushPolicy(500)];
void errorHandler(Exception error) {
if (error is NetworkServerLimited) {
// 删除所有刷新策略
journify.removeFlushPolicy(journify.getFlushPolicies());
// 添加不太持久的刷新策略
journify.addFlushPolicy([
CountFlushPolicy(100),
TimerFlushPolicy(5000)
]);
}
}
final analytics = createClient(Configuration(writeKey),
errorHandler: errorHandler,
flushPolicies: flushPolicies);
从插件报告错误
插件还可以通过使用journify客户端的.error函数报告错误,我们建议使用PluginError保持一致性,并附加innerError以实际捕获的异常:
import 'package:journify/errors.dart';
//...
try {
distinctId = await mixpanel.getDistinctId();
} catch (e) {
journify.error(
PluginError('Error: Mixpanel error calling getDistinctId', e)
);
}
更多关于Flutter日记或笔记管理插件journify_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter日记或笔记管理插件journify_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
journify_flutter 是一个用于在 Flutter 应用中集成日记或笔记管理功能的插件。它提供了一系列工具和组件,帮助开发者快速构建日记或笔记应用。以下是如何使用 journify_flutter 插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml 文件中添加 journify_flutter 插件的依赖:
dependencies:
flutter:
sdk: flutter
journify_flutter: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get 来获取依赖。
2. 初始化 Journify
在应用的 main.dart 文件中,初始化 Journify 插件:
import 'package:flutter/material.dart';
import 'package:journify_flutter/journify_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化 Journify
await Journify.initialize(
apiKey: 'YOUR_API_KEY', // 替换为你的 API Key
enableLogging: true, // 是否启用日志
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Journify Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: JournalScreen(),
);
}
}
3. 创建日记或笔记
你可以使用 Journify 提供的 API 来创建日记或笔记。以下是一个简单的示例:
import 'package:flutter/material.dart';
import 'package:journify_flutter/journify_flutter.dart';
class JournalScreen extends StatefulWidget {
@override
_JournalScreenState createState() => _JournalScreenState();
}
class _JournalScreenState extends State<JournalScreen> {
final TextEditingController _titleController = TextEditingController();
final TextEditingController _contentController = TextEditingController();
Future<void> _saveJournal() async {
final String title = _titleController.text;
final String content = _contentController.text;
if (title.isNotEmpty && content.isNotEmpty) {
await Journify.createJournal(
title: title,
content: content,
);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Journal saved successfully!')),
);
_titleController.clear();
_contentController.clear();
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Please fill in both title and content.')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My Journal'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _titleController,
decoration: InputDecoration(labelText: 'Title'),
),
SizedBox(height: 16.0),
TextField(
controller: _contentController,
decoration: InputDecoration(labelText: 'Content'),
maxLines: 5,
),
SizedBox(height: 16.0),
ElevatedButton(
onPressed: _saveJournal,
child: Text('Save Journal'),
),
],
),
),
);
}
}
4. 获取日记或笔记
你可以使用 Journify.getJournals() 方法来获取所有保存的日记或笔记:
Future<void> _getJournals() async {
final List<Journal> journals = await Journify.getJournals();
journals.forEach((journal) {
print('Title: ${journal.title}, Content: ${journal.content}');
});
}
5. 删除日记或笔记
你可以使用 Journify.deleteJournal() 方法来删除特定的日记或笔记:
Future<void> _deleteJournal(String journalId) async {
await Journify.deleteJournal(journalId);
}
6. 更新日记或笔记
你可以使用 Journify.updateJournal() 方法来更新特定的日记或笔记:
Future<void> _updateJournal(String journalId, String newTitle, String newContent) async {
await Journify.updateJournal(
journalId: journalId,
title: newTitle,
content: newContent,
);
}
7. 处理错误
在使用 Journify 时,可能会遇到错误。你可以使用 try-catch 块来捕获和处理这些错误:
try {
await Journify.createJournal(
title: 'My Title',
content: 'My Content',
);
} catch (e) {
print('Error: $e');
}
8. 自定义配置
Journify 提供了一些配置选项,例如日志级别、用户 ID 等。你可以在初始化时或在运行时进行配置:
await Journify.initialize(
apiKey: 'YOUR_API_KEY',
enableLogging: true,
userId: 'USER_ID', // 可选,用于标识用户
);
9. 事件跟踪
你还可以使用 Journify 来跟踪用户事件,例如用户打开应用的次数、用户点击按钮的次数等:
await Journify.trackEvent('app_opened');
await Journify.trackEvent('button_clicked', properties: {'button_name': 'save_journal'});
10. 用户属性
你可以使用 Journify 来设置用户属性,例如用户的姓名、电子邮件等:
await Journify.setUserProperties({
'name': 'John Doe',
'email': 'john.doe@example.com',
});
11. 用户 ID
你可以使用 Journify 来设置用户 ID,以便在分析中跟踪用户:
await Journify.setUserId('USER_ID');
12. 重置用户
如果你想要重置用户数据(例如用户注销时),你可以使用 Journify.reset() 方法:
await Journify.reset();

