[flutter] InAppWebView file download (Android 버전) 에러 해결과정 [해결]
지금 notification 클릭하면 파일 안열리는데,,어디서 잘못된 것인지 찾아가기 위해 작업 과정을 기록해본다. 해결 !!!
Android integration
- 내가 작업하는 플러터 환경은 v2 embedding이어서 추가적으로 필요한 작업은 없었지만, 프로젝트가 플러터 v1.12 이전이라면, 해당 과정을 먼저 거쳐야 한다.
notification을 클릭함으로써 다운로드된 파일을 열기 위해서, AndroidManifest.xml 파일에 다음 코드를 추가해주어야 한다.
<provider
android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
android:authorities="${applicationId}.flutter_downloader.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
- 다운로드 파일을 external strage(어플이 permission을 가진 곳)에 저장해야 한다.
- 다운로드된 파일은 파일 확장자를 읽을 수 있는 어플이 있을 때만 열 수 있다.
Usage
- 패키지 import 한다. (flutter_downloader Installing)
import 'package:flutter_downloader/flutter_downloader.dart';
- 초기화하기
해당 plugin은 초기화가 필수이다.
//main함수 내에서 했다.
WidgetsFlutterBinding.ensureInitialized();
await FlutterDownloader.initialize(
debug: true // optional: set false to disable printing logs to console
);
- download task 만들기
// 나는 이 때, InAppWebView widget 내에서 실행했기 때문에,
// InAppWebView의 함수인 onDownloadStart를 통해 실행했다.
//공식 문서에 나와있는 코드
final taskId = await FlutterDownloader.enqueue(
url: 'your download link',
savedDir: 'the path of directory where you want to save downloaded files',
showNotification: true, // show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);
//실제 사용된 코드의 일부
InAppWebView (
...
onDownloadStart: (controller, url) async {
final taskId = await FlutterDownloader.enqueue(
url: url.toString(),
savedDir: // 이부분에서도 시간 많이 썼는데 뒤에서 마저 정리할 것임.,
showNotification: true, // show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
saveInPublicStorage: true, //이거 꼭꼭 있어야한다. 이거 없어서 파일 저장이 제대로 안되었다.
);
}
...
)
3-1. savedDir은 다운로드 된 파일이 저장되는 path를 나타내는 곳이다.
- 여기서 또 다른 package를 다운받고 import 해야한다. (path_provider Installing)
import 'package:path_provider/path_provider.dart';
- example (이 외에도 다양한 예시가 있다.)
Directory tempDir = await getTemporaryDirectory(); String tempPath = tempDir.path; Directory appDocDir = await getApplicationDocumentsDirectory(); String appDocPath = appDocDir.path;
이런식으로 path를 구하는 것이다.
나는 아래처럼 path를 설정해서, 3번 download task의 savedDir에 해당 path를 할당했다.var externalStorageDirPath; final directory = await getExternalStorageDirectory(); externalStorageDirPath = directory?.path;
(공식 문서에 보면 external storage에 저장을 해두어야 한다고 되어있는데,, 내가 여기서 잘못 해서 notification에서 파일이 안열리는 것 같다고 생각이 된다..)
- Update download progress
FlutterDownloader.registerCallback(callback); // callback is a top-level or static function
- UI는 main isolate으로 렌더링되지만, download event는 backgound isolate에서 발생한다. 2개의 iolate간에 통신을 처리해야한다. 아래가 해당 코드이다.
- 링크 에 있는 코드가 도움이 되었다. (해당 코드를 어디에 위치 시켜야하는지)
ReceivePort _port = ReceivePort();
@override
void initState() {
super.initState();
IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
_port.listen((dynamic data) {
String id = data[0];
DownloadTaskStatus status = data[1];
int progress = data[2];
setState((){ });
});
FlutterDownloader.registerCallback(downloadCallback);
}
@override
void dispose() {
IsolateNameServer.removePortNameMapping('downloader_send_port');
super.dispose();
}
@pragma('vm:entry-point')
static void downloadCallback(String id, DownloadTaskStatus status, int progress) {
final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port');
send.send([id, status, progress]);
}
@pragma('vm:entry-point') 는 반드시 callback 함수 위에 위치해야한다.
원인과 해결방법
- 다운로드 파일을 external strage(어플이 permission을 가진 곳)에 저장해야 한다.
- 다운로드된 파일은 파일 확장자를 읽을 수 있는 어플이 있을 때만 열 수 있다.
이 요소가 중요한것 같다.
Author And Source
이 문제에 관하여([flutter] InAppWebView file download (Android 버전) 에러 해결과정 [해결]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@like02_like0/flutter-InAppWebView-file-download-Android-버전-에러-해결과정저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)