"选择要上传的文件"在Android版的WebView 4.4.2奇巧 [英] "choose file to upload" on webview android kitkat 4.4.2
问题描述
我有一个Web视图,我添加了code上传文件和它运作良好,在4.3和4.2(银河S3),但它不喜欢4.4.2银河S5和LG3工作。
当我点击选择文件不响应,没有任何反应...
这是我的code。
MainActivity.java:
包com.com.myapplication;/ **
*创建者tadmitinteractive于14年9月21日。
* /进口android.app.Activity;
进口android.app.AlertDialog;
进口android.app.ProgressDialog;
进口android.content.ActivityNotFoundException;
进口android.content.DialogInterface;
进口android.content.Intent;
进口android.graphics.Bitmap;
进口android.net.Uri;
进口android.os.Bundle;
进口android.os.Environment;
进口android.provider.MediaStore;
进口android.view.View;
进口android.webkit.JsResult;
进口android.webkit.ValueCallback;
进口android.webkit.WebChromeClient;
进口android.webkit.WebSettings;
进口android.webkit.WebSettings.PluginState;
进口android.webkit.WebView;
进口android.webkit.WebViewClient;
进口android.widget.ImageView;
进口android.widget.Toast;进口的java.io.File;
进口的java.lang.reflect.Method;
进口的java.net.URL;公共类MainActivity延伸活动{ @覆盖
公共无效的onCreate(捆绑savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.main);
web视图的WebView =(的WebView)findViewById(R.id.webview); 字符串URL =http://www.ipets.co.il/wp-login.php;
initWebView(web视图,URL);
// TODO输入您的网址 } 私人最终静态对象methodInvoke(obj对象,字符串方法,类<> [] parameterTypes,对象[]参数){
尝试{
方法M = obj.getClass()实现getMethod(方法,新的Class [] {} boolean.class)。
m.invoke(OBJ,参数);
}赶上(例外五){
e.printStackTrace();
} 返回null;
}
私人无效initWebView(的WebView视图,字符串URL){ WebSettings设置= view.getSettings();
最终的WebView myWebView =(的WebView)findViewById(R.id.webview);
最后ImageView的ImageView的=(ImageView的)findViewById(R.id.imageView);
view.setWebViewClient(新WebViewClient());
settings.setJavaScriptEnabled(真);
settings.setAllowFileAccess(真);
settings.setDomStorageEnabled(真);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
settings.setLoadWithOverviewMode(真);
settings.setUseWideViewPort(真);
settings.setSupportZoom(真);
// settings.setPluginsEnabled(真);
methodInvoke(设置setPluginsEnabled,新的Class [] {} boolean.class,新的对象[] {真});
// settings.setPluginState(PluginState.ON);
methodInvoke(设置setPluginState,新的Class [] {} PluginState.class,新的对象[] {PluginState.ON});
// settings.setPluginsEnabled(真);
methodInvoke(设置setPluginsEnabled,新的Class [] {} boolean.class,新的对象[] {真});
// settings.setAllowUniversalAccessFromFileURLs(真);
methodInvoke(设置setAllowUniversalAccessFromFileURLs,新的Class [] {} boolean.class,新的对象[] {真});
// settings.setAllowFileAccessFromFileURLs(真);
methodInvoke(设置setAllowFileAccessFromFileURLs,新的Class [] {} boolean.class,新的对象[] {真}); view.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
view.clearHistory();
view.clearFormData();
view.clearCache(真);
view.loadUrl(URL); view.setWebViewClient(新WebViewClient(){
ProgressDialog对话框=新ProgressDialog(MainActivity.this);
@覆盖
公共无效onPageStarted(的WebView视图,字符串URL,
位图图标){
// TODO自动生成方法存根 dialog.setMessage(טוען......);
dialog.show();
super.onPageStarted(查看,网址,图标);
} @覆盖
公共无效onPageFinished(的WebView视图,字符串URL){
// TODO自动生成方法存根
myWebView.setVisibility(View.VISIBLE);
imageView.setVisibility(View.GONE);
dialog.dismiss();
super.onPageFinished(查看,网址); }
}); view.setWebChromeClient(新MyWebChromeClient());
// webView.setDownloadListener(downloadListener); } UploadHandler mUploadHandler; @覆盖
保护无效的onActivityResult(INT申请code,INT结果code,意图意图){ 如果(要求code == Controller.FILE_SELECTED){
//之所以选择从文件选择器中的文件。
如果(mUploadHandler!= NULL){
mUploadHandler.onResult(结果code,意向);
}
} super.onActivityResult(要求code,结果code,意向);
} 类MyWebChromeClient扩展WebChromeClient {
公共MyWebChromeClient(){ } 私人字符串getTitleFromUrl(字符串URL){
字符串title =网址;
尝试{
网址urlObj =新的URL(网址);
串主机= urlObj.getHost();
如果(主机=空&放大器;!&放大器;!host.isEmpty()){
返回urlObj.getProtocol()+://+主机;
}
如果(url.startsWith(文件)){
字符串文件名= urlObj.getFile();
如果(文件名= NULL&放大器;!&安培;!fileName.isEmpty()){
返回文件名;
}
}
}赶上(例外五){
// 忽视
} 返回称号;
} @覆盖
公共布尔onJsAlert(的WebView视图,URL字符串,字符串消息,最终的结果JsResult){
字符串newTitle的= getTitleFromUrl(URL); 新AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok,新DialogInterface.OnClickListener(){ @覆盖
公共无效的onClick(DialogInterface对话,诠释它){
result.confirm();
}
})setCancelable(假).create()显示()。
返回true;
//返回super.onJsAlert(查看,网址,邮件,结果);
} @覆盖
公共布尔onJsConfirm(的WebView视图,URL字符串,字符串消息,最终的结果JsResult){ 字符串newTitle的= getTitleFromUrl(URL); 新AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok,新DialogInterface.OnClickListener(){ @覆盖
公共无效的onClick(DialogInterface对话,诠释它){
result.confirm();
}
})。setNegativeButton(android.R.string.cancel,新DialogInterface.OnClickListener(){
公共无效的onClick(DialogInterface对话,诠释它){
result.cancel();
}
})setCancelable(假).create()显示()。
返回true; //返回super.onJsConfirm(查看,网址,邮件,结果);
} //的Android 2.X
公共无效openFileChooser(ValueCallback<&乌里GT; uploadMsg){
openFileChooser(uploadMsg,);
} // Android 3.0的
公共无效openFileChooser(ValueCallback<&乌里GT; uploadMsg,弦乐acceptType){
openFileChooser(uploadMsg,,文件系统);
} //是Android 4.1
公共无效openFileChooser(ValueCallback<&乌里GT; uploadMsg,字符串acceptType,字符串捕获){
mUploadHandler =新UploadHandler(新控制器());
mUploadHandler.openFileChooser(uploadMsg,acceptType,捕捉);
}
}; 类控制器{
最终静态INT FILE_SELECTED = 4; 活性getActivity(){
返回MainActivity.this;
}
} //从Android的4.4.3_r1 / src目录/ COM /安卓/浏览器/ UploadHandler.java复制
////////////////////////////////////////////////// //////////////////// / *
*版权所有(C)2010年Android开源项目
*
*在Apache许可,2.0版(以下简称许可证);
*您不能使用这个文件除了在遵守许可。
*您可以在获得许可证的副本
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*除非适用法律要求或书面同意,软件
*许可下发布的分布在原样的基础,
*无担保或任何形式的条件,无论是前preSS或暗示的保证。
*请参阅许可证的特定语言的管理权限和
*根据许可证的限制。
* / //包com.android.browser;
//
//进口android.app.Activity;
//进口android.content.ActivityNotFoundException;
//进口android.content.Intent;
//进口android.net.Uri;
//进口android.os.Environment;
//进口android.provider.MediaStore;
//进口android.webkit.ValueCallback;
//进口android.widget.Toast;
//
//进口的java.io.File;
//进口java.util.Vector中;
//
// / **
// *从web视图处理文件上传这里的回调
// * /
//公共类UploadHandler { 类UploadHandler {
/ *
*用于通知文件的WebView上传的对象。
* /
私人ValueCallback<&乌里GT; mUploadMessage;
私人字符串mCameraFilePath;
私人布尔mHandled;
私人布尔mCaughtActivityNotFoundException;
私人控制器mController;
公共UploadHandler(控制器控制器){
mController =控制器;
}
串getFilePath(){
返回mCameraFilePath;
}
布尔处理(){
返回mHandled;
}
无效onResult(INT结果code,意图意图){
如果(结果code == Activity.RESULT_CANCELED&放大器;&安培; mCaughtActivityNotFoundException){
//无法解析一个活动,我们将再次尝试所以跳过
//这个结果。
mCaughtActivityNotFoundException = FALSE;
返回;
}
乌里结果=意图== NULL ||结果code!= Activity.RESULT_OK?空值
:intent.getData();
//当我们问相机来保存用户回吐的结果
//一张照片后,相机应用程序不返回任何其他
//比RESULT_OK。因此,我们需要检查文件是否我们的预期
//在的情况下写入到磁盘中,我们
//没有得到返回的意图,但确实得到了RESULT_OK。如果是,
//我们假设这个结果已经来自于相机背面。
如果(结果== NULL和放大器;&安培;意图== NULL和放大器;&安培;结果code == Activity.RESULT_OK){
文件cameraFile =新的文件(mCameraFilePath);
如果(cameraFile.exists()){
结果= Uri.fromFile(cameraFile);
//发送到我们有一个新的照片媒体扫描
//所以它会被添加到库的用户。
mController.getActivity()。sendBroadcast(
新意图(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,结果));
}
}
mUploadMessage.onReceiveValue(结果);
mHandled = TRUE;
mCaughtActivityNotFoundException = FALSE;
}
无效openFileChooser(ValueCallback<&乌里GT; uploadMsg,字符串acceptType,字符串捕获){
最后弦乐imageMimeType =图像/ *;
最后弦乐videoMimeType =视频/ *;
最后弦乐audioMimeType =音频/ *;
最后弦乐mediaSourceKey =捕获;
最后弦乐mediaSourceValueCamera =镜头;
最后弦乐mediaSourceValueFileSystem =文件系统;
最后弦乐mediaSourceValueCamcorder =摄像机
最后弦乐mediaSourceValueMicrophone =麦克风;
//根据规范,媒体源可以是文件系统或相机或摄像机
//或麦克风,默认值应该是文件系统。
字符串MEDIASOURCE = mediaSourceValueFileSystem;
如果(mUploadMessage!= NULL){
//已经是正在进行的文件选择操作。
返回;
}
mUploadMessage = uploadMsg;
//解析接受的类型。
串PARAMS [] = acceptType.split(;);
串mime类型=参数[0];
如果(capture.length()大于0){
MEDIASOURCE =捕捉;
}
如果(capture.equals(mediaSourceValueFileSystem)){
//为了保持与previous实现向后兼容
//媒体捕捉的API,如果'捕获'属性的值是
//文件系统,我们应该研究的接受式的MIME类型
//可以指定不同的捕获值。
对(串P:PARAMS){
串[]的keyValue = p.split(=);
如果(keyValue.length == 2){
//处理key = value的参数。
如果(mediaSourceKey.equals(的keyValue [0])){
MEDIASOURCE =的keyValue [1];
}
}
}
}
//确保它是不是还从previous上传设置。
mCameraFilePath = NULL;
如果(mimeType.equals(imageMimeType)){
如果(mediaSource.equals(mediaSourceValueCamera)){
//指定的图像/ *,并要求拍照,所以,尽管启动
//相机直接。
startActivity(createCameraIntent());
返回;
}其他{
//指定只是图像/ *',捕捉文件系统=,或无效的拍摄参数。
//在所有这些情况下,我们展示filetered在接受型传统选择器
//所以推出一个意图您的相机和图像/ *打开的两个。
意向选择器= createChooserIntent(createCameraIntent());
chooser.putExtra(Intent.EXTRA_INTENT,createOpenableIntent(imageMimeType));
startActivity(选配);
返回;
}
}否则如果(mimeType.equals(videoMimeType)){
如果(mediaSource.equals(mediaSourceValueCamcorder)){
//指定的视频/ *,并要求摄像机,所以,尽管启动
//摄像机直接。
startActivity(createCamcorderIntent());
返回;
}其他{
//指定只是视频/ *',捕获=文件系统或无效的拍摄参数。
//在所有这些情况下,我们显示了传统的文件选择器的意图,过滤
//在接受类型,以便发动意图为摄像机和视频/ *打开。
意向选择器= createChooserIntent(createCamcorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT,createOpenableIntent(videoMimeType));
startActivity(选配);
返回;
}
}否则如果(mimeType.equals(audioMimeType)){
如果(mediaSource.equals(mediaSourceValueMicrophone)){
//指定的音频/ *,并要求麦克风,所以,尽管推出的声音
//记录。
startActivity(createSoundRecorderIntent());
返回;
}其他{
//指定只是'音频/ *',捕获=无效捕捉参数的文件系统。
//在所有这些情况下,所以,尽管推出的意图为声音
//记录器和音频/ *打开。
意向选择器= createChooserIntent(createSoundRecorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT,createOpenableIntent(audioMimeType));
startActivity(选配);
返回;
}
}
//基于该接受类型没有特殊的处理是必要的,所以触发默认
//文件上传选择器。
startActivity(createDefaultOpenableIntent());
}
私人无效startActivity(意向意图){
尝试{
。mController.getActivity()startActivityForResult(意向,Controller.FILE_SELECTED);
}赶上(ActivityNotFoundException E){
//没有安装的应用程序能够处理的意图
//我们发送,因此退回到默认的文件上传控件。
尝试{
mCaughtActivityNotFoundException =真;
mController.getActivity()。startActivityForResult(createDefaultOpenableIntent(),
Controller.FILE_SELECTED);
}赶上(ActivityNotFoundException E2){
//没有什么能回报我们一个文件,这样的文件上传有效禁止。
Toast.makeText(mController.getActivity(),R.string.uploads_disabled,
Toast.LENGTH_LONG).show();
}
}
}
私人意图createDefaultOpenableIntent(){
//创建并使用默认打开的返回一个选择器
//行动,包括照相机,摄像机和声音
//记录(如有)。
意图I =新意图(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(* / *);
意向选择器= createChooserIntent(createCameraIntent(),createCamcorderIntent()
createSoundRecorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT,I);
返回选择器;
}
私人意图createChooserIntent(意向...意图){
意图选择器=新意图(Intent.ACTION_CHOOSER);
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS,意图);
chooser.putExtra(Intent.EXTRA_TITLE,
mController.getActivity()。getResources()
.getString(R.string.choose_upload));
返回选择器;
}
私人意图createOpenableIntent(字符串类型){
意图I =新意图(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(类型);
返回我;
}
私人意图createCameraIntent(){
意图cameraIntent =新意图(MediaStore.ACTION_IMAGE_CAPTURE);
文件externalDataDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM);
文件cameraDataDir =新的文件(externalDataDir.getAbsolutePath()+
文件分割符+浏览器的照片);
cameraDataDir.mkdirs();
mCameraFilePath = cameraDataDir.getAbsolutePath()+文件分割符+
System.currentTimeMillis的()+.JPG;
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(新文件(mCameraFilePath)));
返回cameraIntent;
}
私人意图createCamcorderIntent(){
返回新意图(MediaStore.ACTION_VIDEO_CAPTURE);
}
私人意图createSoundRecorderIntent(){
返回新意图(MediaStore.Audio.Media.RECORD_SOUND_ACTION); } } @覆盖
公共无效onBack pressed()
{
web视图的WebView =(的WebView)findViewById(R.id.webview);
如果(webView.canGoBack()){
webView.goBack();
}其他{
super.onBack pressed();
}
}}
下面是所有的Android版本,完整的解决方案,
进口的java.io.File;
进口的java.lang.reflect.Method;
进口的java.net.URL;进口android.app.Activity;
进口android.app.AlertDialog;
进口android.content.ActivityNotFoundException;
进口android.content.DialogInterface;
进口android.content.Intent;
进口android.net.Uri;
进口android.os.Bundle;
进口android.os.Environment;
进口android.provider.MediaStore;
进口android.view.View;
进口android.webkit.JsResult;
进口android.webkit.ValueCallback;
进口android.webkit.WebChromeClient;
进口android.webkit.WebSettings;
进口android.webkit.WebView;
进口android.webkit.WebSettings.PluginState;
进口android.widget.Toast;公共类MainActivity延伸活动{ @覆盖
公共无效的onCreate(捆绑savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.activity_main);
web视图的WebView =(的WebView)findViewById(R.id.webView1); initWebView(web视图);
webView.loadUrl(http://google.com); // TODO输入您的网址 } 私人最终静态对象methodInvoke(obj对象,字符串方法,类<> [] parameterTypes,对象[]参数){
尝试{
方法M = obj.getClass()实现getMethod(方法,新的Class [] {} boolean.class)。
m.invoke(OBJ,参数);
}赶上(例外五){
e.printStackTrace();
} 返回null;
} 私人无效initWebView(web视图的WebView){ WebSettings设置= webView.getSettings(); settings.setJavaScriptEnabled(真);
settings.setAllowFileAccess(真);
settings.setDomStorageEnabled(真);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
settings.setLoadWithOverviewMode(真);
settings.setUseWideViewPort(真);
settings.setSupportZoom(真);
// settings.setPluginsEnabled(真);
methodInvoke(设置setPluginsEnabled,新的Class [] {} boolean.class,新的对象[] {真});
// settings.setPluginState(PluginState.ON);
methodInvoke(设置setPluginState,新的Class [] {} PluginState.class,新的对象[] {PluginState.ON});
// settings.setPluginsEnabled(真);
methodInvoke(设置setPluginsEnabled,新的Class [] {} boolean.class,新的对象[] {真});
// settings.setAllowUniversalAccessFromFileURLs(真);
methodInvoke(设置setAllowUniversalAccessFromFileURLs,新的Class [] {} boolean.class,新的对象[] {真});
// settings.setAllowFileAccessFromFileURLs(真);
methodInvoke(设置setAllowFileAccessFromFileURLs,新的Class [] {} boolean.class,新的对象[] {真}); webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webView.clearHistory();
webView.clearFormData();
webView.clearCache(真); webView.setWebChromeClient(新MyWebChromeClient());
// webView.setDownloadListener(downloadListener);
} UploadHandler mUploadHandler; @覆盖
保护无效的onActivityResult(INT申请code,INT结果code,意图意图){ 如果(要求code == Controller.FILE_SELECTED){
//之所以选择从文件选择器中的文件。
如果(mUploadHandler!= NULL){
mUploadHandler.onResult(结果code,意向);
}
} super.onActivityResult(要求code,结果code,意向);
} 类MyWebChromeClient扩展WebChromeClient {
公共MyWebChromeClient(){ } 私人字符串getTitleFromUrl(字符串URL){
字符串title =网址;
尝试{
网址urlObj =新的URL(网址);
串主机= urlObj.getHost();
如果(主机=空&放大器;!&放大器;!host.isEmpty()){
返回urlObj.getProtocol()+://+主机;
}
如果(url.startsWith(文件)){
字符串文件名= urlObj.getFile();
如果(文件名= NULL&放大器;!&安培;!fileName.isEmpty()){
返回文件名;
}
}
}赶上(例外五){
// 忽视
} 返回称号;
} @覆盖
公共布尔onJsAlert(的WebView视图,URL字符串,字符串消息,最终的结果JsResult){
字符串newTitle的= getTitleFromUrl(URL); 新AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok,新DialogInterface.OnClickListener(){ @覆盖
公共无效的onClick(DialogInterface对话,诠释它){
result.confirm();
}
})setCancelable(假).create()显示()。
返回true;
//返回super.onJsAlert(查看,网址,邮件,结果);
} @覆盖
公共布尔onJsConfirm(的WebView视图,URL字符串,字符串消息,最终的结果JsResult){ 字符串newTitle的= getTitleFromUrl(URL); 新AlertDialog.Builder(MainActivity.this).setTitle(newTitle).setMessage(message).setPositiveButton(android.R.string.ok,新DialogInterface.OnClickListener(){ @覆盖
公共无效的onClick(DialogInterface对话,诠释它){
result.confirm();
}
})。setNegativeButton(android.R.string.cancel,新DialogInterface.OnClickListener(){
公共无效的onClick(DialogInterface对话,诠释它){
result.cancel();
}
})setCancelable(假).create()显示()。
返回true; //返回super.onJsConfirm(查看,网址,邮件,结果);
} //的Android 2.X
公共无效openFileChooser(ValueCallback<&乌里GT; uploadMsg){
openFileChooser(uploadMsg,);
} // Android 3.0的
公共无效openFileChooser(ValueCallback<&乌里GT; uploadMsg,弦乐acceptType){
openFileChooser(uploadMsg,,文件系统);
} //是Android 4.1
公共无效openFileChooser(ValueCallback<&乌里GT; uploadMsg,字符串acceptType,字符串捕获){
mUploadHandler =新UploadHandler(新控制器());
mUploadHandler.openFileChooser(uploadMsg,acceptType,捕捉);
}
}; 类控制器{
最终静态INT FILE_SELECTED = 4; 活性getActivity(){
返回MainActivity.this;
}
} //从Android的4.4.3_r1 / src目录/ COM /安卓/浏览器/ UploadHandler.java复制
////////////////////////////////////////////////// //////////////////// / *
*版权所有(C)2010年Android开源项目
*
*在Apache许可,2.0版(以下简称许可证);
*您不能使用这个文件除了在遵守许可。
*您可以在获得许可证的副本
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*除非适用法律要求或书面同意,软件
*许可下发布的分布在原样的基础,
*无担保或任何形式的条件,无论是前preSS或暗示的保证。
*请参阅许可证的特定语言的管理权限和
*根据许可证的限制。
* / //包com.android.browser;
//
//进口android.app.Activity;
//进口android.content.ActivityNotFoundException;
//进口android.content.Intent;
//进口android.net.Uri;
//进口android.os.Environment;
//进口android.provider.MediaStore;
//进口android.webkit.ValueCallback;
//进口android.widget.Toast;
//
//进口的java.io.File;
//进口java.util.Vector中;
//
// / **
// *从web视图处理文件上传这里的回调
// * /
//公共类UploadHandler { 类UploadHandler {
/ *
*用于通知文件的WebView上传的对象。
* /
私人ValueCallback<&乌里GT; mUploadMessage;
私人字符串mCameraFilePath;
私人布尔mHandled;
私人布尔mCaughtActivityNotFoundException;
私人控制器mController;
公共UploadHandler(控制器控制器){
mController =控制器;
}
串getFilePath(){
返回mCameraFilePath;
}
布尔处理(){
返回mHandled;
}
无效onResult(INT结果code,意图意图){
如果(结果code == Activity.RESULT_CANCELED&放大器;&安培; mCaughtActivityNotFoundException){
//无法解析一个活动,我们将再次尝试所以跳过
//这个结果。
mCaughtActivityNotFoundException = FALSE;
返回;
}
乌里结果=意图== NULL ||结果code!= Activity.RESULT_OK?空值
:intent.getData();
//当我们问相机来保存用户回吐的结果
//一张照片后,相机应用程序不返回任何其他
//比RESULT_OK。因此,我们需要检查文件是否我们的预期
//在的情况下写入到磁盘中,我们
//没有得到返回的意图,但确实得到了RESULT_OK。如果是,
//我们假设这个结果已经来自于相机背面。
如果(结果== NULL和放大器;&安培;意图== NULL和放大器;&安培;结果code == Activity.RESULT_OK){
文件cameraFile =新的文件(mCameraFilePath);
如果(cameraFile.exists()){
结果= Uri.fromFile(cameraFile);
//发送到我们有一个新的照片媒体扫描
//所以它会被添加到库的用户。
mController.getActivity()。sendBroadcast(
新意图(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,结果));
}
}
mUploadMessage.onReceiveValue(结果);
mHandled = TRUE;
mCaughtActivityNotFoundException = FALSE;
}
无效openFileChooser(ValueCallback<&乌里GT; uploadMsg,字符串acceptType,字符串捕获){
最后弦乐imageMimeType =图像/ *;
最后弦乐videoMimeType =视频/ *;
最后弦乐audioMimeType =音频/ *;
最后弦乐mediaSourceKey =捕获;
最后弦乐mediaSourceValueCamera =镜头;
最后弦乐mediaSourceValueFileSystem =文件系统;
最后弦乐mediaSourceValueCamcorder =摄像机
最后弦乐mediaSourceValueMicrophone =麦克风;
//根据规范,媒体源可以是文件系统或相机或摄像机
//或麦克风,默认值应该是文件系统。
字符串MEDIASOURCE = mediaSourceValueFileSystem;
如果(mUploadMessage!= NULL){
//已经是正在进行的文件选择操作。
返回;
}
mUploadMessage = uploadMsg;
//解析接受的类型。
串PARAMS [] = acceptType.split(;);
串mime类型=参数[0];
如果(capture.length()大于0){
MEDIASOURCE =捕捉;
}
如果(capture.equals(mediaSourceValueFileSystem)){
//为了保持与previous实现向后兼容
//媒体捕捉的API,如果'捕获'属性的值是
//文件系统,我们应该研究的接受式的MIME类型
//可以指定不同的捕获值。
对(串P:PARAMS){
串[]的keyValue = p.split(=);
如果(keyValue.length == 2){
//处理key = value的参数。
如果(mediaSourceKey.equals(的keyValue [0])){
MEDIASOURCE =的keyValue [1];
}
}
}
}
//确保它是不是还从previous上传设置。
mCameraFilePath = NULL;
如果(mimeType.equals(imageMimeType)){
如果(mediaSource.equals(mediaSourceValueCamera)){
//指定的图像/ *,并要求拍照,所以,尽管启动
//相机直接。
startActivity(createCameraIntent());
返回;
}其他{
//指定只是图像/ *',捕捉文件系统=,或无效的拍摄参数。
//在所有这些情况下,我们展示filetered在接受型传统选择器
//所以推出一个意图您的相机和图像/ *打开的两个。
意向选择器= createChooserIntent(createCameraIntent());
chooser.putExtra(Intent.EXTRA_INTENT,createOpenableIntent(imageMimeType));
startActivity(选配);
返回;
}
}否则如果(mimeType.equals(videoMimeType)){
如果(mediaSource.equals(mediaSourceValueCamcorder)){
//指定的视频/ *,并要求摄像机,所以,尽管启动
//摄像机直接。
startActivity(createCamcorderIntent());
返回;
}其他{
//指定只是视频/ *',捕获=文件系统或无效的拍摄参数。
//在所有这些情况下,我们显示了传统的文件选择器的意图,过滤
//在接受类型,以便发动意图为摄像机和视频/ *打开。
意向选择器= createChooserIntent(createCamcorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT,createOpenableIntent(videoMimeType));
startActivity(选配);
返回;
}
}否则如果(mimeType.equals(audioMimeType)){
如果(mediaSource.equals(mediaSourceValueMicrophone)){
//指定的音频/ *,并要求麦克风,所以,尽管推出的声音
//记录。
startActivity(createSoundRecorderIntent());
返回;
}其他{
//指定只是'音频/ *',捕获=无效捕捉参数的文件系统。
//在所有这些情况下,所以,尽管推出的意图为声音
//记录器和音频/ *打开。
意向选择器= createChooserIntent(createSoundRecorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT,createOpenableIntent(audioMimeType));
startActivity(选配);
返回;
}
}
//基于该接受类型没有特殊的处理是必要的,所以触发默认
//文件上传选择器。
startActivity(createDefaultOpenableIntent());
}
私人无效startActivity(意向意图){
尝试{
。mController.getActivity()startActivityForResult(意向,Controller.FILE_SELECTED);
}赶上(ActivityNotFoundException E){
//没有安装的应用程序能够处理的意图
//我们发送,因此退回到默认的文件上传控件。
尝试{
mCaughtActivityNotFoundException =真;
mController.getActivity()。startActivityForResult(createDefaultOpenableIntent(),
Controller.FILE_SELECTED);
}赶上(ActivityNotFoundException E2){
//没有什么能回报我们一个文件,这样的文件上传有效禁止。
Toast.makeText(mController.getActivity(),R.string.uploads_disabled,
Toast.LENGTH_LONG).show();
}
}
}
私人意图createDefaultOpenableIntent(){
//创建并使用默认打开的返回一个选择器
//行动,包括照相机,摄像机和声音
//记录(如有)。
意图I =新意图(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(* / *);
意向选择器= createChooserIntent(createCameraIntent(),createCamcorderIntent()
createSoundRecorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT,I);
返回选择器;
}
私人意图createChooserIntent(意向...意图){
意图选择器=新意图(Intent.ACTION_CHOOSER);
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS,意图);
chooser.putExtra(Intent.EXTRA_TITLE,
mController.getActivity()。getResources()
.getString(R.string.choose_upload));
返回选择器;
}
私人意图createOpenableIntent(字符串类型){
意图I =新意图(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(类型);
返回我;
}
私人意图createCameraIntent(){
意图cameraIntent =新意图(MediaStore.ACTION_IMAGE_CAPTURE);
文件externalDataDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM);
文件cameraDataDir =新的文件(externalDataDir.getAbsolutePath()+
文件分割符+浏览器的照片);
cameraDataDir.mkdirs();
mCameraFilePath = cameraDataDir.getAbsolutePath()+文件分割符+
System.currentTimeMillis的()+.JPG;
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(新文件(mCameraFilePath)));
返回cameraIntent;
}
私人意图createCamcorderIntent(){
返回新意图(MediaStore.ACTION_VIDEO_CAPTURE);
}
私人意图createSoundRecorderIntent(){
返回新意图(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
}
}
}
有关4.4.2使用此功能。这是一个演示应用程序的链接。下载并导入您的工作区。
http://applusform.com/down/AgateWebViewFileUpload_AndroidEclipse.zip
I have a web view, I add the code to upload files and it works well on 4.3 and 4.2 (galaxy s3) , but it doesn't work on 4.4.2 like galaxy s5 and lg3.
when I click on "choose file" it does not respond and nothing happens...
this my code.
MainActivity.java :
package com.com.myapplication;
/**
* Created by tadmitinteractive on 9/21/14.
*/
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
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.WebSettings.PluginState;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView webView = (WebView) findViewById(R.id.webview);
String url="http://www.ipets.co.il/wp-login.php";
initWebView(webView,url);
// 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 view, String url) {
WebSettings settings = view.getSettings();
final WebView myWebView = (WebView) findViewById(R.id.webview);
final ImageView imageView = (ImageView) findViewById(R.id.imageView);
view.setWebViewClient(new WebViewClient());
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 });
view.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
view.clearHistory();
view.clearFormData();
view.clearCache(true);
view.loadUrl(url);
view.setWebViewClient(new WebViewClient() {
ProgressDialog dialog = new ProgressDialog(MainActivity.this);
@Override
public void onPageStarted(WebView view, String url,
Bitmap favicon) {
// TODO Auto-generated method stub
dialog.setMessage("טוען...");
dialog.show();
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
myWebView.setVisibility(View.VISIBLE);
imageView.setVisibility(View.GONE);
dialog.dismiss();
super.onPageFinished(view, url);
}
});
view.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);
}
};
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);
}
}
@Override
public void onBackPressed()
{
WebView webView = (WebView) findViewById(R.id.webview);
if(webView.canGoBack()){
webView.goBack();
}else{
super.onBackPressed();
}
}
}
here is a full solution for all android versions,
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);
}
};
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);
}
}
}
For 4.4.2 Use this. This is a demo application link. download and import in your workspace. http://applusform.com/down/AgateWebViewFileUpload_AndroidEclipse.zip
这篇关于&QUOT;选择要上传的文件&QUOT;在Android版的WebView 4.4.2奇巧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!