juicycleff / flutter-unity-view-widget

Embeddable unity game engine view for Flutter. Advance demo here https://github.com/juicycleff/flutter-unity-arkit-demo
BSD 3-Clause "New" or "Revised" License
2.15k stars 524 forks source link

Unity app crashes in release mode on Android ARCore #269

Closed ljmatan closed 3 years ago

ljmatan commented 3 years ago

When I run "flutter build apk --split-per-abi" the release app always crashes, however it works most of the time when I run "flutter run --release" (although this results in an app 30mbs larger than it should be).

This is happening on Samsung Galaxy A8 2018 API 28 and Samsung Galaxy S10 API 29. I have debug keys set for release mode the same way package's (3.0.1) README describes.

Sometimes the app crashes before the Unity personal licence splash screen, sometimes during the splash screen, and also sometimes nothing is visible in the terminal on crash (I did however manage to get one output shown below).

E/AndroidRuntime(26783): FATAL EXCEPTION: UnityMain
E/AndroidRuntime(26783): Process: com.example.ar_unity, PID: 26783
E/AndroidRuntime(26783): java.lang.Error: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
E/AndroidRuntime(26783): Version '2019.3.3f1 (7ceaae5f7503)', Build type 'Release', Scripting Backend 'il2cpp', CPU 'arm64-v8a'
E/AndroidRuntime(26783): Build fingerprint: 'samsung/jackpotltexx/jackpotlte:9/PPR1.180610.011/A530FXXSECTJ1:user/release-keys'
E/AndroidRuntime(26783): Revision: '7'
E/AndroidRuntime(26783): ABI: 'arm64'
E/AndroidRuntime(26783): Timestamp: 2020-12-04 18:38:59+0100
E/AndroidRuntime(26783): pid: 26783, tid: 26871, name: UnityMain  >>> com.example.ar_unity <<<
E/AndroidRuntime(26783): uid: 10293
E/AndroidRuntime(26783): signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
E/AndroidRuntime(26783):     x0  0000000000000000  x1  00000000000068f7  x2  0000000000000006  x3  0000000000000008
E/AndroidRuntime(26783):     x4  20676e696c6c6143  x5  20676e696c6c6143  x6  20676e696c6c6143  x7  6f74736572507241
E/AndroidRuntime(26783):     x8  0000000000000083  x9  c4c25d0c5a469944  x10 0000000000000000  x11 fffffffc7ffffbdf
E/AndroidRuntime(26783):     x12 0000000000000001  x13 2e657a696c616974  x14 ffffffffffffffff  x15 00005791f7fef2fc
E/AndroidRuntime(26783):     x16 00000074625302a0  x17 000000746246f6c8  x18 00000000e843421b  x19 000000000000689f
E/AndroidRuntime(26783):     x20 00000000000068f7  x21 00000073ae5d1940  x22 000000736e495588  x23 00000073ae56c7e5
E/AndroidRuntime(26783):     x24 00000073ae56bbbf  x25 000000000000000f  x26 00000073b22c68a0  x27 0000000000000001
E/AndroidRuntime(26783):     x28 0000000000000000  x29 000000736e493200
E/AndroidRuntime(26783):     sp  000000736e4931c0  lr  0000007462462ecc  pc  0000007462462ef4
E/AndroidRuntime(26783): 
E/AndroidRuntime(26783): backtrace:
E/AndroidRuntime(26783):       #00 pc 0000000000021ef4  /system/lib64/libc.so (abort+116) (BuildId: 068840a6ea442b4f95dc3bd52b539682)
E/AndroidRuntime(26783):       #01 pc 000000000002d3a4  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 47a01dad660d236bd86133b8442a243d)
E/AndroidRuntime(26783):       #02 pc 000000000002d370  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 47a01dad660d236bd86133b8442a243d)
E/AndroidRuntime(26783):       #03 pc 000000000002d1a0  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 47a01dad660d236bd86133b8442a243d)
E/AndroidRuntime(26783):       #04 pc 000000000002cd38  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 47a01dad660d236bd86133b8442a243d)
E/AndroidRuntime(26783):       #05 pc 000000000002d5c0  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 47a01dad660d236bd86133b8442a243d)
E/AndroidRuntime(26783):       #06 pc 0000000000025e68  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (ArPresto_getStatus) (BuildId: 47a01dad660d236bd86133b8442a243d)
E/AndroidRuntime(26783):       #07 pc 0000000000023bdc  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (ArCoreUnity_getPose+48) (BuildId: 7784ab658fc7d1c39498e9b445ec7615)
E/AndroidRuntime(26783):       #08 pc 00000000005f8340  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #09 pc 00000000005f83f4  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #10 pc 000000000013f220  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #11 pc 0000000000f6ef18  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 83bd088edc784e84f8061eec845fc040c13057af)
E/AndroidRuntime(26783):       #12 pc 0000000000f6edc8  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 83bd088edc784e84f8061eec845fc040c13057af)
E/AndroidRuntime(26783):       #13 pc 0000000000f6f72c  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 83bd088edc784e84f8061eec845fc040c13057af)
E/AndroidRuntime(26783):       #14 pc 00000000004c9754  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 83bd088edc784e84f8061eec845fc040c13057af)
E/AndroidRuntime(26783):       #15 pc 0000000000573ba8  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: 83bd088edc784e84f8061eec845fc040c13057af)
E/AndroidRuntime(26783):       #16 pc 00000000002a5564  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #17 pc 00000000002b1ab8  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #18 pc 00000000002ba34c  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #19 pc 00000000001984fc  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #20 pc 000000000022495c  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #21 pc 0000000000224990  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #22 pc 0000000000224bc8  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #23 pc 0000000000319e2c  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #24 pc 000000000032cb24  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/base.apk (BuildId: fdab09abad973514e23ccfb803727b88834e7222)
E/AndroidRuntime(26783):       #25 pc 000000000000a0ac  /data/app/com.example.ar_unity-PjyThxlzjfMNX52MdqNFNg==/oat/arm64/base.odex
E/AndroidRuntime(26783): 
E/AndroidRuntime(26783):        at libc.abort(abort:116)
E/AndroidRuntime(26783):        at base.0x2d3a4(Native Method)
E/AndroidRuntime(26783):        at base.0x2d370(Native Method)
E/AndroidRuntime(26783):        at base.0x2d1a0(Native Method)
E/AndroidRuntime(26783):        at base.0x2cd38(Native Method)
E/AndroidRuntime(26783):        at base.0x2d5c0(Native Method)
E/AndroidRuntime(26783):        at base.ArPresto_getStatus(ArPresto_getStatus:0)
E/AndroidRuntime(26783):        at base.ArCoreUnity_getPose(ArCoreUnity_getPose:48)
E/AndroidRuntime(26783):        at base.0x5f8340(Native Method)
E/AndroidRuntime(26783):        at base.0x5f83f4(Native Method)
E/AndroidRuntime(26783):        at base.0x13f220(Native Method)
E/AndroidRuntime(26783):        at base.0xf6ef18(Native Method)
E/AndroidRuntime(26783):        at base.0xf6edc8(Native Method)
E/AndroidRuntime(26783):        at base.0xf6f72c(Native Method)
E/AndroidRuntime(26783):        at base.0x4c9754(Native Method)
E/AndroidRuntime(26783):        at base.0x573ba8(Native Method)
E/AndroidRuntime(26783):        at base.0x2a5564(Native Method)
E/AndroidRuntime(26783):        at base.0x2b1ab8(Native Method)
E/AndroidRuntime(26783):        at base.0x2ba34c(Native Method)
E/AndroidRuntime(26783):        at base.0x1984fc(Native Method)
E/AndroidRuntime(26783):        at base.0x22495c(Native Method)
E/AndroidRuntime(26783):        at base.0x224990(Native Method)
E/AndroidRuntime(26783):        at base.0x224bc8(Native Method)
E/AndroidRuntime(26783):        at base.0x319e2c(Native Method)
E/AndroidRuntime(26783):        at base.0x32cb24(Native Method)
E/AndroidRuntime(26783):        at base.0xa0ac(Native Method)

