objectbox / objectbox-dart

Flutter database for super-fast Dart object persistence
https://docs.objectbox.io/getting-started
Apache License 2.0
981 stars 119 forks source link

Forced to use getApplicationDocumentsDirectory() on Android? #259

Closed natgross closed 2 years ago

natgross commented 3 years ago

ObjectBox gives me a code 10199 when trying to use an external directory on Android like this:

static const String EZObjectBoxFolder = 'storage/emulated/0/EZData/ObjectBox/01';

Future verifyCreateStorageDirectory()  async {
  final dbDirectory = Directory(EZObjectBoxFolder);
  bool dbDirectoryExists = await dbDirectory.exists();
  if (!dbDirectoryExists) await dbDirectory.create(recursive: true); 
}

  @override
  void initState() {
    super.initState();
    initAsync();
  }

  Future<void> initAsync() async {
    await verifyCreateStorageDirectory();
    _store = Store(
      getObjectBoxModel(),
      directory: EZObjectBoxFolder,
    );
  }

I have the Android permissions for reading/writing the entire drive. In fact the above code correctly creates the directory, but OB doesn't want to use it! I do not want the data in the ApplicationDirectory because of three reasons. 1) I want the data browsable by any File Explorer, 2) All data in app dir is deleted by Android when uninstalling the app, and 3) I might have multiple apps accessing the same data (albeit not simultaneously).

I don't have this problem with any other Flutter db. And I have tried many. Hopefully this is not a bug, just need some 'trick' to get it going. tnx

Here is the console dump:


E/Box     (12726): Storage error "Operation not permitted" (code 1)
E/flutter (12726): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: ObjectBoxException: failed to create store: 10199 Could not open database environment; please check options and file system (1: Operation not permitted)
E/flutter (12726): #0      ObjectBoxNativeError.throwMapped
package:objectbox/…/bindings/helpers.dart:77
E/flutter (12726): #1      throwLatestNativeError
package:objectbox/…/bindings/helpers.dart:49
E/flutter (12726): #2      checkObxPtr
package:objectbox/…/bindings/helpers.dart:31
E/flutter (12726): #3      new Store
package:objectbox/…/native/store.dart:103
E/flutter (12726): #4      _HomePageState.initAsync
package:objectbox_tutorial/home_page.dart:40
E/flutter (12726): <asynchronous suspension>
E/flutter (12726):
vaind commented 3 years ago

Hmm, if your flutter app is able to write to the directory, I wonder what's different to the native code not being able to. Might be related to the macOS specific issue which is (almost certainly) caused by sandboxing #248 . I'll try to ask around about android and native writes permissions.

vaind commented 3 years ago

I've tried your code in the demo app on emulator and faced no issues - DB was created as expected. I had to use package permission_handler to request permissions at runtime, of course - it wasn't enough to update the android manifest.

natgross commented 3 years ago

Of course it's not enough to declare the required permissions in the manifest. But Android allows the user to 'manually' grant these permissions via the app's settings. As pointed out in the docs of... permission_handler! And I quote:

This plugin provides a cross-platform (iOS, Android) API to request permissions and check their status. You can also open the device's app settings so users can grant a permission.

But..but why argue over this? The fact is that this same app is writing (and reading of course) test files to the same folder!

But you tested it (with permission_handler) and it does work. So maybe the problem depends on Android version and/or virtual versus real device.

I tested it on a Lenovo tablet running Android 9.

vaind commented 3 years ago

Have you been able to verify the issue happens in your app in an emulator? If so, have you tried setting permissions from inside the app, using the permissions_handler?

natgross commented 2 years ago

Good news! Am happy to report that with ver 1.1.1 of OB, it now works ok on the same machine/android that it had previously failed. The code snippet of my original post in this thread now works, as-is. (I just realized today that ob had a newer version!)

From my perspective, you can close this issue.