Android

WebView 기반 안드로이드 네이티브 앱 개발5 (file upload)

태인킴 2020. 5. 19. 21:48
반응형

WebView 기반 안드로이드 네이티브 앱 개발5
WebView 기반 안드로이드 네이티브 앱 개발5


webView를 이용해서 android 네이티브 앱 개발시에, webView 안에 html 안에 <input type="file">은 네이티브 쪽에서 아무 처리도 해주지 않으면, 아무런 반응도 일어나지 않습니다. 이것을 구현하는 방법을 소개 하겠습니다.

 

 

 

1. WebView 객체 만들기

먼저, WebView 객체를 만들어 줍니다.

WebView myWebView = (WebView) findViewById(R.id.webview);

 

 

2. onShowFileChooser 함수 구현

<input type="file"> 이것을 android 네이티브에서도 처리해 주기 위해서는 WebChromeClient.onShowFileChooser()Override 해주어야 합니다. 

public static final int IMAGE_SELECTOR_REQ = 1;
private ValueCallback mFilePathCallback;

myWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
                mFilePathCallback = filePathCallback;
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                
                //여러장의 사진을 선택하는 경우 필요 <input type="file" multiple>
                intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
                
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setType("image/*");

                startActivityForResult(Intent.createChooser(intent,"Select Picture"), IMAGE_SELECTOR_REQ);
                return true;
            }
        });

1. webChromeClient전체 화면 지원 사용 설정. WebView창을 만들거나 닫고 자바스크립트 대화상자사용자에게 전송하는 등 호스트 앱의 UI변경하기 위한 권한을 필요로 할 때도 호출 됩니다. 

2. mFilePathCallback은 추후 file의 uriwebView로 전달해 주기 위한 전역 변수 필요.

3. intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)은 <input type="file" multiple>의 경우 필요.

 

 

2. onActivityResult 함수 구현

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == IMAGE_SELECTOR_REQ) {
        if (resultCode == Activity.RESULT_OK) {
            if (data.getClipData() != null) {
                int count = data.getClipData().getItemCount();
                Uri[] uris = new Uri[count];
                for (int i = 0; i < count; i++)
                    uris[i] = data.getClipData().getItemAt(i).getUri();
                mFilePathCallback.onReceiveValue(uris);
            } else if (data.getData() != null) {
                mFilePathCallback.onReceiveValue(new Uri[]{data.getData()});
            }
        }
    }
}

1. <input type="file" multiple>의 경우 data.getClipData()file 정보를 확인 할수 있습니다.

2. <input type="file">의 경우 또는 1장의 image를 업로드 하는 경우에 data.getData()를 통해 file 정보를 확인 할수 있습니다.

3. mFilePathCallback.onReceiveValue()webViewfile uri 정보를 보낼수 있습니다.

 

 

전체 소스

 

public class TestActivity extends AppCompatActivity {
    ....

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myWebView = (WebView) findViewById(R.id.webview);
        myWebView.setWebChromeClient(new MyWebChromeClient());
        myWebView.loadUrl(SERVER_IP);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK){
            switch (requestCode) {
                case IMAGE_SELECTOR_REQ:
                    if (data.getClipData() != null) {
                        int count = data.getClipData().getItemCount();
                        Uri[] uris = new Uri[count];
                        for (int i = 0; i < count; i++)
                            uris[i] = data.getClipData().getItemAt(i).getUri();
                        mFilePathCallback.onReceiveValue(uris);
                    } else if (data.getData() != null) {
                        mFilePathCallback.onReceiveValue(new Uri[]{data.getData()});
                    }
                    break;
            }
        }
    }

    private class MyWebChromeClient extends WebChromeClient {
        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback,
                                         WebChromeClient.FileChooserParams fileChooserParams) {
            mFilePathCallback = filePathCallback;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");
            startActivityForResult(Intent.createChooser(intent,"Select Picture"), IMAGE_SELECTOR_REQ);
            return true;
        }
    }
}

 

 

갤러리앱 다중 선택 지원

네이티브앱에서 이미지 다중 선택을 위해서는, 사용자에게 갤러리앱 or 구글 포토앱 으로 연결 할수 있도록, 사용자에게 권할수 있습니다. 구글 포토앱 으로 연결 시, 이미지 다중 선택을 할수 있고, 갤러리앱 으로 연결 시, 이미지 다중 선택을 현재는 지원하지는 않습니다. 만약, 갤러리앱 에서도 이미지 다중 선택을 지원하게 하려면, 커스텀 갤러리앱따로 개발을 해야 합니다.  갤러리앱 or 구글 포토앱으로 연결 유도를 위해서는 onShowFileChooser 함수가 아래와 같이 변경되어야 합니다.

        @Override
        // 갤러리 다중 선택 갤러리앱 or 구글 포토 연결 선택으로 변경
        public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback,
                                         WebChromeClient.FileChooserParams fileChooserParams) {
            mFilePathCallback = filePathCallback;
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setType("image/*");
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
            startActivityForResult(Intent.createChooser(intent,"Select Picture"), IMAGE_SELECTOR_REQ);
            return true;
        }

 

 

▶WebView 기반 안드로이드 네이티브 앱 개발4 (스플래쉬 화면 기능)

 

WebView 기반 안드로이드 네이티브 앱 개발4(스플래쉬 화면)

WebView기반의 네이티브 앱 개발 할 때 WebView를 처음 띄울때 이미지가 많거나 리소스 용량이 크면 WebView에 로딩이 늦게 되는 경우가 있습니다. 이럴때 WebView가 모두 로딩 되기 전에 로딩 화면을 보

coding-food-court.tistory.com

▶WebView 기반 안드로이드 네이티브 앱 개발3 (뒤로가기 기능)

 

WebView 기반의 안드로이드 네이티브 앱 개발 3 (뒤로가기)

https://coding-food-court.tistory.com/41 WebView 기반의 안드로이드 네이티브 앱 개발 2 https://coding-food-court.tistory.com/39 WebView 기반의 안드로이드 네이티브 앱 개발 1 안드로이드의 WebView를 이..

coding-food-court.tistory.com

반응형