Things take time

[Android] Webview의 파일 업로드(input type = 'file') 본문

Android(기능)

[Android] Webview의 파일 업로드(input type = 'file')

겸손할 겸 2018. 12. 6. 11:37

[파일 업로드]

 

기존 하이브리드앱에서는 각 위지윅에 달려있던 버튼을 커스터마이징해서 앨범열기, 카메라 찍기 뭐 이런식으로 바로 네이티브 함수를 호출했다. 그렇기 때문에 각 기능 마다 네이티브 함수를 호출하고, 끝나면 업로드함수까지 직접 호출하여 위지윅의 JS에서 해당 데이터를 받아 서버에 저장, 에디터에 Insert까지 수행했다.

 

그러나 지금 필요한건 이런 각 기능이 아니라 파일 탐색기를 열고, 해당 파일을 선택하면 업로드하는.. 포괄적인 기능으로 변경을 요청했다.

 

[로직]

 

예제로 간단히 해본결과, 오히려 기존에 사용하던 앨범, 카메라같이 귀찮음이 사라졌다. 특히 업로드 부분에서는 내가 JS함수를 호출할 필요 없이 완료되었어요! 라고 웹뷰에 알려주면 웹에서 자동적으로 알아서 해준다. 즉, 웹의 input type을 file로 했을 때 사용자는 해당 파일을 선택만하면 그 이후 작업은 Html에서 해야하는 것처럼, 이후 작업 자체가 앱에서 할 일이 없어졌다는 것이다.

    ValueCallback mFilePathCallback;

해당 클래스내 전역변수를 하나 선언한다. 이 변수는 웹뷰의 특정 함수를 override할 때 사용할 변수이다.

        webView.setWebChromeClient(new WebChromeClient(){
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
                mFilePathCallback = filePathCallback;

                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("image/*");

                startActivityForResult(intent, 0);
                return true;
            }
        });

웹뷰를 받아서 WebChromeClient를 상속받는다. 이 클래스는 Gps, Confirm, Alert 등의 작업이 웹에서 호출되었을 때 네이티브에서 어떻게 할 것인지에 대해 정의하는 클래스므로, 위의 onShowFileChooser만 사용하는 것이 아님이다.

 

간단히 보자면, input type = 'file'이 걸린 버튼을 클릭했을 때 호출되는 함수이다. 그래서 mFilePathCallback 변수가 여기서 직접 대입이 되고 intent를 통해 Content타입이면서 image타입인 것을 보여달라가 되는 것이다.

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        Log.e("resultCode:: ", String.valueOf(resultCode));
        if(requestCode == 0 && resultCode == Activity.RESULT_OK){
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mFilePathCallback.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
            }else{
                mFilePathCallback.onReceiveValue(new Uri[]{data.getData()});
            }
            mFilePathCallback = null;
        }else{
            mFilePathCallback.onReceiveValue(null);
        }
    }

간단한 소스코드. 이 방법대로 하게 되면, 기본적인 이미지 파일 선택 및 업로드가 가능하다.

 

 

[추가]

 

여기서 나는 파일 업로드 뿐 아니라 사진 촬영까지 같이 하고 싶다면, 카메라 찍는 권한부터 파일 생성까지 하고 그 이후에 onShowFileChooser에서 intent에 ImageCapture 인텐트를 넣으면 된다. 기회가 된다면, 추가할 예정이나 현재 필요없다고 하니까 뭐..