티스토리 뷰

728x90
반응형

그랬습니다.


안드로이드 하이브리드앱 개발할때 웹뷰에 불려올 웹페이지에서 input type="file" 넣으면


그냥 업로드 기능이 될줄로 알고 있었습니다.



하지만 그게 아니였죠.



웹뷰를 활용하여 안드로이드 하이브리드앱을 개발할때 업로드 기능을 구현하기 위해서는


추가적인 코드가 필요합니다.


그렇지 않으면 input type="file" 입력컨트롤을 아무리 터치해도 파일선택창이 나타나지 않습니다.



        WebView wv = (WebView) findViewById(R.id.webview);
        wv.setWebChromeClient(new WebChromeClient() {
            // For Android < 3.0
            public void openFileChooser( ValueCallback<uri> uploadMsg) {
                Log.d("MainActivity", "3.0 <");
                openFileChooser(uploadMsg, "");
            }
            // For Android 3.0+
            public void openFileChooser( ValueCallback<uri> uploadMsg, String acceptType) {
                Log.d("MainActivity", "3.0+");
                filePathCallbackNormal = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("image/*");
                startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_NORMAL_REQ_CODE);
            }
            // For Android 4.1+
            public void openFileChooser(ValueCallback<uri> uploadMsg, String acceptType, String capture) {
                Log.d("MainActivity", "4.1+");
                openFileChooser(uploadMsg, acceptType);
            }

            // For Android 5.0+
            public boolean onShowFileChooser(
                    WebView webView, ValueCallback<uri[]> filePathCallback,
                    WebChromeClient.FileChooserParams fileChooserParams) {
                Log.d("MainActivity", "5.0+");
                if (filePathCallbackLollipop != null) {
                    filePathCallbackLollipop.onReceiveValue(null);
                    filePathCallbackLollipop = null;
                }
                filePathCallbackLollipop = filePathCallback;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                i.setType("image/*");
                startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_LOLLIPOP_REQ_CODE);

                return true;
            }
        });
        WebSettings set = wv.getSettings();
        set.setJavaScriptEnabled(true);
        wv.loadUrl("http://test.com/upload.php");



웹뷰에 필요한 코드는 이렇습니다.


각 OS버전별로 override 해야할 함수가 다릅니다.


안드로이드에 openFileChooser와 onShowFileChooser라는 숨겨진 함수가 있는거죠.


해당 메소드를 재정의하고 intent를 호출하여 파일을 선택할수 있도록 해야합니다.



    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == FILECHOOSER_NORMAL_REQ_CODE) {
            if (filePathCallbackNormal == null) return ;
            Uri result = (data == null || resultCode != RESULT_OK) ? null : data.getData();
            filePathCallbackNormal.onReceiveValue(result);
            filePathCallbackNormal = null;
        } else if (requestCode == FILECHOOSER_LOLLIPOP_REQ_CODE) {
            if (filePathCallbackLollipop == null) return ;
            filePathCallbackLollipop.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
            filePathCallbackLollipop = null;
        }
    }


onAcitivityResult 에서 선택한 파일을 input 컨트롤로 전달하기 위한 코드를 추가하면 끝납니다.


필요한 퍼미션은 internet만 있으면 되는데


5.0 미만 버전의 호환을 위해서 read_external_strage도 있어야 합니다.


그렇지 않으면 파일 선택후 업로드시 오류가 발생합니다.



<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />



참고하셔야할 것은


업로드한 파일이 mime 타입이 버전별로 차이가 있습니다.


안드로이드 4.x 버전에서는 첨부한 파일의 mime가 무조건 application/octet-stream 으로 전송되니


서버측에서 다시한번 파일 검증을 하셔야 합니다.




샘플 프로젝트는 AndroidOpenFileChooser 깃헙에 공개되어있으니 여기서 확인하셔도 됩니다.




이렇게 하이브리드앱에서 업로드 기능 구현을 마쳤나 했더니 아주아주 무시무시한 일이 남아있었습니다...


그건 바로 4.4.2버전에서만 유일하게 이 코드는 동작하지 않다는것이지요...


구글링을 열심히 해보니 4.4.2버전에서는 유일하게 filechooser를 열기 위한 내장메소드가 포함되어있지 않다고 하는군요... 털썩...


4.4.2 보다 높은 버전 대상으로 배포하는 앱인 경우에는 상관이 없겠으나


그렇지 않은 경우 4.4.2 버전에 대한 예외처리를 생각해주어야 합니다.


대표적인 4.4.2 기기가 무엇이 있냐면요...


바로 갤럭시노트2...


으악 갤럭시노트2!!! 없애버리겠다!!!



이에 대처하는 코드는 다음 포스팅으로 이어집니다...




728x90
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함