giandifra / arcore_flutter_plugin

Flutter plugin for ARCore SDK, Android platform to build new augmented reality experiences
MIT License
434 stars 281 forks source link

ArCoreController.addArCoreNodeToAugmentedImage cause "[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Null check operator used on a null value" #177

Open media-ch opened 2 years ago

media-ch commented 2 years ago

Hello. I have faced "Unhandled Exception: Null check operator used on a null value" on using addArCoreNodeToAugmentedImage.

As a tutorial, I copied the augmented_images.dart example to my flutter project. And I tried with my android device in debug mode.

Image detection seems to be succeeded, but an exception was caused and no reactions. Recording result as below.

E/native  ( 2393): E0000 00:00:1653966132.806819    2393 hit_test.cc:428] INTERNAL: No point hit.
E/native  ( 2393): E0000 00:00:1653966132.840047    2393 hit_test.cc:428] INTERNAL: No point hit.
I/flutter ( 2393): ======================
I/flutter ( 2393): ======================
I/flutter ( 2393): ======================
I/flutter ( 2393): =========DETECT=======
I/flutter ( 2393): ======================
I/flutter ( 2393): ======================
I/flutter ( 2393): ======================
E/flutter ( 2393): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Null check operator used on a null value
E/flutter ( 2393): #0      ArCoreController.addArCoreNodeToAugmentedImage (package:arcore_flutter_plugin/src/arcore_controller.dart:157:75)
E/flutter ( 2393): #1      _AppArBodyState._addSphere (package:practice/page/ar.dart:95:23)
E/flutter ( 2393): <asynchronous suspension>
E/flutter ( 2393): 
I/native  ( 2393): I0000 00:00:1653966134.911273   12131 motion_analysis_calculator.cc:645] Analyzed frame 224
I/native  ( 2393): I0000 00:00:1653966135.979843   12135 tracking.cc:3493] no history. confidence : 1.0
D/SmartClipDataCropperImpl( 2393): doExtractSmartClipData : Extraction start! reqId = 0  Cropped area = Rect(360, 780 - 361, 781)  Package = com.example.practice
D/SmartClipDataCropperImpl( 2393): addAppMetaTag : package name is com.example.practice
D/SmartClipDataCropperImpl( 2393): sendExtractionResultToSmartClipService : -- Extracted SmartClip data information --
D/SmartClipDataCropperImpl( 2393): sendExtractionResultToSmartClipService : Request Id : 0
D/SmartClipDataCropperImpl( 2393): sendExtractionResultToSmartClipService : Extraction mode : 1
D/SemSmartClipDataRepository( 2393): ----- Start of SmartClip repository informations -----
D/SemSmartClipDataRepository( 2393): ** Content type : image
D/SemSmartClipDataRepository( 2393): ** Meta area rect : Rect(0, 0 - 0, 0)
D/SemSmartClipDataRepository( 2393): ** Captured image file path : null
D/SemSmartClipDataRepository( 2393): ----- End of SmartClip repository informations -----
D/SmartClipDataCropperImpl( 2393): sendExtractionResultToSmartClipService : Elapsed = 29
I/native  ( 2393): I0000 00:00:1653966138.246802   12131 motion_analysis_calculator.cc:645] Analyzed frame 324
E/native  ( 2393): E0000 00:00:1653966138.973837    2393 hit_test.cc:428] INTERNAL: No point hit.
E/native  ( 2393): E0000 00:00:1653966139.008610    2393 hit_test.cc:428] INTERNAL: No point hit.

My code is here. (Almost copy)

import 'dart:developer';
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
import 'package:arcore_flutter_plugin/arcore_flutter_plugin.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:vector_math/vector_math_64.dart' as vector;

class AppArBody extends StatefulWidget {
  @override
  _AppArBodyState createState() => _AppArBodyState();
}

class _AppArBodyState extends State<AppArBody> {
  ArCoreController? arCoreController;
  Map<int, ArCoreAugmentedImage> augmentedImagesMap = Map();

  @override
  Widget build(BuildContext context) {
    return ArCoreView(
      onArCoreViewCreated: _onArCoreViewCreated,
      type: ArCoreViewType.AUGMENTEDIMAGES,
    );
  }

