꿈꾸는 시스템 디자이너

Flutter 강좌 - File Picker나 Document Picker 플러그인이 동작하지 않을 때 해결 방법 | File Picker or Document Picker is not working 본문

Development/Flutter

Flutter 강좌 - File Picker나 Document Picker 플러그인이 동작하지 않을 때 해결 방법 | File Picker or Document Picker is not working

독행소년 2020. 6. 16. 15:52

 

Flutter Code Examples 강좌를 추천합니다.

  • 제 블로그에서 Flutter Code Examples 프로젝트를 시작합니다.
  • Flutter의 다양한 예제를 소스코드와 실행화면으로 제공합니다.
  • 또한 모든 예제는 Flutter Code Examples 앱을 통해 테스트 가능합니다.

Flutter Code Examples 강좌로 메뉴로 이동

Flutter Code Examples 강좌 목록 페이지로 이동

Flutter Code Examples 앱 설치 | Google Play Store로 이동

 

Flutter Code Examples - Google Play 앱

Are you a beginner at Flutter? Check out the various features of Flutter through the demo. Source code for all demos is also provided.

play.google.com


Flutter 강좌 시즌2 목록 : https://here4you.tistory.com/149

 

이번 시간은 강좌가 아닌 팁을 하나 소개한다.

 

최근 개발 중인 앱에서 File Picker가 필요해서 다음과 같은 플러그인들을 살펴보았다.

 

https://pub.dev/packages/file_picker

 

file_picker | Flutter Package

A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extension filtering support.

pub.dev

https://pub.dev/packages/flutter_document_picker

 

flutter_document_picker | Flutter Package

Allows user pick a document. Picked document is copied to app temporary directory. Optionally allows pick document with specific extension only.

pub.dev

 

문제는 별다른 오류 없이 빌드가 되고 설치까지 되는데, 장작 파일을 선택하면 앱이 비정상 종료되거나 파일의 경로값으로 null을 받는 문제가 있었다. 구글링을 해보니 꽤 많은 사람들이 정상 동작하지 않는다고 하고 있으나 나이스한 나이게 맞는 해결책은 없었다. 이 문제로 며칠을 고생했는데 결과적으로 원인은 따로 있었다.

 

처음 의심한 부분은 안드로이 플랫폼이 10으로 업그래이드 되면서 파일 시스템에 접근하는 방법이 변경되어 발생하는 것이라고 추측했었다. 이미 비스한 경험이 있었기 때문이나 아니었다.

https://here4you.tistory.com/244

 

Flutter 강좌 - [Tip] image_picker 플러그인을 이용해서 갤러리 이미지를 읽어오지 못할 때 해결 법 | Fai

Flutter Code Examples 강좌를 추천합니다. 제 블로그에서 Flutter Code Examples 프로젝트를 시작합니다. Flutter의 다양한 예제를 소스코드와 실행화면으로 제공합니다. 또한 모든 예제는 Flutter Code Examples..

here4you.tistory.com

그 외에 각종 퍼미션을 넣었다 뺐다 해봤었는데 이것으로도 해결되지 않았다.

 

그래서 플러그인 개발자의 Git Repository를 뒤져보기 시작했다. 결국 그 안에 답이 있었는데 너무 오래 멀리 돌아왔다.

 

결론부터 기술하자면, MainActivity의 configureFlutterEngine 메소드에서 플로그인을 등록하는 부분을 삭제하면 해결된다.

 

Android Studio를 이용해서 Flutter 프로젝트를 생성하면 다음과 같은 MainActivity 파일이 자동 생성된다. 그리고 configureFlutterEngine 메소드에서 생성된 플러그인을 플러터의 엔진에 등록하는 것으로 추측되는 코드가 실행된다. 정확한 구조는 본인도 잘 모른다.

package com.h4u.plugininstalltest;

import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
  @Override
  public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
    GeneratedPluginRegistrant.registerWith(flutterEngine);
  }
}

 

다음으로 io.flutter.plugins 디렉토리에 자동 생성된 GeneratedPluginRegistrant.java 파일을 확인해 보자.

package io.flutter.plugins;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.FlutterEngine;

/**
 * Generated file. Do not edit.
 * This file is generated by the Flutter tool based on the
 * plugins that support the Android platform.
 */
@Keep
public final class GeneratedPluginRegistrant {
  public static void registerWith(@NonNull FlutterEngine flutterEngine) {
  }
}

 

MainActivity의 configureFlutterEngine 메소드에서 수행된 내용과 동일한 기능을 수행하는 것으로 추측되는 코드가 자동 생성되어 있다. 아직 설치한 플러그인이 없으니 아무 내용이 없는 상태다.

 

앱을 개발하면서 플러그인인들을 설치하면 설치된 플러그인의 내용이 이 파일에 자동으로 구성되게 된다. 주석으로도 적혀있지 않는가? 안드로이드 플랫폼을 지원하는 플러그인들을 기반으로 해서 자동으로 생성된 파일이므로 수정하지 말라고....

 

실제로 플러그인들을 추가하다보면 다음과 같이 파일의 내용이 자동으로 수정된다.

package io.flutter.plugins;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;

import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry;

/**
 * Generated file. Do not edit.
 * This file is generated by the Flutter tool based on the
 * plugins that support the Android platform.
 */
@Keep
public final class GeneratedPluginRegistrant {
    public static void registerWith(@NonNull FlutterEngine flutterEngine) {
        ShimPluginRegistry shimPluginRegistry = new ShimPluginRegistry(flutterEngine);
        com.github.yasukotelin.ext_storage.ExtStoragePlugin.registerWith(shimPluginRegistry.registrarFor("com.github.yasukotelin.ext_storage.ExtStoragePlugin"));
        flutterEngine.getPlugins().add(new com.sidlatau.flutterdocumentpicker.FlutterDocumentPickerPlugin());
        io.github.ponnamkarthik.toast.fluttertoast.FluttertoastPlugin.registerWith(shimPluginRegistry.registrarFor("io.github.ponnamkarthik.toast.fluttertoast.FluttertoastPlugin"));
        de.pdad.getip.GetIpPlugin.registerWith(shimPluginRegistry.registrarFor("de.pdad.getip.GetIpPlugin"));
        flutterEngine.getPlugins().add(new io.flutter.plugins.packageinfo.PackageInfoPlugin());
        flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin());
        flutter.plugins.screen.screen.ScreenPlugin.registerWith(shimPluginRegistry.registrarFor("flutter.plugins.screen.screen.ScreenPlugin"));
    }
}

 

기존에는 이 부분(Android Java쪽 코드)은 신경쓰지 않았는데, 두 파일에서 플러그인이 플러터엔진에 두번 등록되면서 문제가 발생하는 것으로 추측된다.

아마도 일부 상태값을 가지는 플러그인의 경우 중복 등록에 의해 상태값을 일어버리면서 오류가 발생되는 것이 아닌가 싶다.

 

메인함수를 다음과 같이 중복호출되지 않도록 수정하면 플러그인이 정상 동작한다.

package com.h4u.plugininstalltest;

import androidx.annotation.NonNull;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
//    GeneratedPluginRegistrant.registerWith(flutterEngine);
    }
}

 

 

며칠을 고생했는데 허무하게 해결되었다.

 

Comments