[英]Android WebView File Upload
我正在開發一款Android應用。 基本上它是一個WebView
和一個progressBar。 Facebook的移動網站(m.facebook.com)被加載到WebView
。
當我單擊“選擇文件”按鈕上傳圖像時,沒有任何反應。 我已經嘗試了所有解決方案,但沒有一個能夠正常工作。 我正在測試運行4.0.3的Galaxy Note(GT-N7000)。 我的最低SDK版本是版本8。
(來源: istyla.com )
這是我的代碼了解更多信息......
public class IStyla extends Activity {
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;
}
}
private class MyWebChromeClient extends WebChromeClient {
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
IStyla.this.startActivityForResult(Intent.createChooser(i, "Image Browser"), FILECHOOSER_RESULTCODE);
}
@Override
public boolean onJsAlert(WebView view, String url, String message,final JsResult result) {
//handle Alert event, here we are showing AlertDialog
new AlertDialog.Builder(IStyla.this)
.setTitle("JavaScript Alert !")
.setMessage(message)
.setPositiveButton(android.R.string.ok,
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do your stuff
result.confirm();
}
}).setCancelable(false).create().show();
return true;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_istyla);
WebView webView = (WebView) findViewById(R.id.webView1);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.setWebChromeClient(new MyWebChromeClient(){
public void onProgressChanged(WebView view, int progress) {
// Activities and WebViews measure progress with different scales.
// The progress meter will automatically disappear when we reach 100%
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar1);
if(progress < 100 && progressBar.getVisibility() == ProgressBar.GONE){
progressBar.setVisibility(ProgressBar.VISIBLE);
}
progressBar.setProgress(progress);
if(progress == 100) {
progressBar.setVisibility(ProgressBar.GONE);
}
}
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
IStyla.this.startActivityForResult(Intent.createChooser(i, "Image Browser"), FILECHOOSER_RESULTCODE);
}
});
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar1);
progressBar.setVisibility(ProgressBar.VISIBLE);
return true;
}
});
webView.loadUrl("https://m.facebook.com");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK){
if(((WebView)findViewById(R.id.webView1)).canGoBack()){
((WebView)findViewById(R.id.webView1)).goBack();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_istyla, menu);
return true;
}
}
謝謝
這就是我在我的應用程序中使用的方式
private class MyWebChromeClient extends 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 uploadMsg, String acceptType) {
mUploadMessage = uploadMsg;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
}
//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("*/*");
startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
}
protected void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(Intent.createChooser(intent, "File Chooser"), 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 = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
intent = fileChooserParams.createIntent();
}
try {
startActivityForResult(intent, REQUEST_SELECT_FILE);
} catch (ActivityNotFoundException e) {
uploadMessage = null;
Toast.makeText(getApplicationContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show();
return false;
}
return true;
}
由Fr33dan分享的Mike Olivier的參考很重要。 我正在分享在我的情況下對我有用的東西。
wv.setWebChromeClient(new WebChromeClient() {
// For Android 3.0+
public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
MainActivity.this.startActivityForResult( Intent.createChooser( i, getString(R.string.fileselect) ), MainActivity.FILECHOOSER_RESULTCODE );
}
// For Android < 3.0
public void openFileChooser( ValueCallback<Uri> uploadMsg ) {
openFileChooser( uploadMsg, "" );
}
// For Android > 4.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
openFileChooser( uploadMsg, "" );
}
});
注意:我在堆棧溢出和m0s的博客中找到了這個地方。
另外,忽略lint警告。 這個適用於API 8及更高版本。
鑒於投票數量很高,我猜測沒有人注意到第3條評論(來自David Esteves )包含了回答這個問題的鏈接。
米歇爾奧利維爾說:
該解決方案也適用於Honeycomb和Ice Cream Sandwich。 似乎谷歌推出了一個很酷的新功能(接受屬性),忘了實現過載以實現向后兼容。
所以你只需要在接受字符串參數的MyWebChromeClient
類中添加一個openFileChooser
重載,然后調用不會:
public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType )
{
this.openFileChooser(uploadMsg);
}
這樣做我能夠使您的代碼按預期運行。
此代碼將有助於解決此問題
只需使用下面的代碼更新MainActivity.Java文件即可
public class MainActivity extends Activity{
private 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;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mWebview = (WebView) findViewById(R.id.help_webview);
WebSettings webSettings = mWebview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setAllowFileAccess(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setPluginState(WebSettings.PluginState.ON);
webSettings.setSupportZoom(true);
webSettings.setAllowContentAccess(true);
final Activity activity = this;
mWebview.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(activity, description, Toast.LENGTH_SHORT).show();
}
});
mWebview .loadUrl("http://www.google.com");
String permission = Manifest.permission.CAMERA;
int grant = ContextCompat.checkSelfPermission(this, permission);
if (grant != PackageManager.PERMISSION_GRANTED) {
String[] permission_list = new String[1];
permission_list[0] = permission;
ActivityCompat.requestPermissions(this, permission_list, 1);
}
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
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
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(MainActivity.this.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);
}
});
}
@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(MainActivity.this.getApplicationContext(), "Failed to Upload Image", Toast.LENGTH_LONG).show();
}
確保在AndroidManifest.xml中啟用權限更新以下行
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
它適用於我嘗試使用此代碼。
在WebChromeClient.OpenFileChooser中調用AlertDialog時,您需要通知webchrome在后退按鈕的情況下沒有選擇。 由於可以在對話框中按下“返回”按鈕,因此必須處理對話框的OnCancel並告知WebChrome選擇已完成。
例如:
private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE = 1;
private final static int CAMERA_RESULTCODE = 2;
...
webView.setWebChromeClient(new WebChromeClient() {
public boolean onConsoleMessage(ConsoleMessage cm) {
Log.d("MyApplication", cm.message() + " -- From line "
+ cm.lineNumber() + " of "
+ cm.sourceId() );
return true;
}
public void onExceededDatabaseQuota(String url, String
databaseIdentifier, long currentQuota, long estimatedSize, long
totalUsedQuota, QuotaUpdater quotaUpdater) {
quotaUpdater.updateQuota(estimatedSize+65536);
}
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType, String capture) {
this.openFileChooser(uploadMsg);
}
@SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType) {
this.openFileChooser(uploadMsg);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
mUploadMessage = uploadMsg;
PesScreen.this.openImageIntent();
}
});
...
private void openImageIntent() {
final File root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); //file storage
root.mkdirs();
int nCnt = 1;
if ( root.listFiles() != null )
nCnt = root.listFiles().length;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
final String fname = String.format("/dest-%s-%d.jpg", sdf.format(Calendar.getInstance().getTime()), nCnt);
final File sdImageMainDirectory = new File(root.getAbsolutePath() + fname);
outputFileUri = Uri.fromFile(sdImageMainDirectory);
//selection Photo/Gallery dialog
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Select source");
final CharSequence[] items = {"Photo", "Gallery"};
alert.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
if( whichButton == 0)
{
Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(chooserIntent, CAMERA_RESULTCODE);
}
if( whichButton == 1)
{
Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT);
chooserIntent.setType("image/*");
startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
}
}
});
alert.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
//here we have to handle BACK button/cancel
if ( mUploadMessage!= null ){
mUploadMessage.onReceiveValue(null);
}
mUploadMessage = null;
dialog.dismiss();
}
});
alert.create().show();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.