  void _onArCoreViewCreated(ArCoreController controller) async {
    loadSingleImage();
    arCoreController = controller;
    arCoreController?.onTrackingImage = _handleOnTrackingImage;
    //OR
    // loadImagesDatabase();
  }

  loadSingleImage() async {
    final ByteData bytes =
        await rootBundle.load('assets/earth_augmented_image.jpg');
    arCoreController?.loadSingleAugmentedImage(
        bytes: bytes.buffer.asUint8List());
  }

  loadImagesDatabase() async {
    final ByteData bytes = await rootBundle.load('assets/myimages.imgdb');
    arCoreController?.loadAugmentedImagesDatabase(
        bytes: bytes.buffer.asUint8List());
  }

  _handleOnTrackingImage(ArCoreAugmentedImage augmentedImage) {
    if (!augmentedImagesMap.containsKey(augmentedImage.index)) {
      augmentedImagesMap[augmentedImage.index] = augmentedImage;
      _addSphere(augmentedImage);
    }
  }

  Future _addSphere(ArCoreAugmentedImage augmentedImage) async {
    print("======================");
    print("======================");
    print("======================");
    print("=========DETECT=======");
    print("======================");
    print("======================");
    print("======================");

    final ByteData textureBytes = await rootBundle.load('assets/earth.jpg');

    final material = ArCoreMaterial(
      color: Color.fromARGB(120, 66, 134, 244),
      textureBytes: textureBytes.buffer.asUint8List(),
    );
    final sphere = ArCoreSphere(
      materials: [material],
      radius: augmentedImage.extentX / 2,
    );
    final node = ArCoreNode(
      shape: sphere,
    );

    arCoreController?.addArCoreNodeToAugmentedImage(node, augmentedImage.index);
  }

  @override
  void dispose() {
    arCoreController?.dispose();
    super.dispose();
  }
}

pubspec.yaml

name: practice
description: A new Flutter project.

version: 1.0.0+1

environment:
  sdk: ">=2.16.2 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  arcore_flutter_plugin: ^0.1.0-null-safety.3

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  assets:
    - assets/earth.jpg
    - assets/earth_augmented_image.jpg

I think this example result will show like this on my device. https://github.com/giandifra/arcore_flutter_plugin/issues/4#issuecomment-607263366

But display on my device with above my code is here.

Screenshot_20220531-120217

Is it probmlem of ArCoreController.addArCoreNodeToAugmentedImage or my coding?

media-ch commented 2 years ago

@bilel2104

I have just solved this problem. Flutter pub arcore_flutter_plugin 0.1.0-null-safety.3 seems not to contain this change.

The cause is null checke operator at package:arcore_flutter_plugin/src/arcore_controller.dart:157:75.

Repository's master branch contains that fix, but flutter pub does not contain. Easy solution is to install directly this packges to your flutter project directory without passing through flutter pub add.

  1. Download codes from master branch.
  2. Move the unziped folder under your_flutter_project/plugins/
  3. Write pubspec.yml as below.
dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.

  # ↓from flutter pub. comment out or remove.
  # arcore_flutter_plugin: ^0.1.0-null-safety.3

  # ↓read from your local.
  arcore_flutter_plugin:
     path: ./plugins/arcore_flutter_plugin-master/
  1. Run flutter packages get. The pakcage will be read from your local!

I hope the master branch's change is taken in flutter pub as soon as possible. If flutter pub updated, above solution is unnecessary and we just install new version.

cyrus1127 commented 1 year ago

@media-ch I encountered and faced the same issue several hours before try your solutions. However my project will build failed after followed the solution.

And I traced the error stack, I found the core issue is in this line

./arcore_flutter_plugin-0.1.0-null-safety.3/lib/src/arcore_controller.dart :: 157 final params = _addParentNodeNameToParams(node.toMap(), parentNodeName!);

The issue is the private function is requesting a nullable parentNodeName parameter. Unfortunately, the function still pasting a Null check '!'. At the same time , addArCoreNodeToAugmentedImage() have had accept the nullable parentNodeName input parameter.

In this situation, I make the code change as showing in below. Just do remove the Null check from parentNodeName , as unnecessary

final params = _addParentNodeNameToParams(node.toMap(), parentNodeName);

The script will pass smoothly after a quick fix.