Code:

import 'package:flutter/material.dart';
import 'package:flutter_unity_widget/flutter_unity_widget.dart';
import 'dart:io' as io;
import 'bottom_bar/bottom_bar.dart';
import 'effects/front_camera_flash.dart';

class ARCore extends StatefulWidget {
  @override
  _ARCoreState createState() => _ARCoreState();
}

class _ARCoreState extends State<ARCore> {
  /// Required by the Unity plugin.
  UnityWidgetController _unityWidgetController;

  /// Provides access to BottomBar state.
  final GlobalKey<BottomBarState> _bottomBarKey = GlobalKey();

  /// Callback that connects the created controller to the unity controller,
  /// then displays the bottom button bar.
  ///
  /// Required by the Unity plugin.
  void _onUnityCreated(controller) {
    this._unityWidgetController = controller;
    _bottomBarKey.currentState.showBottomBar();
  }

  /// Communication from Flutter to Unity. Unity C# functions with one optional
  /// parameter are called using this function.
  void _callUnityFunction(String function, [String parameter = '']) =>
      _unityWidgetController.postMessage('ARCore Device', function, parameter);

  /// Latest file saved to persistentAppData.
  String _latestFile;

  /// Move file to gallery and delete data from persistentAppData.
  Future<void> _moveFile(String filePath) async {
    // Fallback
    if (_latestFile != filePath) {
      _latestFile = filePath;

      // File from persistentAppData folder
      final io.File sourceFile = io.File(filePath);

      // Android device gallery folder name
      final String galleryFolder = '/storage/emulated/0/DCIM/GoVirol/';

      // Final filename displayed in the gallery
      final String newFilename =
          DateTime.now().toIso8601String() + '.' + filePath.split('.').last;

      // Create gallery folder if it doesn't exist
      await io.Directory(galleryFolder).create();

      // Move file to the gallery folder
      await sourceFile.copy(galleryFolder + newFilename);

      // Delete the file from persistentAppData
      await sourceFile.delete();

      // Refresh Android gallery so the new file is visible
      _callUnityFunction('RefreshGallery', galleryFolder + newFilename);
    }
  }

