最近又折腾了一波鸿蒙,发现鸿蒙的数据库支持SQLite,于是乎,就想着把Sqflite鸿蒙化,于是乎,就有了这个系列。
在此之前先打个广告,有鸿蒙5+的设备朋友帮我刷个下载量,在AppGallery下载以下app打开并运行一下子,感谢:
- 乐活伴侣
- 阿默宠物
和Sqflite无关的东西
先说点和鸿蒙相关的其他的小知识点,不算什么新知识,但是可能会帮到你。 作为后起之秀,鸿蒙算是站在不少巨人的肩膀上的,因此,一些权限管理的相对比较严格,以下内容仅对上架华为应用市场的手机app有效,对于非上架华为应用市场的app及其他类型设备本人没有研究。
应用读取剪贴板
对剪切板的主动读取,不像Android那样,直接调用ClipboardManager就可以。 在鸿蒙中,应用读取剪贴板是不仅要在module.json5中申请权限:
json
{
"name": "ohos.permission.READ_PASTEBOARD",
"reason": "$string:request_paste_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
还要在申请Profile时申请ACL权限,得等ACL权限申请通过后,才能使用这个权限。目前,官方允许使用该权限的只有符合以下场景:
- 银行卡号复制:银行类应用需要读取剪贴板中的银行卡号自动生成卡片。
- 口令复制:应用需要读取剪贴板中特定格式口令,自动打开应用内对应页面。
- 文档编辑类应用。
- 输入法:系统级输入法需要读取剪贴板信息实现自动填充。应用内置输入法不能申请此权限。
同时,官方也给出了一个解决方案,使用"粘贴控件"读取剪贴板数据,使用方式请参考:使用粘贴控件,但这是一个原生组件,Flutter中似乎无法使用(当然我也没有试过)。
以下是我在申请时,给我的答复:
makefile
审核意见: 开发者您好:
受限权限仅少量符合特殊场景的应用可在通过审批后使用,您的场景不符合权限使用要求,请使用非权限的替代方案实现功能。
粘贴场景ArkUI输入框支持长按拉起toolbar,可以直接粘贴剪切板内的第一条内容,无需申请ohos.permission.READ_PASTEBOARD权限,如您使用的是三方框架,请在申请理由中描述并重新提交申请,感谢您的理解与支持!
其他权限
还有一些权限,在我看起来好像并不需要声明,但实际上你还是要在module.json5中声明一下,比如调用系统的打印服务:
bash
{
"name": "ohos.permission.PRINT",
"reason": "$string:request_print_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
不声明是无法使用的。关于权限具体可以参看:应用权限管控,文档说的很详细了,不赘述了。
Sqflite鸿蒙化
起初,我以为flutter_sqflite已经支持鸿蒙了,那理应问题不大,但是,当我尝试使用时,还是给我了一些小小的惊喜。
INTEGER变blob了?
用flutter_sqflite库建表时候,字段为INTEGER,理论上sqlite的INTEGER兼容long型。并且dart中 int也是兼容long。但是现在dart模型中int字段(比如:DateTime.now().millisecondsSinceEpoch),存入数据库,会被强制转成blob类型,然后查询上来的数据是unmodifiableUint8arrayview。
如何解决?
答:像时间戳这种比较大的数据类型字段要用UNLIMITED INT,不能用INTEGER ,例如:
sql
CREATE TABLE $_tableName(id INTEGER PRIMARY KEY, name TEXT, age INTEGER, create_t UNLIMITED INT)
不支持REAL
有一个字段的类型是REAL,在鸿蒙中是不支持的,因此,我又把其类型改成DOUBLE类型。结果我发现,我取出来的值全成成了整数,精度全部丢失了,我不太清楚是哪个环节出现了问题,是数据库本身的问题还是插件层的代码出现了问题,总之,精度确实丢了。评论区如果有知道原因的,可以告诉我。没办法,我又把其类型改成TEXT类型,用字符串存储,然后在dart层进入解析才算完事。
兼容性
我从flutter_sqflite中摘抄了部分文档,大家可以参考一下:
属性
!TIP\] "ohos Support"列为 yes 表示 ohos 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
存储类型
| Name | Description | Type | ohos Support |
|---|---|---|---|
| String | 存储字符串值 | String | yes |
| int | 存储整数值 | int | yes |
| real | 存储浮点数值 | double | no |
| bool | 存储布尔值 | bool | yes |
| null | 空 | null | yes |
| date_time | 储存时间值 | date_time | yes |
OpenDatabaseOptions
| Name | Description | Type | ohos Support |
|---|---|---|---|
| version | 数据库版本 | int? | yes |
| onConfigure | 数据库配置回调 | OnDatabaseConfigureFn? | yes |
| onCreate | 数据库首次创建回调 | OnDatabaseCreateFn? | yes |
| onUpgrade | 数据库版本升级回调 | OnDatabaseVersionChangeFn? | yes |
| onDowngrade | 数据库版本降级回调 | OnDatabaseVersionChangeFn? | yes |
| onOpen | 数据库成功打开回调 | OnDatabaseOpenFn? | yes |
| readOnly | 是否以只读模式打开数据库 | bool? | yes |
| singleInstance | 是否强制单例模式 | bool? | yes |
API
!TIP\] "ohos Support"列为 yes 表示 ohos 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
DatabaseFactory
| Name | return value | Description | Type | ohos Support |
|---|---|---|---|---|
| openDatabase(String path, {OpenDatabaseOptions? options}) | Future | 打开指定路径的数据库,可配置打开选项 | function | yes |
| getDatabasesPath | Future | 获取数据库默认存储路径 | function | yes |
| setDatabasesPath(String path) | Future | 设置默认数据库存储路径 | function | yes |
| deleteDatabase(String path) | Future | 删除指定路径的数据库 | function | yes |
| databaseExists(String path) | Future | 检查指定路径的数据库是否存在 | function | yes |
DatabaseExecutor
| Name | return value | Description | Type | ohos Support |
|---|---|---|---|---|
| execute(String sql, [List<Object?>? arguments]) | Future | 执行 SQL 语句 | function | yes |
| rawInsert(String sql, [List<Object?>? arguments]) | Future | 直接执行插入 SQL 返回行数 | function | yes |
| insert(String table, Map<String, Object?> values, {String? nullColumnHack,ConflictAlgorithm? conflictAlgorithm}) | Future | 插入 SQL 返回行数 | function | yes |
| query(String table, {bool? distinct, List? columns, String? where, List<Object?>? whereArgs, String? groupBy, String? having, String? orderBy, int? limit, int? offset}); | Future<List<Map<String, Object?>>> | 查询返回结果集列表 | function | yes |
| rawQuery(String sql, [List<Object?>? arguments]) | Future<List<Map<String, Object?>>> | 直接执行 SQL 查询返回结果集列表 | function | yes |
| rawQueryCursor(String sql, List<Object?>? arguments, {int? bufferSize}) | Future | 执行原始 SQL 查询返回游标对象 | function | yes |
| queryCursor(String table, {bool? distinct, List? columns, String? where, List<Object?>? whereArgs, String? groupBy, String? having, String? orderBy, int? limit, int? offset, int? bufferSize}) | Future | 查询返回游标对象 | function | yes |
| rawUpdate(String sql, [List<Object?>? arguments]) | Future | 直接执行更新 SQL 返回影响行数 | function | yes |
| update(String table, Map<String, Object?> values, {String? where, List<Object?>? whereArgs, ConflictAlgorithm? conflictAlgorithm}) | Future | 执行更新 SQL 返回影响行数 | function | yes |
| rawDelete(String sql, [List<Object?>? arguments]) | Future | 直接执行SQL删除符合条件的数据行 | function | yes |
| delete(String table, {String? where, List<Object?>? whereArgs}) | Future | 删除符合条件的数据行 | function | yes |
| batch | Batch | 获取批处理操作对象 | function | yes |
| get database | Database | 获取底层数据库实例 | function | yes |
Batch
| Name | return value | Description | Type | ohos Support |
|---|---|---|---|---|
| commit({ bool? exclusive, bool? noResult, bool? continueOnError, }) | Future<List<Object?>> | 提交批量操作 | function | yes |
| apply({bool? noResult, bool? continueOnError}) | Future<List<Object?>> | 执行批量操作并自动提交 | function | yes |
| rawInsert(String sql, [List<Object?>? arguments]) | void | 执行SQL插入语句 | function | yes |
| insert(String table, Map<String, Object?> values, {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) | void | 执行SQL插入语句 | function | yes |
| rawUpdate(String sql, [List<Object?>? arguments]) | void | 执行SQL更新语句 | function | yes |
| update(String table, Map<String, Object?> values, {String? where, List<Object?>? whereArgs, ConflictAlgorithm? conflictAlgorithm}) | void | 执行SQL更新语句 | function | yes |
| rawDelete(String sql, [List<Object?>? arguments]) | void | 执行SQL删除语句 | function | yes |
| delete(String table, {String? where, List<Object?>? whereArgs}) | void | 执行SQL删除语句 | function | yes |
| execute(String sql, [List<Object?>? arguments]) | void | 执行通用SQL语句 | function | yes |
| query(String table, {bool? distinct, List? columns, String? where, List<Object?>? whereArgs, String? groupBy, String? having, String? orderBy, int? limit, int? offset}) | void | 执行 SQL 查询语句 | function | yes |
| rawQuery(String sql, [List<Object?>? arguments]) | void | 执行 SQL 查询语句 | function | yes |
| get length | int | 获取累计操作数量 | function | yes |