Giter Site home page Giter Site logo

Comments (20)

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024 1

That will be WidgetsFlutterBinding.ensureInitialized(); instead of FlutterWidgetsBinding.ensureInitialized() right :D

from sqlite3.dart.

simolus3 avatar simolus3 commented on September 6, 2024

What the hell is Android doing here? 😧 But it's interesting to know that the object gets put there...

applyWorkaroundToOpenSqlCipherOnOldAndroidVersions function threw an error. (Null check operator used on a null value).

Are you using the function before runApp by any chance? It sounds like a missed initialization on the Flutter method channel, are you calling FlutterWidgetsBinding.ensureInitialized()? But even then it's weird that this only fails on some devices... Do you have a stack trace by any chance?

from sqlite3.dart.

ikbendewilliam avatar ikbendewilliam commented on September 6, 2024

I'm not sure... 🙈
Before we do anything, we do WidgetsFlutterBinding.ensureInitialized();, so the function is called after this, but before the runApp() (inside a preResolve).

  @singleton
  @preResolve
  Future<DatabaseConnection> provideDatabaseConnection(...) async {
    ...
    await Isolate.spawn(
      _startBackground, <--- This function calls the applyWorkaroundToOpenSqlCipherOnOldAndroidVersions
     ...
    );

The stacktrace is

E/flutter (10337): [ERROR:flutter/runtime/dart_isolate.cc(1137)] Unhandled exception:
E/flutter (10337): Null check operator used on a null value
E/flutter (10337): #0      MethodChannel.binaryMessenger package:flutter/…/services/platform_channel.dart:142
E/flutter (10337): #1      MethodChannel._invokeMethod package:flutter/…/services/platform_channel.dart:148
E/flutter (10337): #2      MethodChannel.invokeMethod package:flutter/…/services/platform_channel.dart:331
E/flutter (10337): #3      applyWorkaroundToOpenSqlCipherOnOldAndroidVersions package:sqlcipher_flutter_libs/sqlcipher_flutter_libs.dart:34
E/flutter (10337): #4      _startBackground package:our_package/di/injectable.dart:156
E/flutter (10337): #5      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:286:17)
E/flutter (10337): #6      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

The reason that this only fails on some devices is that the workaround only calls invokeMethod when the DynamicLibrary.open('libsqlcipher.so'); fails. And for most devices, opening the file is not an issue.

Future<void> applyWorkaroundToOpenSqlCipherOnOldAndroidVersions() async {
  if (!Platform.isAndroid) return;
  try {
    DynamicLibrary.open('libsqlcipher.so');
  } on ArgumentError {
    // Ok, the regular approach failed. Try to open sqlite3 in Java, which seems
    // to fix the problem.
    await _platform.invokeMethod('doesnt_matter');

    // Try again. If it still fails we're out of luck.
    DynamicLibrary.open('libsqlcipher.so');
  }
}

I'll try removing the preresolve next week, but this has quite a few implications in the app and will still result in using a workaround, which I don't really like 🤔 (not that my suggestion is fool-proof 😬)

from sqlite3.dart.

simolus3 avatar simolus3 commented on September 6, 2024

From the stack trace, it looks like you're opening the native library in a new isolate. That's completely fine, but it means that you also need to call FlutterWidgetsBinding.ensureInitialized() in _startBackground. Essentially, the binding (and the messenger) need to be initialized on each isolate separately.

If possible, an alternative would be to always open the library in the main isolate (even if it's not used there). Once opened correctly, the default path attempting to open libsqlcipher.so in a new isolate will work too.

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

I think it has something to do with aab files. I built the apk and installed it with adb. And everything works fine. If I download the app from the playstore. -> AAB -> the database doesn't work.

On a side note. We are also using obfuscation in dart & android. But again that works perfectly when building the aab files.

I am using a Nexus 5 (Phone) & Nexus 7 (Tablet). Both have this issue (reproducable when using the playstore)

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

@simolus3 We do have this in our build.gradle

release {
...
      ndk {
          abiFilters 'armeabi-v7a','arm64-v8a','x86_64', 'x86'
      }
...
}

Could that result in issues?

from sqlite3.dart.

simolus3 avatar simolus3 commented on September 6, 2024

The abiFilters should not be a problem (but are you sure that you're actually doing a Flutter release build on 32-bit x86? That would require some hacks).

App bundles changing the location of the actual library could explain this. Anyway, did you try using applyWorkaroundToOpenSqlCipherOnOldAndroidVersions with FlutterWidgetsBinding.ensureInitialized() in the background isolate? AFAIK that should also fix the problem.

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

I am building to the playstore internal test because that is the only place where I can reproduce this issue. The FlutterWidgetsBinding.ensureInitialized() should be the first thing we do in the _startBackground right? I did not see this in your isolate/encryption guide.

from sqlite3.dart.

simolus3 avatar simolus3 commented on September 6, 2024

Yes, calling ensureInitialized before applyWorkaroundToOpenSqlCipherOnOldAndroidVersions is necessary for each isolate. So doing that as a first call in _startBackground can't hurt :D

I think there were some general issues with using platform channels in background isolates, but AFAIK most of them have been resolved.

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

WidgetsFlutterBinding.ensureInitialized(); does not work. The app get stuck at startup. (When creating the dependency tree, I will try this in debug to get a stacktrace but in release (playstore I do not get a stacktrace)

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

This is the error I got (After deobfuscation)

10-25 17:32:20.629 11211-11300/? E/flutter: [ERROR:flutter/runtime/dart_isolate.cc(1137)] Unhandled exception:
    LateInitializationError: Field '_tbc@15065589' has not been initialized.
    Warning: This VM has been configured to produce stack traces that violate the Dart standard.
    *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    pid: 11211, tid: 11300, name DartWorker
    build_id: '4ff9bfa0daa533efd010fb425f5e2abb'
    isolate_dso_base: 9f5ae000, vm_dso_base: 9f5ae000
    isolate_instructions: 9f5ba000, vm_instructions: 9f5b0000
    #0      PlatformDispatcher.initialLifecycleState (dart:ui/platform_dispatcher.dart)
    #1      SingletonFlutterWindow.initialLifecycleState (dart:ui/window.dart:399:58)
    #2      ServicesBinding.readInitialLifecycleStateFromNativeWindow (package:flutter/src/services/binding.dart:185:71)
    #3      ServicesBinding.initInstances (package:flutter/src/services/binding.dart:35:5)
    #4      PaintingBinding.initInstances (package:flutter/src/painting/binding.dart:22:11)
    #5      SemanticsBinding.initInstances (package:flutter/src/semantics/binding.dart:22:11)
    #6      RendererBinding.initInstances (package:flutter/src/rendering/binding.dart:28:11)
    #7      WidgetsBinding.initInstances (package:flutter/src/widgets/binding.dart:277:11)
    #8      new BindingBase (package:flutter/src/foundation/binding.dart:56:5)
    #9      new _WidgetsFlutterBinding&BindingBase&GestureBinding (package:flutter/src/widgets/binding.dart)
    #10     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding (package:flutter/src/widgets/binding.dart)
    #11     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding (package:flutter/src/widgets/binding.dart)
    #12     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding&SemanticsBinding (package:flutter/src/widgets/binding.dart)
    #13     new Completer (dart:async/future.dart)
    #14     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding (package:flutter/src/widgets/binding.dart:704:48)
    #15     WidgetsFlutterBinding.ensureInitialized (package:flutter/src/widgets/binding.dart)
    #16     _startBackground (package:our_app/di/injectable.dart:153:25)
    #17     _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:286:17)
    #18     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

late String _initialLifecycleState; is still null

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

It has something to do with the aab files. If I build with --split-apk it works perfectly. If I build an aab and upload that one to the playstore it is broken.

from sqlite3.dart.

simolus3 avatar simolus3 commented on September 6, 2024

That's unfortunate. Do you start a main UI isolate before starting the background isolate? If you have a chance to await applyWorkaroundToOpenSqlCipherOnOldAndroidVersions on the main isolate before starting the background isolate, it might work because the loaded libraries are shared across threads.

There's a bit more information on this workaround here: simolus3/drift#895 (comment)

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

I will try that tomorrow. I have been working on this today for more than 9 hours. I couldn't think straight anymore. 🤞🤞🤞

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

The applyWorkaroundToOpenSqlCipherOnOldAndroidVersions should be called in the _startBackground or before?

from sqlite3.dart.

simolus3 avatar simolus3 commented on September 6, 2024

Try calling it before. So in the main isolate before you do Isolate.spawn(_startBackground).

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

If we only call applyWorkaroundToOpenSqlCipherOnOldAndroidVersions before we start the new isolate it doesn't work.

We now call applyWorkaroundToOpenSqlCipherOnOldAndroidVersions before the start of the isolate. And in _startBackground be do this:

Future<void> _startBackground(_IsolateStartRequest request) async {
  if (Platform.isIOS) {
    open.overrideFor(OperatingSystem.iOS, () => DynamicLibrary.process());
  } else if (Platform.isAndroid) {
    await applyWorkaroundToOpenSqlCipherOnOldAndroidVersions();
    open.overrideFor(OperatingSystem.android, openCipherOnAndroid);
  }
  final executor = VmDatabase(File(request.targetPath), setup: (db) => db.execute("PRAGMA key = '${request.password}'"));
  final moorIsolate = MoorIsolate.inCurrent(() => DatabaseConnection.fromExecutor(executor));
  request.sendMoorIsolate.send(moorIsolate);
}

Because calling WidgetsFlutterBinding.ensureInitialized(); crashes as well. We don't do that in _startBackground

from sqlite3.dart.

ikbendewilliam avatar ikbendewilliam commented on September 6, 2024

That fixed it and a new release is in the make. Thank you for your support!

from sqlite3.dart.

vanlooverenkoen avatar vanlooverenkoen commented on September 6, 2024

Yes indeed! Thanks again for your support. We do think that this step should be documented somewhere.
When to call applyWorkaroundToOpenSqlCipherOnOldAndroidVersions with isolate
And when to call applyWorkaroundToOpenSqlCipherOnOldAndroidVersions without isolate

from sqlite3.dart.

simolus3 avatar simolus3 commented on September 6, 2024

I have added matching warnings to the readme in f05f5d6.

from sqlite3.dart.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.