본문 바로가기

Programming/Android

android 5.0 이상 웹뷰에서 파일 업로드 하기

반응형
웹페이지에서 사진이나 문서등 다양한 형식의 첨부파일을 업로드하는 기능이 구현 되어있는 곳이 많습니다.

하지만 android 웹뷰에서 첨부파일 업로드 기능은 추가 구현을 해주어야 동작을 합니다.

5.0 이전과 이후 버전에서 이 기능의 구현 방법은 다른데요.
오늘은 5.0 이상 버전에서 어떻게 구현 하는지 알아볼까 합니다.


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

manifest 파일에 권한을 추가 합니다.

    private ValueCallback<Uri[]> mFilePathCallback;

WebChromeClient webChromeClient = new WebChromeClient() {

// For Android Version 5.0+
public boolean onShowFileChooser(WebView webView,
ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (mFilePathCallback != null) {
mFilePathCallback.onReceiveValue(null);
}
mFilePathCallback = filePathCallback;
showImageChooser();
return true;
}

};
업로드를 위해서 앱에서 해주어야 할 일은 간단 합니다.
WebchromeClient를 통해 파일선택창이 호출 되면 파일 선택창을 띄어주고
선택한 파일의 uri를 onShowFileChooser의 인자값으로 받은 filePathCallback에 넣어 주면 됩니다.

이미지 선택창을 띄어 보겠습니다.

private void imageChooser() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
} catch (IOException ex) {
// Error occurred while creating the File
Log.e(getClass().getName(), "Unable to create Image File", ex);
}

// Continue only if the File was successfully created
if (photoFile != null) {
mCameraPhotoPath = "file:"+photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}

Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType(TYPE_IMAGE);

Intent[] intentArray;
if(takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}

Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Select");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);

startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
}
위 소스는 Intent를 활용하여 카메라 촬영혹은 디바이스내에서 이미지 가져오는 선택 창을 띄우는 소스입니다.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == INPUT_FILE_REQUEST_CODE && resultCode == RESULT_OK) {
if (mFilePathCallback == null) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
Uri[] results = new Uri[]{getResultUri(data)};

mFilePathCallback.onReceiveValue(results);
mFilePathCallback = null;

} else {
if (mFilePathCallback != null) mFilePathCallback.onReceiveValue(null);
mFilePathCallback = null;
super.onActivityResult(requestCode, resultCode, data);
}


}
선택되었거나 촬영된 이미지는 onActivityResult를 통해 들어온 파일 경로 값을 Uri배열에 담아 보내면 앱에서 파일업로드를 위해 해주어야 하는 작업은 끝입니다.

소스가 길어서 많은 작업이 필요 한 것 같지만 이미지 선택을 위해 호출하는 부분들을 제외 한다면 간단한 작업만으로 구현 가능하다고 생각 합니다.