  /// Communication from Unity to Flutter. A message object is passed from Unity
  /// using the UnityMessageManager.
  void _onUnityMessage(msg) {
    final String message = msg.toString();

    // If a file had been successfully saved into the persistentAppData folder
    if (message.contains('.jpg') ||
        message.contains('.gif') ||
        message.contains('.mp4')) _moveFile(message);
  }

  /// Model currently in the scene.
  String _currentModel;

  /// Display model into a current Unity scene.
  void _displayModel(String model) => _callUnityFunction('DisplayModel', model);

  /// Remove current model from the Unity scene.
  void _removeModel() => _callUnityFunction('RemoveModel', _currentModel);

  /// Change ARCore face filter. Updates the face texture, and removes and / or
  /// displays an overlaying 3D model.
  void _changeFilter(String textureName, [String model]) {
    // Changes texture displayed over the face mesh.
    _callUnityFunction('ChangeFilter', textureName);

    // If the model parameter had been set and there is no 3D model currently displayed
    if (model != null && _currentModel == null) {
      _currentModel = model;
      _displayModel(model);

      // If the model parameter had been set and a 3D model is currently displayed
    } else if (model != null && _currentModel != null) {
      _removeModel();
      _currentModel = model;
      _displayModel(model);

      // If the model parameter had not been set and a 3D model is currently displayed
    } else if (_currentModel != null && model == null) {
      _removeModel();
      _currentModel = null;
    }
  }

