안드로이드에서 단순한 웹뷰만 띄웠을 경우 파일 업로드 버튼을 눌러도 아무런 반응이 없는 게 정상적인 반응이다.
예를 들어 아래와 같은 웹뷰에 대해 파일 선택을 누르면 원래는 아무것도 뜨지 않는다.
이를 해결하기 위해 여러 블로그를 뒤져 결국 파일 선택 창을 띄워 냈다.
기록을 남겨놓으면 좋을 것 같아 파트별로 구분해서 기록을 남긴다.
환경설정
먼저 아래와 같은 권한들을 AndroidManifest.xml 파일에 적어준다.
적어주는 위치는 <manifest ~ > 바로 아래에 적어준다.
<uses-permission android:name="android.permission.INTERNET"/>
<!--네트워크 상태 퍼미션-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 카메라 퍼미션 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CAMERA2" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<!-- 5.0 버전 파일업로드 퍼미션 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>
<!-- 외부 저장소 사용 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
또한 https 가 아닌 http url 을 지원하기 위해서는 application 에 android:usesCleartextTraffic="true" 를 설정해야 한다.
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.JavaWebview"
android:usesCleartextTraffic="true">
MainActivity설정
이제 MainActivity에서 설정해야 할 코드를 소개하겠다.
먼저 class 내부의 전역 변수로
public static final int IMAGE_SELECTOR_REQ = 1;
private ValueCallback mFilePathCallback;
위 두 개를 선언해주고,
onCreate 시점에 아래 코드를 적어준다.
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, 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;
}
});
또한 클래스 내부의 다른 곳에 override function 하나를 선언해준다.
@Override
protected 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()}));
}
}
}
}
(헷갈려 하는 분들을 위해 맨 아래에 전체 코드를 올려두겠다.)
결과
이제 파일 선택을 클릭하면
아래와 같은 파일 선택 창이 뜨고,
갤러리를 클릭하면,
맨 첫 번째 앨범 클릭
전체코드
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private WebView mWebView;
private WebSettings mWebSettings;
public static final int IMAGE_SELECTOR_REQ = 1;
private ValueCallback mFilePathCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 웹뷰 시작
mWebView = (WebView) findViewById(R.id.webview);
setmWebViewFileUploadPossible();
mWebView.setWebViewClient(new WebViewClient());
mWebSettings = mWebView.getSettings(); //각종 환경 설정 가능여부
mWebSettings.setJavaScriptEnabled(true); // 자바스크립트 허용여부
mWebSettings.setSupportMultipleWindows(false); // 윈도우 여러개 사용여부
mWebSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); // 컨텐츠사이즈 맞추기
mWebSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); // 캐시 허용 여부
mWebSettings.setUseWideViewPort(true); // wide viewport 사용 여부
mWebSettings.setSupportZoom(true); // Zoom사용여부
mWebSettings.setJavaScriptCanOpenWindowsAutomatically(false); // 자바스크립트가 window.open()사용할수있는지 여부
mWebSettings.setLoadWithOverviewMode(true); // 메타태그 허용 여부
mWebSettings.setBuiltInZoomControls(true); // 화면 확대 축소 허용 여부
mWebSettings.setDomStorageEnabled(true); // 로컬저장소 허용 여부
mWebView.loadUrl("http://192.168.0.105:8080/egovCourseList.do"); // 웹뷰 사이트 주소 및 시작
}
@Override
public void onBackPressed() {
if(mWebView.canGoBack()){
mWebView.goBack();
}else{
super.onBackPressed();
}
}
public void touchUpGoToDestinationButton() {
final Button button = (Button) findViewById(R.id.goToDestinationButton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mWebView.loadUrl("http://192.168.0.105:8080/egovCourseList.do");
}
});
}
protected void setmWebViewFileUploadPossible() {
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, 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;
}
});
}
@Override
protected 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()}));
}
}
}
}
}
최근댓글