WebView에서 파일 업로드
지난 며칠 이후 WebView에서 파일을 업로드하는 데 어려움을 겪고 있으며 진행 상황이 없습니다. 내가 봤와 같은 모든 제안 된 솔루션을하지만 전혀 작동 구현 : 솔루션 제안 여기 , 등등을.
문제 : 파일을 업로드 할 다음 코드가있는 HTML 페이지가 있습니다. Firefox와 같은 데스크탑 브라우저 및 에뮬레이터 / AVD의 내장 브라우저에서 제대로 작동합니다. 즉, 요소별로 렌더링 된 "찾아보기 ..."버튼을 클릭하면 브라우저가 업로드 할 파일을 선택할 수있는 대화 상자를 엽니 다.
그러나 안드로이드 3.0 에뮬레이터 / AVD에서 "파일 선택"을 클릭해도 아무 일도 일어나지 않으며 파일 대화 상자가 열리지 않습니다!
<form method="POST" enctype="multipart/form-data">
File to upload: <input type="file" name="uploadfile">
<input type="submit" value="Press to Upload..."> to upload the file!
</form>
가능한 한 빨리 가능한 해결책을 제안 할 수 있습니까?
이것은 모든 안드로이드 버전에 대한 완벽한 솔루션이며, 이것으로 어려움을 겪었습니다.
public class MyWb extends Activity {
/** Called when the activity is first created. */
WebView web;
ProgressBar progressBar;
private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE=1;
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
if(requestCode==FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage) return;
Uri result = intent == null || resultCode != RESULT_OK ? null
: intent.getData();
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
web = (WebView) findViewById(R.id.webview01);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
web = new WebView(this);
web.getSettings().setJavaScriptEnabled(true);
web.loadUrl("http://www.script-tutorials.com/demos/199/index.html");
web.setWebViewClient(new myWebClient());
web.setWebChromeClient(new WebChromeClient()
{
//The undocumented magic method override
//Eclipse will swear at you if you try to put @Override here
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
MyWb.this.startActivityForResult(Intent.createChooser(i,"File Chooser"), FILECHOOSER_RESULTCODE);
}
// For Android 3.0+
public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MyWb.this.startActivityForResult(
Intent.createChooser(i, "File Browser"),
FILECHOOSER_RESULTCODE);
}
//For Android 4.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
MyWb.this.startActivityForResult( Intent.createChooser( i, "File Chooser" ), MyWb.FILECHOOSER_RESULTCODE );
}
});
setContentView(web);
}
public class myWebClient extends WebViewClient
{
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.setVisibility(View.GONE);
}
}
//flipscreen not loading again
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
// To handle "Back" key press event for WebView to go back to previous screen.
/*@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) {
web.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}*/
}
또한이 예제의 것과 같은 "업로드 페이지"는 이미지 미리보기 기능이 있기 때문에 <4 버전에서는 작동하지 않습니다. 미리보기없이 간단한 PHP 업로드를 사용하려면 작업하십시오.
업데이트 :
롤리팝 장치에 대한 솔루션을 찾아주세요 여기에 와 주셔서 감사합니다 gauntface을
업데이트 2 :
여기에 오레오 까지 모든 안드로이드 장치에 대한 완벽한 솔루션 이 있으며 이것은 고급 버전 입니다. 어쩌면 도움이 될 수 있습니다.
HONEYCOMB (API 11)에서 Oreo (API 27) 로의 작업 방법
[파이 9.0에서 테스트되지 않음]
static WebView mWebView;
private ValueCallback<Uri> mUploadMessage;
public ValueCallback<Uri[]> uploadMessage;
public static final int REQUEST_SELECT_FILE = 100;
private final static int FILECHOOSER_RESULTCODE = 1;
수정 onActivityResult()
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
if (requestCode == REQUEST_SELECT_FILE)
{
if (uploadMessage == null)
return;
uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
uploadMessage = null;
}
}
else if (requestCode == FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage)
return;
// Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
// Use RESULT_OK only if you're implementing WebView inside an Activity
Uri result = intent == null || resultCode != MainActivity.RESULT_OK ? null : intent.getData();
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
else
Toast.makeText(getActivity().getApplicationContext(), "Failed to Upload Image", Toast.LENGTH_LONG).show();
}
지금에 onCreate()
또는 onCreateView()
다음 코드를 붙여 넣습니다
WebSettings mWebSettings = mWebView.getSettings();
mWebSettings.setJavaScriptEnabled(true);
mWebSettings.setSupportZoom(false);
mWebSettings.setAllowFileAccess(true);
mWebSettings.setAllowFileAccess(true);
mWebSettings.setAllowContentAccess(true);
mWebView.setWebChromeClient(new WebChromeClient()
{
// For 3.0+ Devices (Start)
// onActivityResult attached before constructor
protected void openFileChooser(ValueCallback uploadMsg, String acceptType)
{
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
}
// For Lollipop 5.0+ Devices
public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
{
if (uploadMessage != null) {
uploadMessage.onReceiveValue(null);
uploadMessage = null;
}
uploadMessage = filePathCallback;
Intent intent = fileChooserParams.createIntent();
try
{
startActivityForResult(intent, REQUEST_SELECT_FILE);
} catch (ActivityNotFoundException e)
{
uploadMessage = null;
Toast.makeText(getActivity().getApplicationContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show();
return false;
}
return true;
}
//For Android 4.1 only
protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
{
mUploadMessage = uploadMsg;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
}
protected void openFileChooser(ValueCallback<Uri> uploadMsg)
{
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
}
});
이것이 내가 찾은 유일한 해결책입니다!
WebView webview;
private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE = 1;
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == mUploadMessage)
return;
Uri result = intent == null || resultCode != RESULT_OK ? null
: intent.getData();
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
// Next part
class MyWebChromeClient extends WebChromeClient {
// The undocumented magic method override
// Eclipse will swear at you if you try to put @Override here
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
Cv5appActivity.this.startActivityForResult(
Intent.createChooser(i, "Image Browser"),
FILECHOOSER_RESULTCODE);
}
}
5.0 Lollipop에서 Google은 공식적인 방법 인 WebChromeClient.onShowFileChooser를 추가했습니다 . 입력 선택 마임 유형을 사용하도록 파일 선택기 의도를 자동으로 생성하는 방법도 제공합니다.
public class MyWebChromeClient extends WebChromeClient {
// reference to activity instance. May be unnecessary if your web chrome client is member class.
private MyActivity activity;
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
// make sure there is no existing message
if (myActivity.uploadMessage != null) {
myActivity.uploadMessage.onReceiveValue(null);
myActivity.uploadMessage = null;
}
myActivity.uploadMessage = filePathCallback;
Intent intent = fileChooserParams.createIntent();
try {
myActivity.startActivityForResult(intent, MyActivity.REQUEST_SELECT_FILE);
} catch (ActivityNotFoundException e) {
myActivity.uploadMessage = null;
Toast.makeText(myActivity, "Cannot open file chooser", Toast.LENGTH_LONG).show();
return false;
}
return true;
}
}
public class MyActivity extends ... {
public static final int REQUEST_SELECT_FILE = 100;
public ValueCallback<Uri[]> uploadMessage;
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == REQUEST_SELECT_FILE) {
if (uploadMessage == null) return;
uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
uploadMessage = null;
}
}
}
}
KitKat 이전의 Android 버전의 경우 다른 답변에 언급 된 개인용 메소드가 작동합니다. KitKat (4.4)에 대한 좋은 해결 방법을 찾지 못했습니다.
다양한 버전의 안드로이드를 처리하기 위해 3 개의 인터페이스 정의가 필요하다는 것을 알았습니다.
public void openFileChooser(ValueCallback < Uri > uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
FreeHealthTrack.this.startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILECHOOSER_RESULTCODE);
}
public void openFileChooser(ValueCallback < Uri > uploadMsg, String acceptType) {
openFileChooser(uploadMsg);
}
public void openFileChooser(ValueCallback < Uri > uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg);
}
이 솔루션은 Honeycomb 및 Ice Cream Sandwich에도 적용됩니다. Google이 멋진 새로운 기능 (속성 허용)을 도입하고 이전 버전과의 호환성을 위해 과부하를 구현하지 않은 것 같습니다.
protected class CustomWebChromeClient extends WebChromeClient
{
// For Android 3.0+
public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType )
{
context.mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
context.startActivityForResult( Intent.createChooser( i, "File Chooser" ), MainActivity.FILECHOOSER_RESULTCODE );
}
// For Android < 3.0
public void openFileChooser( ValueCallback<Uri> uploadMsg )
{
openFileChooser( uploadMsg, "" );
}
}
hifarrer의 전체 솔루션은 저에게 매우 도움이됩니다.
그러나 다른 많은 MIME 유형 지원, 캡처 장치 (카메라, 비디오, 오디오 레코더) 나열, 캡처 장치 열기 (예 : <input accept = "image / *; capture">) ...
그래서 기본 웹 브라우저 앱과 똑같이 작동하는 솔루션을 만들었습니다.
android-4.4.3_r1 / src / com / android / browser / UploadHandler.java를 사용했습니다. (Rupert Rawnsley에게 감사드립니다)
package org.mospi.agatenativewebview;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebSettings.PluginState;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.webView1);
initWebView(webView);
webView.loadUrl("http://google.com"); // TODO input your url
}
private final static Object methodInvoke(Object obj, String method, Class<?>[] parameterTypes, Object[] args) {
try {
Method m = obj.getClass().getMethod(method, new Class[] { boolean.class });
m.invoke(obj, args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void initWebView(WebView webView) {
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccess(true);
settings.setDomStorageEnabled(true);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
settings.setLoadWithOverviewMode(true);
settings.setUseWideViewPort(true);
settings.setSupportZoom(true);
// settings.setPluginsEnabled(true);
methodInvoke(settings, "setPluginsEnabled", new Class[] { boolean.class }, new Object[] { true });
// settings.setPluginState(PluginState.ON);
methodInvoke(settings, "setPluginState", new Class[] { PluginState.class }, new Object[] { PluginState.ON });
// settings.setPluginsEnabled(true);
methodInvoke(settings, "setPluginsEnabled", new Class[] { boolean.class }, new Object[] { true });
// settings.setAllowUniversalAccessFromFileURLs(true);
methodInvoke(settings, "setAllowUniversalAccessFromFileURLs", new Class[] { boolean.class }, new Object[] { true });
// settings.setAllowFileAccessFromFileURLs(true);
methodInvoke(settings, "setAllowFileAccessFromFileURLs", new Class[] { boolean.class }, new Object[] { true });
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.clearHistory();
webView.clearFormData();
webView.clearCache(true);
webView.setWebChromeClient(new MyWebChromeClient());
// webView.setDownloadListener(downloadListener);
}
UploadHandler mUploadHandler;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == Controller.FILE_SELECTED) {
// Chose a file from the file picker.
if (mUploadHandler != null) {
mUploadHandler.onResult(resultCode, intent);
}
}
super.onActivityResult(requestCode, resultCode, intent);
}
class MyWebChromeClient extends WebChromeClient {
public MyWebChromeClient() {
}
private String getTitleFromUrl(String url) {
String title = url;
try {
URL urlObj = new URL(url);
String host = urlObj.getHost();
if (host != null && !host.isEmpty()) {
return urlObj.getProtocol() + "://" + host;
}
if (url.startsWith("file:")) {
String fileName = urlObj.getFile();
if (fileName != null && !fileName.isEmpty()) {
return fileName;
}
}
} catch (Exception e) {
// ignore
}
return title;
}
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
String newTitle = getTitleFromUrl(url);
new AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
}).setCancelable(false).create().show();
return true;
// return super.onJsAlert(view, url, message, result);
}
@Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
String newTitle = getTitleFromUrl(url);
new AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
}).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
}).setCancelable(false).create().show();
return true;
// return super.onJsConfirm(view, url, message, result);
}
// Android 2.x
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(uploadMsg, "");
}
// Android 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
openFileChooser(uploadMsg, "", "filesystem");
}
// Android 4.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
mUploadHandler = new UploadHandler(new Controller());
mUploadHandler.openFileChooser(uploadMsg, acceptType, capture);
}
// Android 4.4, 4.4.1, 4.4.2
// openFileChooser function is not called on Android 4.4, 4.4.1, 4.4.2,
// you may use your own java script interface or other hybrid framework.
// Android 5.0.1
public boolean onShowFileChooser(
WebView webView, ValueCallback<Uri[]> filePathCallback,
FileChooserParams fileChooserParams) {
String acceptTypes[] = fileChooserParams.getAcceptTypes();
String acceptType = "";
for (int i = 0; i < acceptTypes.length; ++ i) {
if (acceptTypes[i] != null && acceptTypes[i].length() != 0)
acceptType += acceptTypes[i] + ";";
}
if (acceptType.length() == 0)
acceptType = "*/*";
final ValueCallback<Uri[]> finalFilePathCallback = filePathCallback;
ValueCallback<Uri> vc = new ValueCallback<Uri>() {
@Override
public void onReceiveValue(Uri value) {
Uri[] result;
if (value != null)
result = new Uri[]{value};
else
result = null;
finalFilePathCallback.onReceiveValue(result);
}
};
openFileChooser(vc, acceptType, "filesystem");
return true;
}
};
class Controller {
final static int FILE_SELECTED = 4;
Activity getActivity() {
return MainActivity.this;
}
}
// copied from android-4.4.3_r1/src/com/android/browser/UploadHandler.java
//////////////////////////////////////////////////////////////////////
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// package com.android.browser;
//
// import android.app.Activity;
// import android.content.ActivityNotFoundException;
// import android.content.Intent;
// import android.net.Uri;
// import android.os.Environment;
// import android.provider.MediaStore;
// import android.webkit.ValueCallback;
// import android.widget.Toast;
//
// import java.io.File;
// import java.util.Vector;
//
// /**
// * Handle the file upload callbacks from WebView here
// */
// public class UploadHandler {
class UploadHandler {
/*
* The Object used to inform the WebView of the file to upload.
*/
private ValueCallback<Uri> mUploadMessage;
private String mCameraFilePath;
private boolean mHandled;
private boolean mCaughtActivityNotFoundException;
private Controller mController;
public UploadHandler(Controller controller) {
mController = controller;
}
String getFilePath() {
return mCameraFilePath;
}
boolean handled() {
return mHandled;
}
void onResult(int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_CANCELED && mCaughtActivityNotFoundException) {
// Couldn't resolve an activity, we are going to try again so skip
// this result.
mCaughtActivityNotFoundException = false;
return;
}
Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
: intent.getData();
// As we ask the camera to save the result of the user taking
// a picture, the camera application does not return anything other
// than RESULT_OK. So we need to check whether the file we expected
// was written to disk in the in the case that we
// did not get an intent returned but did get a RESULT_OK. If it was,
// we assume that this result has came back from the camera.
if (result == null && intent == null && resultCode == Activity.RESULT_OK) {
File cameraFile = new File(mCameraFilePath);
if (cameraFile.exists()) {
result = Uri.fromFile(cameraFile);
// Broadcast to the media scanner that we have a new photo
// so it will be added into the gallery for the user.
mController.getActivity().sendBroadcast(
new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
}
}
mUploadMessage.onReceiveValue(result);
mHandled = true;
mCaughtActivityNotFoundException = false;
}
void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
final String imageMimeType = "image/*";
final String videoMimeType = "video/*";
final String audioMimeType = "audio/*";
final String mediaSourceKey = "capture";
final String mediaSourceValueCamera = "camera";
final String mediaSourceValueFileSystem = "filesystem";
final String mediaSourceValueCamcorder = "camcorder";
final String mediaSourceValueMicrophone = "microphone";
// According to the spec, media source can be 'filesystem' or 'camera' or 'camcorder'
// or 'microphone' and the default value should be 'filesystem'.
String mediaSource = mediaSourceValueFileSystem;
if (mUploadMessage != null) {
// Already a file picker operation in progress.
return;
}
mUploadMessage = uploadMsg;
// Parse the accept type.
String params[] = acceptType.split(";");
String mimeType = params[0];
if (capture.length() > 0) {
mediaSource = capture;
}
if (capture.equals(mediaSourceValueFileSystem)) {
// To maintain backwards compatibility with the previous implementation
// of the media capture API, if the value of the 'capture' attribute is
// "filesystem", we should examine the accept-type for a MIME type that
// may specify a different capture value.
for (String p : params) {
String[] keyValue = p.split("=");
if (keyValue.length == 2) {
// Process key=value parameters.
if (mediaSourceKey.equals(keyValue[0])) {
mediaSource = keyValue[1];
}
}
}
}
//Ensure it is not still set from a previous upload.
mCameraFilePath = null;
if (mimeType.equals(imageMimeType)) {
if (mediaSource.equals(mediaSourceValueCamera)) {
// Specified 'image/*' and requested the camera, so go ahead and launch the
// camera directly.
startActivity(createCameraIntent());
return;
} else {
// Specified just 'image/*', capture=filesystem, or an invalid capture parameter.
// In all these cases we show a traditional picker filetered on accept type
// so launch an intent for both the Camera and image/* OPENABLE.
Intent chooser = createChooserIntent(createCameraIntent());
chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(imageMimeType));
startActivity(chooser);
return;
}
} else if (mimeType.equals(videoMimeType)) {
if (mediaSource.equals(mediaSourceValueCamcorder)) {
// Specified 'video/*' and requested the camcorder, so go ahead and launch the
// camcorder directly.
startActivity(createCamcorderIntent());
return;
} else {
// Specified just 'video/*', capture=filesystem or an invalid capture parameter.
// In all these cases we show an intent for the traditional file picker, filtered
// on accept type so launch an intent for both camcorder and video/* OPENABLE.
Intent chooser = createChooserIntent(createCamcorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(videoMimeType));
startActivity(chooser);
return;
}
} else if (mimeType.equals(audioMimeType)) {
if (mediaSource.equals(mediaSourceValueMicrophone)) {
// Specified 'audio/*' and requested microphone, so go ahead and launch the sound
// recorder.
startActivity(createSoundRecorderIntent());
return;
} else {
// Specified just 'audio/*', capture=filesystem of an invalid capture parameter.
// In all these cases so go ahead and launch an intent for both the sound
// recorder and audio/* OPENABLE.
Intent chooser = createChooserIntent(createSoundRecorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT, createOpenableIntent(audioMimeType));
startActivity(chooser);
return;
}
}
// No special handling based on the accept type was necessary, so trigger the default
// file upload chooser.
startActivity(createDefaultOpenableIntent());
}
private void startActivity(Intent intent) {
try {
mController.getActivity().startActivityForResult(intent, Controller.FILE_SELECTED);
} catch (ActivityNotFoundException e) {
// No installed app was able to handle the intent that
// we sent, so fallback to the default file upload control.
try {
mCaughtActivityNotFoundException = true;
mController.getActivity().startActivityForResult(createDefaultOpenableIntent(),
Controller.FILE_SELECTED);
} catch (ActivityNotFoundException e2) {
// Nothing can return us a file, so file upload is effectively disabled.
Toast.makeText(mController.getActivity(), R.string.uploads_disabled,
Toast.LENGTH_LONG).show();
}
}
}
private Intent createDefaultOpenableIntent() {
// Create and return a chooser with the default OPENABLE
// actions including the camera, camcorder and sound
// recorder where available.
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
Intent chooser = createChooserIntent(createCameraIntent(), createCamcorderIntent(),
createSoundRecorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT, i);
return chooser;
}
private Intent createChooserIntent(Intent... intents) {
Intent chooser = new Intent(Intent.ACTION_CHOOSER);
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
chooser.putExtra(Intent.EXTRA_TITLE,
mController.getActivity().getResources()
.getString(R.string.choose_upload));
return chooser;
}
private Intent createOpenableIntent(String type) {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(type);
return i;
}
private Intent createCameraIntent() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File externalDataDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM);
File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
File.separator + "browser-photos");
cameraDataDir.mkdirs();
mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
System.currentTimeMillis() + ".jpg";
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
return cameraIntent;
}
private Intent createCamcorderIntent() {
return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
}
private Intent createSoundRecorderIntent() {
return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
}
}
}
res / values / string.xml의 추가 문자열 재구성 :
<string name="uploads_disabled">File uploads are disabled.</string>
<string name="choose_upload">Choose file for upload</string>
proguard를 사용하는 경우 proguard-project.txt에 다음 옵션이 필요할 수 있습니다.
-keepclassmembers class * extends android.webkit.WebChromeClient {
public void openFileChooser(...);
}
업데이트 # 1 (2015.09.09)
Android 5.0.1 호환 코드를 추가합니다.
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
Android 4.1에서을 정의해야한다는 것을 알았습니다 . 그런 다음 Michel Olivier의 솔루션을 따랐습니다.
필자는 실제로 파일 선택기를 Kitkat에 표시하고 이미지를 선택하고 활동 결과에서 파일 경로를 가져 왔지만 "수정"할 수없는 (이 해결 방법으로 인해) 입력을 채울 수있는 유일한 방법입니다. 파일 데이터와 함께.
누구나 활동에서 입력 필드에 액세스하는 방법을 알고 있습니까? 이 예제 주석을 사용하고 있습니다. 이 마지막 조각, 벽에있는 마지막 벽돌은 올바른 장소에 넣어야합니다 (코드에서 직접 이미지 파일 업로드를 트리거 할 수 있음).
업데이트 # 1
나는 하드 코어 안드로이드 개발자가 아니므로 초보자 수준에서 코드를 보여줄 것입니다. 기존 활동에서 새 활동을 작성 중입니다.
매니페스트 부분
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application android:label="TestApp">
<activity android:name=".BrowseActivity"></activity>
</application>
이 예제 답변 에서 BrowseActivity 클래스를 만들고 있습니다. WebChromeClient () 인스턴스는 마지막 부분을 제외하고 기본적으로 동일하게 보이며 선택기 UI 파트를 트리거합니다.
private final static int FILECHOOSER_RESULTCODE=1;
private final static int KITKAT_RESULTCODE = 2;
...
// The new WebChromeClient() looks pretty much the same, except one piece...
WebChromeClient chromeClient = new WebChromeClient(){
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg) { /* Default code */ }
// For Android 3.0+
public void openFileChooser( ValueCallback uploadMsg, String acceptType ) { /* Default code */ }
//For Android 4.1, also default but it'll be as example
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
BrowseActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), BrowseActivity.FILECHOOSER_RESULTCODE);
}
// The new code
public void showPicker( ValueCallback<Uri> uploadMsg ){
// Here is part of the issue, the uploadMsg is null since it is not triggered from Android
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
BrowseActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), BrowseActivity.KITKAT_RESULTCODE);
}}
그리고 더 많은 것들
web = new WebView(this);
// Notice this part, setting chromeClient as js interface is just lazy
web.getSettings().setJavaScriptEnabled(true);
web.addJavascriptInterface(chromeClient, "jsi" );
web.getSettings().setAllowFileAccess(true);
web.getSettings().setAllowContentAccess(true);
web.clearCache(true);
web.loadUrl( "http://as3breeze.com/upload.html" );
web.setWebViewClient(new myWebClient());
web.setWebChromeClient(chromeClient);
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
Log.d("Result", "("+requestCode+ ") - (" +resultCode + ") - (" + intent + ") - " + mUploadMessage);
if (null == intent) return;
Uri result = null;
if(requestCode==FILECHOOSER_RESULTCODE)
{
Log.d("Result","Old android");
if (null == mUploadMessage) return;
result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
} else if (requestCode == KITKAT_RESULTCODE) {
Log.d("Result","Kitkat android");
result = intent.getData();
final int takeFlags = intent.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
String path = getPath( this, result);
File selectedFile = new File(path);
//I used you example with a bit of editing so thought i would share, here i added a method to upload the file to the webserver
File selectedFile = new File(path);
UploadFile(selectedFile);
//mUploadMessage.onReceiveValue( Uri.parse(selectedFile.toString()) );
// Now we have the file but since mUploadMessage was null, it gets errors
}
}
public void UploadFile(File selectedFile)
{
Random rnd = new Random();
String sName = "File" + rnd.nextInt(999999) + selectedFile.getAbsolutePath().substring(selectedFile.getAbsolutePath().lastIndexOf("."));
UploadedFileName = sName;
uploadFile = selectedFile;
if (progressBar != null && progressBar.isShowing())
{
progressBar.dismiss();
}
// prepare for a progress bar dialog
progressBar = new ProgressDialog(mContext);
progressBar.setCancelable(true);
progressBar.setMessage("Uploading File");
progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressBar.show();
new Thread() {
public void run()
{
int serverResponseCode;
String serverResponseMessage;
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
DataInputStream inputStream = null;
String pathToOurFile = uploadFile.getAbsolutePath();
String urlServer = "http://serveraddress/Scripts/UploadHandler.php?name" + UploadedFileName;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1*1024*1024;
try
{
FileInputStream fileInputStream = new FileInputStream(uploadFile);
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
Log.i("File", urlServer);
// Allow Inputs & Outputs.
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// Set HTTP method to POST.
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
Log.i("File", "Open conn");
outputStream = new DataOutputStream( connection.getOutputStream() );
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + pathToOurFile +"\"" + lineEnd);
outputStream.writeBytes(lineEnd);
Log.i("File", "write bytes");
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
Log.i("File", "available: " + fileInputStream.available());
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
Log.i("file", "Bytes Read: " + bytesRead);
while (bytesRead > 0)
{
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
serverResponseCode = connection.getResponseCode();
serverResponseMessage = connection.getResponseMessage();
Log.i("file repsonse", serverResponseMessage);
//once the file is uploaded call a javascript function to verify the user wants to save the image
progressBar.dismiss();
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Log.i("start", "File name: " + UploadedFileName);
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("javascript:CheckImage('" + UploadedFileName + "')");
}
});
fileInputStream.close();
outputStream.flush();
outputStream.close();
}
catch (Exception ex)
{
Log.i("exception", "Error: " + ex.toString());
}
}
}.start();
}
마지막으로 실제 파일 경로를 얻는 코드가 더 많으므로 SO에있는 코드는 주석에 게시물 URL을 추가하여 저자가 자신의 작업에 대한 크레딧을 얻습니다.
/**
* Get a file path from a Uri. This will get the the path for Storage Access
* Framework Documents, as well as the _data field for the MediaStore and
* other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @author paulburke
* @source https://stackoverflow.com/a/20559175
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
* @source https://stackoverflow.com/a/20559175
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
* @source https://stackoverflow.com/a/20559175
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
* @source https://stackoverflow.com/a/20559175
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
* @source https://stackoverflow.com/a/20559175
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
마지막으로 HTML 페이지는 새로운 showPicker 메소드를 트리거해야합니다 (A4.4의 경우 구체적으로).
<form id="form-upload" method="post" enctype="multipart/form-data">
<input id="fileupload" name="fileupload" type="file" onclick="javascript:prepareForPicker();"/>
</form>
<script type="text/javascript">
function getAndroidVersion() {
var ua = navigator.userAgent;
var match = ua.match(/Android\s([0-9\.]*)/);
return match ? match[1] : false;
};
function prepareForPicker(){
if(getAndroidVersion().indexOf("4.4") != -1){
window.jsi.showPicker();
return false;
}
}
function CheckImage(name)
{
//Check to see if user wants to save I used some ajax to save the file if necesarry
}
</script>
이것은 나를 위해 일한 것입니다. 또한 누가와 산들을 위해 일 [ [
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
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.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private final static int FCR = 1;
WebView webView;
private String mCM;
private ValueCallback<Uri> mUM;
private ValueCallback<Uri[]> mUMA;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (Build.VERSION.SDK_INT >= 21) {
Uri[] results = null;
//Check if response is positive
if (resultCode == Activity.RESULT_OK) {
if (requestCode == FCR) {
if (null == mUMA) {
return;
}
if (intent == null) {
//Capture Photo if no image available
if (mCM != null) {
results = new Uri[]{Uri.parse(mCM)};
}
} else {
String dataString = intent.getDataString();
if (dataString != null) {
results = new Uri[]{Uri.parse(dataString)};
}
}
}
}
mUMA.onReceiveValue(results);
mUMA = null;
} else {
if (requestCode == FCR) {
if (null == mUM) return;
Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
mUM.onReceiveValue(result);
mUM = null;
}
}
}
@SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 23 && (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1);
}
webView = (WebView) findViewById(R.id.ifView);
assert webView != null;
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
if (Build.VERSION.SDK_INT >= 21) {
webSettings.setMixedContentMode(0);
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else if (Build.VERSION.SDK_INT >= 19) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else if (Build.VERSION.SDK_INT < 19) {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webView.setWebViewClient(new Callback());
webView.loadUrl("https://infeeds.com/");
webView.setWebChromeClient(new WebChromeClient() {
//For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FCR);
}
// For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this
public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MainActivity.this.startActivityForResult(
Intent.createChooser(i, "File Browser"),
FCR);
}
//For Android 4.1+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), MainActivity.FCR);
}
//For Android 5.0+
public boolean onShowFileChooser(
WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {
if (mUMA != null) {
mUMA.onReceiveValue(null);
}
mUMA = filePathCallback;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCM);
} catch (IOException ex) {
Log.e(TAG, "Image file creation failed", ex);
}
if (photoFile != null) {
mCM = "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("*/*");
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, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, FCR);
return true;
}
});
}
// Create an image file
private File createImageFile() throws IOException {
@SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "img_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return File.createTempFile(imageFileName, ".jpg", storageDir);
}
@Override
public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (webView.canGoBack()) {
webView.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
public class Callback extends WebViewClient {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(getApplicationContext(), "Failed loading app!", Toast.LENGTH_SHORT).show();
}
}
}
Google 자체 브라우저는이 문제에 대한 포괄적 인 솔루션을 제공하여 자체 클래스를 보증합니다.
Android 4.0.4에서 openFileChooser 구현
Android 4.0.4의 UploadHandler 클래스
나에게 맞는 솔루션 을 찾았 습니다! 파일에 하나 이상의 규칙을 추가하십시오 proguard-android.txt
.
-keepclassmembers class * extends android.webkit.WebChromeClient {
public void openFileChooser(...);
}
안드로이드 8을위한 코 틀린 솔루션 :
private var mUploadMessage: ValueCallback<Uri>? = null
private var uploadMessage: ValueCallback<Array<Uri>>? = null
상수 :
const val FILECHOOSER_RESULTCODE = 1
const val REQUEST_SELECT_FILE = 100
WebView 설정 :
webView.webChromeClient = object : WebChromeClient() {
override fun onPermissionRequest(request: PermissionRequest?) {
Log.d("MainActivity", "onPermissionRequest")
requestPermission(request)
}
// For Android 3.0+
fun openFileChooser(uploadMsg: ValueCallback<*>, acceptType: String) {
mUploadMessage = uploadMsg as ValueCallback<Uri>
val i = Intent(Intent.ACTION_GET_CONTENT)
i.addCategory(Intent.CATEGORY_OPENABLE)
i.type = "*/*"
this@MainActivity.startActivityForResult(
Intent.createChooser(i, "File Browser"),
FILECHOOSER_RESULTCODE)
}
//For Android 4.1
fun openFileChooser(uploadMsg: ValueCallback<Uri>, acceptType: String, capture: String) {
mUploadMessage = uploadMsg
val i = Intent(Intent.ACTION_GET_CONTENT)
i.addCategory(Intent.CATEGORY_OPENABLE)
i.type = "image/*"
this@MainActivity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE)
}
protected fun openFileChooser(uploadMsg: ValueCallback<Uri>) {
mUploadMessage = uploadMsg
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
startActivityForResult(Intent.createChooser(intent, "File Chooser"), FILECHOOSER_RESULTCODE)
}
override fun onShowFileChooser(webView: WebView?, filePathCallback: ValueCallback<Array<Uri>>?, fileChooserParams: FileChooserParams?): Boolean {
uploadMessage?.onReceiveValue(null)
uploadMessage = null
uploadMessage = filePathCallback
val intent = fileChooserParams!!.createIntent()
try {
startActivityForResult(intent, REQUEST_SELECT_FILE)
} catch (e: ActivityNotFoundException) {
uploadMessage = null
Toast.makeText(applicationContext, "Cannot Open File Chooser", Toast.LENGTH_LONG).show()
return false
}
return true
}
}
그리고 onAcrtivityResult 부분 :
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (requestCode === REQUEST_SELECT_FILE) {
if (uploadMessage == null)
return
print("result code = " + resultCode)
var results: Array<Uri>? = WebChromeClient.FileChooserParams.parseResult(resultCode, data)
uploadMessage?.onReceiveValue(results)
uploadMessage = null
}
} else if (requestCode === FILECHOOSER_RESULTCODE) {
if (null == mUploadMessage)
return
// Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
// Use RESULT_OK only if you're implementing WebView inside an Activity
val result = if (intent == null || resultCode !== RESULT_OK) null else intent.data
mUploadMessage?.onReceiveValue(result)
mUploadMessage = null
} else
Toast.makeText(applicationContext, "Failed to Upload Image", Toast.LENGTH_LONG).show()
}
의도 변수 "data"에주의하십시오.
이 링크를 방문하셨습니까? http://groups.google.com/group/android-developers/browse_thread/thread/dcaf8b2fdd8a90c4/62d5e2ffef31ebdb
http://moazzam-khan.com/blog/?tag=android-upload-file
http://evgenyg.wordpress.com/2010/05/01/uploading-files-multipart-post-apache/
Java lib Apache Commons를 통한 파일 업로드의 간결한 예
나는 당신이 이것으로부터 도움을 얻을 것이라고 생각합니다
KitKat에서는 Storage Access Framework를 사용할 수 있습니다.
웹뷰-단일 및 다중 파일 선택
이 코드를 구현하려면 2 분이 필요합니다.
build.gradle
implementation 'com.github.angads25:filepicker:1.1.1'
자바 코드 :
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.KeyEvent;
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.ProgressBar;
import android.widget.Toast;
import com.bivoiclient.utils.Constants;
import com.github.angads25.filepicker.controller.DialogSelectionListener;
import com.github.angads25.filepicker.model.DialogConfigs;
import com.github.angads25.filepicker.model.DialogProperties;
import com.github.angads25.filepicker.view.FilePickerDialog;
import java.io.File;
public class WebBrowserScreen extends Activity {
private WebView webView;
private ValueCallback<Uri[]> mUploadMessage;
private FilePickerDialog dialog;
private String LOG_TAG = "DREG";
private Uri[] results;
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_complain);
webView = findViewById(R.id.webview);
WebSettings webSettings = webView.getSettings();
webSettings.setAppCacheEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webSettings.setJavaScriptEnabled(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setAllowFileAccess(true);
webView.setWebViewClient(new PQClient());
webView.setWebChromeClient(new PQChromeClient());
if (Build.VERSION.SDK_INT >= 19) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webView.loadUrl(Constants.COMPLAIN_URL);
}
private void openFileSelectionDialog() {
if (null != dialog && dialog.isShowing()) {
dialog.dismiss();
}
//Create a DialogProperties object.
final DialogProperties properties = new DialogProperties();
//Instantiate FilePickerDialog with Context and DialogProperties.
dialog = new FilePickerDialog(WebBrowserScreen.this, properties);
dialog.setTitle("Select a File");
dialog.setPositiveBtnName("Select");
dialog.setNegativeBtnName("Cancel");
properties.selection_mode = DialogConfigs.MULTI_MODE; // for multiple files
// properties.selection_mode = DialogConfigs.SINGLE_MODE; // for single file
properties.selection_type = DialogConfigs.FILE_SELECT;
//Method handle selected files.
dialog.setDialogSelectionListener(new DialogSelectionListener() {
@Override
public void onSelectedFilePaths(String[] files) {
results = new Uri[files.length];
for (int i = 0; i < files.length; i++) {
String filePath = new File(files[i]).getAbsolutePath();
if (!filePath.startsWith("file://")) {
filePath = "file://" + filePath;
}
results[i] = Uri.parse(filePath);
Log.d(LOG_TAG, "file path: " + filePath);
Log.d(LOG_TAG, "file uri: " + String.valueOf(results[i]));
}
mUploadMessage.onReceiveValue(results);
mUploadMessage = null;
}
});
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
if (null != mUploadMessage) {
if (null != results && results.length >= 1) {
mUploadMessage.onReceiveValue(results);
} else {
mUploadMessage.onReceiveValue(null);
}
}
mUploadMessage = null;
}
});
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
if (null != mUploadMessage) {
if (null != results && results.length >= 1) {
mUploadMessage.onReceiveValue(results);
} else {
mUploadMessage.onReceiveValue(null);
}
}
mUploadMessage = null;
}
});
dialog.show();
}
public class PQChromeClient extends WebChromeClient {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
// Double check that we don't have any existing callbacks
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(null);
}
mUploadMessage = filePathCallback;
openFileSelectionDialog();
return true;
}
}
//Add this method to show Dialog when the required permission has been granted to the app.
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
switch (requestCode) {
case FilePickerDialog.EXTERNAL_READ_PERMISSION_GRANT: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (dialog != null) {
openFileSelectionDialog();
}
} else {
//Permission has not been granted. Notify the user.
Toast.makeText(WebBrowserScreen.this, "Permission is Required for getting list of files", Toast.LENGTH_SHORT).show();
}
}
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
webView.goBack();
return true;
}
// If it wasn't the Back key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity)
return super.onKeyDown(keyCode, event);
}
public class PQClient extends WebViewClient {
ProgressBar progressDialog;
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// If url contains mailto link then open Mail Intent
if (url.contains("mailto:")) {
// Could be cleverer and use a regex
//Open links in new browser
view.getContext().startActivity(
new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
// Here we can open new activity
return true;
} else {
// Stay within this webview and load url
view.loadUrl(url);
return true;
}
}
// Show loader on url load
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// Then show progress Dialog
// in standard case YourActivity.this
if (progressDialog == null) {
progressDialog = findViewById(R.id.progressBar);
progressDialog.setVisibility(View.VISIBLE);
}
}
// Called when all page resources loaded
public void onPageFinished(WebView view, String url) {
webView.loadUrl("javascript:(function(){ " +
"document.getElementById('android-app').style.display='none';})()");
try {
// Close progressDialog
progressDialog.setVisibility(View.GONE);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
}
I'm new to Andriod and struggled with this also. According to Google Reference Guide WebView.
By default, a WebView provides no browser-like widgets, does not enable JavaScript and web page errors are ignored. If your goal is only to display some HTML as a part of your UI, this is probably fine; the user won't need to interact with the web page beyond reading it, and the web page won't need to interact with the user. If you actually want a full-blown web browser, then you probably want to invoke the Browser application with a URL Intent rather than show it with a WebView.
Example code I executed in MainActvity.java.
Uri uri = Uri.parse("https://www.example.com");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
Excuted
package example.com.myapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.content.Intent;
import android.net.Uri;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Uri uri = Uri.parse("http://www.example.com/");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
getSupportActionBar().hide();
}}
I researched on this issue for almost one month. Everything failed. All codes seen in multiple websites does n't work good. But here exists the best solution
https://github.com/chiclaim/android-webview-upload-file
단계
1) 복제 또는 다운로드를 클릭하십시오
2) 로컬 디렉토리에서 우편 번호를 가져옵니다.
3) 압축 파일을 압축 해제
4) 오픈 안드로이드 스튜디오
5) 파일로 이동 ----> 열기 ---> 내용의 압축을 푼 디렉토리로 이동하십시오.
6) webView.loadUrl ( "your url hre")에서 필요한 웹 URL을 변경하십시오. MainActivity.java에서
7) 버전 안드로이드 스튜디오 3.4.2와 잘 작동
참고 URL : https://stackoverflow.com/questions/5907369/file-upload-in-webview
'Programing' 카테고리의 다른 글
친숙한 URL을위한 안전한 문자 (0) | 2020.06.07 |
---|---|
값이 홀수인지 또는 짝수인지 테스트 (0) | 2020.06.07 |
Java : System.console ()에서 입력을 얻는 방법 (0) | 2020.06.07 |
안드로이드 소프트 키보드 커버 편집 텍스트 필드 (0) | 2020.06.07 |
C #을 사용하여 CSV 파일 읽기 (0) | 2020.06.07 |