---重要更新---
经过几个小时的实验,我发现了更多关于我认为发生了变化的事情。
由于我对 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 个用户生成的数据文件都丢失了😢
我已经尝试了以下所有方法,无论是单独还是一起,结果总是相同的:
请注意,两个 pubscpec.yaml 文件的差异显示唯一的区别是“version:”行(正如我所期望的)。
我的主要开发环境是 iMac,但我也在 MBP 15 上进行了全新安装,两个平台上的结果是相同的。
还有什么我可以尝试帮助找出可能导致此问题的原因吗?
谢谢
莱斯
我知道回复已经晚了,但也许对其他人有用。
我认为你最好根据平台管理目录。例如,在 iOS 中使用
getApplicationDocumentsDirectory()
,在 Android 中使用 getDownloadsDirectory()
。这里如果是android文件将保存到/storage/emulated/0/android/com.xxx.xxx/files/downloads/file.extension
。
示例代码是,
final appSupportDir = Platform.isAndroid
? await getDownloadsDirectory()
: await getApplicationDocumentsDirectory();
注意:请注意,卸载应用程序时,保存到此文件夹的文件可能会被删除。