Flutter getApplicationDocumentsDirectory() 在 Android 上无法按预期工作,但在 iOS/iPadOS 上正常工作

问题描述 投票:0回答:1

---重要更新---

经过几个小时的实验,我发现了更多关于我认为发生了变化的事情。

由于我对 Android 不太熟悉,我曾假设(现在看来是错误的)Android 的 Flutter 构建系统会像 iOS 一样对 pubspec.yaml 中的 Flutter 版本属性采取必要的操作,但似乎我是错了。

在过去的两年里,我发布了应用程序的版本,其中 Flutter 版本属性已从“1.0.0+1”变为“1.0.0+2”、“1.0.0+3”、“1.0.1+” 1',依此类推直到'1.1.4+9',一切都按我的预期进行。然而,直到现在我还没有意识到,当我从“1.0.0+3”更新到“1.0.1+1”时,Android 会检测到 INSTALL_FAILED_VERSION_DOWNGRADE,因为我的应用程序的 Flutter 版本的 versionCode -“1.0.1” +1' - 是 1,应用程序先前版本的 versionCode - '1.0.0+3' - 是 3,所以 Android 认为我正在尝试从版本 3 降级到版本 1。

您可以在我在原始问题中发布的输出中看到这一点,因为当我尝试从“1.1.4+9”升级到“1.1.5+1”时,您可以看到错误,因为 1 小于 9:

Error: ADB exited with exit code 1
Performing Streamed Install

adb: failed to install /Users/les/.../build/app/outputs/flutter-apk/app-debug.apk: Failure [INSTALL_FAILED_VERSION_DOWNGRADE: Package Verification Result]

据我所知,发生的变化是,直到最近“降级”并没有删除旧应用程序的用户数据,现在它确实删除了,但为什么会这样呢?

如果此更改不是错误并且被认为是更好的,这是否意味着 iOS 和 Android 目标的 Flutter 开发人员需要为每个平台拥有不同的版本属性,或者将我们的 Flutter 生成的 android/app/build.gradle 修改为从应用程序的 Flutter version 属性计算有用的 Android versionCode(这是我现在选择解决此问题的方法)。

如果我没有正确理解这里发生的事情,那么如果有人可以正确解释这一点,以便我可以采取正确的行动,我将非常感激。

非常感谢

莱斯。

---原来的问题---

对这篇长文表示歉意,但我在这里查看了所有其他 getApplicationDocumentsDirectory 问题,但它们似乎都没有涵盖我的问题,我希望有人可以帮助我尝试解决此问题。

我已经开发一个应用程序一年多了,到目前为止,该应用程序在其设备上存储用户生成的数据没有出现任何问题。但现在,当我尝试在 Android 上升级我的应用程序时,无法看到应用程序先前版本的任何数据,但在 iOS/iPadOS 上一切仍然正常工作!

我正在使用 MacOS Ventura (13.6)、VSCode (1.82.2) 和 Flutter 3.13.6,并且我在 VSCode 中有两个单独的窗口,一个用于我的应用程序的 v1.1.4+9,一个用于 v1.1.5+1(每个窗口)窗口位于不同的 git 存储库中)。

每个版本都有完全相同的 main.dart 文件,这是似乎导致我出现问题的代码:

Future<void> main() async {
    FlutterError.onError = (FlutterErrorDetails details) async {
        final exception = details.exception;
        final stackTrace = details.stack ?? StackTrace.empty;
        if (isInDebugMode) {
            FlutterError.dumpErrorToConsole(details);
        } else {
            Zone.current.handleUncaughtError(exception, stackTrace);
        }
    };
    runZonedGuarded<Future<void>>(() async {
    WidgetsFlutterBinding.ensureInitialized();
    var dir = await getApplicationDocumentsDirectory();
    await Hive.initFlutter(dir.path);
    // register Hive TypeAdapters for our enums...
    Hive.registerAdapter(RandomNumberTypeAdapter());
    Hive.registerAdapter(DamageTableOptionAdapter());
    Hive.registerAdapter(PilotRatingTypeAdapter());
    await openGameFiles();
    await initSettings();

我使用 Genymotion 或 Android studio 启动单个 Android 模拟器,然后使用 v1.1.4 启动调试会话,并在此处设置断点:

await Hive.initFlutter(dir.path);

这样我就可以查看 ApplicationDocumentsDirectory“dir”,并且可以在 VSCode 调试控制台中看到以下内容:

Launching lib/main.dart on Pixel 3 in debug mode...
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

✓  Built build/app/outputs/flutter-apk/app-debug.apk.
Connecting to VM Service at ws://127.0.0.1:54668/tAp30o9icjc=/ws


dir
_Directory (Directory: '/data/user/0/info.larsj.tft_01/app_flutter')
_path: "/data/user/0/info.larsj.tft_01/app_flutter"
_rawPath: Uint8List (43 items)
absolute: _Directory (Directory: '/data/user/0/info.larsj.tft_01/app_flutter')
hashCode: 925209278
isAbsolute: true
parent: _Directory (Directory: '/data/user/0/info.larsj.tft_01')
path: "/data/user/0/info.larsj.tft_01/app_flutter"
runtimeType: Type (_Directory)
uri: _Uri (file:///data/user/0/info.larsj.tft_01/app_flutter/)


dir.listSync()
List (22 items)
[0]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/mytftbox.lock')
[1]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/mytftbox.hive')
[2]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/cmpgn1.lock')
[3]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/citye.lock')
[4]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/cmpgn5.hive')
[5]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/cityi.lock')
[6]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/cmpgn3.hive')
[7]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/cmpgn6.lock')
[8]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/cmpgn2.hive')
[9]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/gamebox.lock')
[10]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/gamebox.hive')
[11]: _File
[12]: _Directory
[13]: _File
[14]: _File
[15]: _File
[16]: _File
[17]: _File
[18]: _File
[19]: _File
[20]: _File
[21]: _File

我现在停止 1.1.4 窗口中的调试会话,并使用相同的模拟器实例和相同的断点从 1.1.5 窗口启动调试会话,这就是我在调试控制台中看到的内容:

Launching lib/main.dart on Pixel 3 in debug mode...
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

✓  Built build/app/outputs/flutter-apk/app-debug.apk.
Uninstalling old version...
Error: ADB exited with exit code 1
Performing Streamed Install

adb: failed to install /Users/les/.../build/app/outputs/flutter-apk/app-debug.apk: Failure [INSTALL_FAILED_VERSION_DOWNGRADE: Package Verification Result]

Connecting to VM Service at ws://127.0.0.1:55046/Ki5K48e3ahk=/ws


dir
_Directory (Directory: '/data/user/0/info.larsj.tft_01/app_flutter')
_path: "/data/user/0/info.larsj.tft_01/app_flutter"
_rawPath: Uint8List (43 items)
absolute: _Directory (Directory: '/data/user/0/info.larsj.tft_01/app_flutter')
hashCode: 749014032
isAbsolute: true
parent: _Directory (Directory: '/data/user/0/info.larsj.tft_01')
path: "/data/user/0/info.larsj.tft_01/app_flutter"
runtimeType: Type (_Directory)
uri: _Uri (file:///data/user/0/info.larsj.tft_01/app_flutter/)


dir.listSync()
List (2 items)
[0]: _File (File: '/data/user/0/info.larsj.tft_01/app_flutter/res_timestamp-1-1696326308216')
[1]: _Directory (Directory: '/data/user/0/info.larsj.tft_01/app_flutter/flutter_assets')

因此从 1.1.4 开始所有 20 个用户生成的数据文件都丢失了😢

我已经尝试了以下所有方法,无论是单独还是一起,结果总是相同的:

  • 清理两个项目
  • 删除 android 文件夹,然后使用 flutter create 重新创建它们
  • flutter pub 升级--主要版本

请注意,两个 pubscpec.yaml 文件的差异显示唯一的区别是“version:”行(正如我所期望的)。

我的主要开发环境是 iMac,但我也在 MBP 15 上进行了全新安装,两个平台上的结果是相同的。

还有什么我可以尝试帮助找出可能导致此问题的原因吗?

谢谢

莱斯

android flutter dart android-emulator
1个回答
0
投票

我知道回复已经晚了,但也许对其他人有用。

我认为你最好根据平台管理目录。例如,在 iOS 中使用

getApplicationDocumentsDirectory()
,在 Android 中使用
getDownloadsDirectory()
。这里如果是android文件将保存到
/storage/emulated/0/android/com.xxx.xxx/files/downloads/file.extension

示例代码是,

final appSupportDir = Platform.isAndroid
    ? await getDownloadsDirectory()
    : await getApplicationDocumentsDirectory();

注意:请注意,卸载应用程序时,保存到此文件夹的文件可能会被删除。

© www.soinside.com 2019 - 2024. All rights reserved.