  /// Whether front camera view is active at the moment
  bool _frontCamera = true;

  /// Provides access to the front flash effect state.
  GlobalKey<FrontCameraFlashState> _flashKey = GlobalKey();

  /// Take a photo and store it into the persistantAppData folder.
  void _takePhoto() {
    if (_frontCamera) _flashKey.currentState.startFlash();
    _callUnityFunction('NewPhoto');
  }

  /// Change between front and back camera.
  void _changeCamera() {
    _callUnityFunction('ChangeCamera');
    _frontCamera = !_frontCamera;
  }

  /// Starts GIF recording.
  void _startGIFRecording() => _callUnityFunction('StartGIFRecording');

  /// Stops GIF recording and saves the data to the persistentAppData folder.
  void _stopGIFRecording() => _callUnityFunction('StopGIFRecording');

  /// Starts video recording.
  void _startVideoRecording() => _callUnityFunction('StartVideoRecording');

  /// Stops video recording and saves the data to the persistentAppData folder.
  void _stopVideoRecording() => _callUnityFunction('StopVideoRecording');

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Stack(
          children: [
            // Unity screen
            UnityWidget(
              isARScene: true,
              onUnityCreated: _onUnityCreated,
              onUnityMessage: _onUnityMessage,
            ),
            // Close button
            Positioned(
              right: 0,
              child: IconButton(
                icon: Icon(Icons.close, color: Colors.white),
                onPressed: () => Navigator.pop(context),
              ),
            ),
            // Bottom button bar
            BottomBar(
              key: _bottomBarKey,
              changeFilter: _changeFilter,
              takePhoto: _takePhoto,
              changeCamera: _changeCamera,
              startGIFRecording: _startGIFRecording,
              stopGIFRecording: _stopGIFRecording,
              startVideoRecording: _startVideoRecording,
              stopVideoRecording: _stopVideoRecording,
            ),
            // Flash effect
            FrontCameraFlash(key: _flashKey),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    // Stop recording if in progress
    _stopGIFRecording();
    _stopVideoRecording();

    // 00 is a transparent image texture, so this function effectively removes any filter
    _changeFilter('00');

    // Dispose resources
    _unityWidgetController.dispose();
    super.dispose();
  }
}

New issue created because of added details.

phobye commented 3 years ago

I have the same problem here. With different code, different unity project. I tried the app on OnePlus, Xiaomi, Nokia phones, but all of them crashed when I tried to run in in release mode. When it was in debug, or profile, it has no problem to run. As I see the problem only occurs, when I use ARFoundation. If just a simple Unity project is inculded, it runs without any crashes.

ljmatan commented 3 years ago

ARCore for me, not the whole ARFoundation

ljmatan commented 3 years ago

@juicycleff do you think you could be providing any help or pointers for this issue? If it's unrelated to your package could you point me in the right direction?

The following does not work:

Switching to 2019.4.x version Updating Google AR services on device - https://github.com/google-ar/arcore-android-sdk/issues/1021 Selecting only ARM64 in build options - https://forum.unity.com/threads/ar-app-crashing-on-my-phone-when-arsession-is-loaded-unity-2019.950843/

https://github.com/google-ar/arcore-unity-sdk/issues/771 for reference

juicycleff commented 3 years ago

I suggest using asset streaming in unity, reduce the size of your unity app. Should solve the size issue

ljmatan commented 3 years ago

Although I appreciate your response as well as the effort put into this project I feel that this is something to be noted in the readme. Thanks.

phobye commented 3 years ago

I've put these two lines in the unityLibrary/proguard-unity.txt :

-keep class com.unity3d.plugin.* { *; }
-keep class com.xraph.plugins.flutterunitywidget.UnityUtils { *; }

It solved my problem. I can now build a release version, and it runs perfectly. Don't forget, to put back these two lines after every unity build because it regenerates the proguard-unity.txt and it will miss them.

ljmatan commented 3 years ago

@phobye perfect! Much appreciated.