Android开发心得——网页通过webview调用Android的图片或文件选择
来源:互联网 发布:企业网软件下载 编辑:程序博客网 时间:2024/05/17 23:05
本博文欢迎转载,转载请注明来自http://www.cnblogs.com/qinxianyuzou/
前段时间因为客户需求,做一个客户端结合web微网站的应用。其中,这个应用设计到了要修改头像,但是这个页面却是在微网站上实现的,意味着网站要调用到Android的打开文件的方法,那么这个通过webview是怎么实现的呢?
经过跟服务器的同事讨论发现,方法都是跟pc上是一样的,都是调用一个叫input type=file的属性,于是我就开始找,webview是怎么响应这个属性的了。
于是翻网站找到资料,不难查到,想要适用php上调用打开文件的方法,webview就要重写一个名为openFileChooser的方法。
但是这个方法的使用却不简单,这个方法是要调用webview的setWebChromeClient方法,然后重写一个WebChromeClient类。来到这一步,相信有点开发经验的同行都不难解决。问题的关键就在于,当你重写WebChromeClient这个类的时候会发现,根本就没有openFileChooser这个方法,那要怎么重写呢?是不是意味着这个方法其实行不通?于是再次翻查资料,发现原来这个方法居然是隐藏方法,并不不存在显性的继承重写关系。
最后,我发现要使用这个方法,还得自己继承WebChromeClient这个类把openFileChooser(ValueCallback<Uri> uploadFile)这个方法给写出来,代码如下:
abstract
class
TestWebChromeClient
extends
WebChromeClient
{
private
WebChromeClient mWrappedClient;
protected
TestWebChromeClient(WebChromeClient wrappedClient)
{
mWrappedClient = wrappedClient;
}
/** {@inheritDoc} */
@Override
public
void
onProgressChanged(WebView view,
int
newProgress)
{
mWrappedClient.onProgressChanged(view, newProgress);
}
/** {@inheritDoc} */
@Override
public
void
onReceivedTitle(WebView view, String title)
{
mWrappedClient.onReceivedTitle(view, title);
}
/** {@inheritDoc} */
@Override
public
void
onReceivedIcon(WebView view, Bitmap icon)
{
mWrappedClient.onReceivedIcon(view, icon);
}
/** {@inheritDoc} */
@Override
public
void
onReceivedTouchIconUrl(WebView view, String url,
boolean
precomposed)
{
mWrappedClient.onReceivedTouchIconUrl(view, url, precomposed);
}
/** {@inheritDoc} */
@Override
public
void
onShowCustomView(View view, CustomViewCallback callback)
{
mWrappedClient.onShowCustomView(view, callback);
}
/** {@inheritDoc} */
@Override
public
void
onHideCustomView()
{
mWrappedClient.onHideCustomView();
}
/** {@inheritDoc} */
@Override
public
boolean
onCreateWindow(WebView view,
boolean
dialog,
boolean
userGesture,
Message resultMsg)
{
return
mWrappedClient.onCreateWindow(view, dialog, userGesture, resultMsg);
}
/** {@inheritDoc} */
@Override
public
void
onRequestFocus(WebView view)
{
mWrappedClient.onRequestFocus(view);
}
/** {@inheritDoc} */
@Override
public
void
onCloseWindow(WebView window)
{
mWrappedClient.onCloseWindow(window);
}
/** {@inheritDoc} */
@Override
public
boolean
onJsAlert(WebView view, String url, String message, JsResult result)
{
return
mWrappedClient.onJsAlert(view, url, message, result);
}
/** {@inheritDoc} */
@Override
public
boolean
onJsConfirm(WebView view, String url, String message, JsResult result)
{
return
mWrappedClient.onJsConfirm(view, url, message, result);
}
/** {@inheritDoc} */
@Override
public
boolean
onJsPrompt(WebView view, String url, String message,
String defaultValue, JsPromptResult result)
{
return
mWrappedClient.onJsPrompt(view, url, message, defaultValue, result);
}
/** {@inheritDoc} */
@Override
public
boolean
onJsBeforeUnload(WebView view, String url, String message,
JsResult result)
{
return
mWrappedClient.onJsBeforeUnload(view, url, message, result);
}
/** {@inheritDoc} */
@Override
public
void
onExceededDatabaseQuota(String url, String databaseIdentifier,
long
currentQuota,
long
estimatedSize,
long
totalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
mWrappedClient.onExceededDatabaseQuota(url, databaseIdentifier, currentQuota,
estimatedSize, totalUsedQuota, quotaUpdater);
}
/** {@inheritDoc} */
@Override
public
void
onReachedMaxAppCacheSize(
long
spaceNeeded,
long
totalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
mWrappedClient
.onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota, quotaUpdater);
}
/** {@inheritDoc} */
@Override
public
void
onGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback)
{
mWrappedClient.onGeolocationPermissionsShowPrompt(origin, callback);
}
/** {@inheritDoc} */
@Override
public
void
onGeolocationPermissionsHidePrompt()
{
mWrappedClient.onGeolocationPermissionsHidePrompt();
}
/** {@inheritDoc} */
@Override
public
boolean
onJsTimeout()
{
return
mWrappedClient.onJsTimeout();
}
/** {@inheritDoc} */
@Override
@Deprecated
public
void
onConsoleMessage(String message,
int
lineNumber, String sourceID)
{
mWrappedClient.onConsoleMessage(message, lineNumber, sourceID);
}
/** {@inheritDoc} */
@Override
public
boolean
onConsoleMessage(ConsoleMessage consoleMessage)
{
return
mWrappedClient.onConsoleMessage(consoleMessage);
}
/** {@inheritDoc} */
@Override
public
Bitmap getDefaultVideoPoster()
{
return
mWrappedClient.getDefaultVideoPoster();
}
/** {@inheritDoc} */
@Override
public
View getVideoLoadingProgressView()
{
return
mWrappedClient.getVideoLoadingProgressView();
}
/** {@inheritDoc} */
@Override
public
void
getVisitedHistory(ValueCallback<String[]> callback)
{
mWrappedClient.getVisitedHistory(callback);
}
/** {@inheritDoc} */
public
void
openFileChooser(ValueCallback<Uri> uploadFile)
{
((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile);
}
}
以上代码我是在eoe上发现的,并不是我自己参详发现的哈。但是原作是谁我就不知道了,因为这段代码你只要百度一下openFileChooser这个方法你就能找到。
当你这样写好,然后就是去设置WebChromeClient的时候了。设置方法如下:
mContentView.web_main_web.setWebChromeClient(
new
TestWebChromeClient(
new
WebChromeClient())
{
public
void
openFileChooser(ValueCallback<Uri> uploadFile)
{
if
(mUploadMessage !=
null
)
return
;
mUploadMessage = uploadFile;
//自己写你的调用图片方法,我这里是封装了调用图片的方法的
//关键点在于这个mUploadMessage参数,获取到图片以后传给这个参数回去就可以了。
//具体用法百度一下就有。
Select_Activity.start(mContext,mUploadMessage,indexUrlString,FILE_SELECTED);
}
});
当你设置完后,这个时候你就该兴高采烈地去测试了。
于是,你有可能会兴高采烈地发现,不行!!完全没有反应!
是不是开始怀疑这个方法是坑人的?是不是在努力骂撸主?来来来,别生气,让我告诉你真相。
我告诉你哦,这个方法其实一点都不吭人,真的可以啊,不过~这是在3.0以前的sdk上有效...但是现在的主流Android机基本都是4.0以上了,哪里还有3.0以前的系统?
于是你又开始了新的一轮骂娘,为什么我会知道?因为我那个时候也是这个反应!
那时候我努力地翻资料,把百度、eoe、CSDN、德问、博客园、安卓巴士、DEVDIV都翻烂了,终于找到了原因,原来泥煤的3.0的要多加一个参数才能生效!
于是我傻乎乎的仿照人家重写的openFileChooser方法,给TestWebChromeClient这个类添加了一个openFileChooser(ValueCallback<Uri> uploadFile, String acceptType)方法。(具体这个acceptType参数有什么用,我还不怎么清楚,有知道的大神麻烦告知一下哈)在webview的setWebChromeClient方法里也添加了一个对应调用方法。
于是新一轮测试又开始了。
终于,你又一次兴高采烈地骂娘了,泥煤的还是不行啊!(po主:喂!别打头,把我打傻了以后就不能分享技术了!)
于是,我终于相信了国内搜索引擎和论坛的不靠谱,我投靠了谷歌和stackoverflow。
说实话,po主的英文很烂,烂得掉渣了,只有小学5年级的水准(po主那个时候是四年纪开始学的英语)所以不到逼不得已都不想投靠外国网站,实在是看不到,这搜索不来啊!
我找了足足一天得谷歌,最后通过谷歌找到了stackoverflow上有这个相同的问题(我这英文的水平只能通过谷歌使用了,捂脸)
人家大神解答到,原来尼玛的4.0以后的版本又多了一个参数于是乎,再加一个openFileChooser(ValueCallback<Uri> uploadFile, String acceptType,String capture)方法就可以了。
下面我贴上TestWebChromeClient的完整代码。
abstract
class
TestWebChromeClient
extends
WebChromeClient
{
private
WebChromeClient mWrappedClient;
protected
TestWebChromeClient(WebChromeClient wrappedClient)
{
mWrappedClient = wrappedClient;
}
/** {@inheritDoc} */
@Override
public
void
onProgressChanged(WebView view,
int
newProgress)
{
mWrappedClient.onProgressChanged(view, newProgress);
}
/** {@inheritDoc} */
@Override
public
void
onReceivedTitle(WebView view, String title)
{
mWrappedClient.onReceivedTitle(view, title);
}
/** {@inheritDoc} */
@Override
public
void
onReceivedIcon(WebView view, Bitmap icon)
{
mWrappedClient.onReceivedIcon(view, icon);
}
/** {@inheritDoc} */
@Override
public
void
onReceivedTouchIconUrl(WebView view, String url,
boolean
precomposed)
{
mWrappedClient.onReceivedTouchIconUrl(view, url, precomposed);
}
/** {@inheritDoc} */
@Override
public
void
onShowCustomView(View view, CustomViewCallback callback)
{
mWrappedClient.onShowCustomView(view, callback);
}
/** {@inheritDoc} */
@Override
public
void
onHideCustomView()
{
mWrappedClient.onHideCustomView();
}
/** {@inheritDoc} */
@Override
public
boolean
onCreateWindow(WebView view,
boolean
dialog,
boolean
userGesture,
Message resultMsg)
{
return
mWrappedClient.onCreateWindow(view, dialog, userGesture, resultMsg);
}
/** {@inheritDoc} */
@Override
public
void
onRequestFocus(WebView view)
{
mWrappedClient.onRequestFocus(view);
}
/** {@inheritDoc} */
@Override
public
void
onCloseWindow(WebView window)
{
mWrappedClient.onCloseWindow(window);
}
/** {@inheritDoc} */
@Override
public
boolean
onJsAlert(WebView view, String url, String message, JsResult result)
{
return
mWrappedClient.onJsAlert(view, url, message, result);
}
/** {@inheritDoc} */
@Override
public
boolean
onJsConfirm(WebView view, String url, String message, JsResult result)
{
return
mWrappedClient.onJsConfirm(view, url, message, result);
}
/** {@inheritDoc} */
@Override
public
boolean
onJsPrompt(WebView view, String url, String message,
String defaultValue, JsPromptResult result)
{
return
mWrappedClient.onJsPrompt(view, url, message, defaultValue, result);
}
/** {@inheritDoc} */
@Override
public
boolean
onJsBeforeUnload(WebView view, String url, String message,
JsResult result)
{
return
mWrappedClient.onJsBeforeUnload(view, url, message, result);
}
/** {@inheritDoc} */
@Override
public
void
onExceededDatabaseQuota(String url, String databaseIdentifier,
long
currentQuota,
long
estimatedSize,
long
totalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
mWrappedClient.onExceededDatabaseQuota(url, databaseIdentifier, currentQuota,
estimatedSize, totalUsedQuota, quotaUpdater);
}
/** {@inheritDoc} */
@Override
public
void
onReachedMaxAppCacheSize(
long
spaceNeeded,
long
totalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
mWrappedClient
.onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota, quotaUpdater);
}
/** {@inheritDoc} */
@Override
public
void
onGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback)
{
mWrappedClient.onGeolocationPermissionsShowPrompt(origin, callback);
}
/** {@inheritDoc} */
@Override
public
void
onGeolocationPermissionsHidePrompt()
{
mWrappedClient.onGeolocationPermissionsHidePrompt();
}
/** {@inheritDoc} */
@Override
public
boolean
onJsTimeout()
{
return
mWrappedClient.onJsTimeout();
}
/** {@inheritDoc} */
@Override
@Deprecated
public
void
onConsoleMessage(String message,
int
lineNumber, String sourceID)
{
mWrappedClient.onConsoleMessage(message, lineNumber, sourceID);
}
/** {@inheritDoc} */
@Override
public
boolean
onConsoleMessage(ConsoleMessage consoleMessage)
{
return
mWrappedClient.onConsoleMessage(consoleMessage);
}
/** {@inheritDoc} */
@Override
public
Bitmap getDefaultVideoPoster()
{
return
mWrappedClient.getDefaultVideoPoster();
}
/** {@inheritDoc} */
@Override
public
View getVideoLoadingProgressView()
{
return
mWrappedClient.getVideoLoadingProgressView();
}
/** {@inheritDoc} */
@Override
public
void
getVisitedHistory(ValueCallback<String[]> callback)
{
mWrappedClient.getVisitedHistory(callback);
}
/** {@inheritDoc} */
public
void
openFileChooser(ValueCallback<Uri> uploadFile)
{
((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile);
}
/** {@inheritDoc} */
public
void
openFileChooser(ValueCallback<Uri> uploadFile, String acceptType)
{
((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile, acceptType);
}
/** {@inheritDoc} */
public
void
openFileChooser(ValueCallback<Uri> uploadFile, String acceptType,
String capture)
{
((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile, acceptType,
capture);
}
}
一下是setWebChromeClient需要添加的方法。
public
void
openFileChooser(ValueCallback<Uri> uploadFile, String acceptType)
{
openFileChooser(uploadFile);
}
public
void
openFileChooser(ValueCallback<Uri> uploadFile, String acceptType,
String capture)
{
openFileChooser(uploadFile);
}
尽管前面很多部分都不难找到,但是后面这段3.0和4.0坑爹隐藏代码实在让人惨死。我当初都差点放弃了,国内论坛我还没有发现到关于这个描述,所以我就在这里分享一下,也当作是马克,省得以后忘记了。
这回终于不用再被骂娘了,感谢CCAV,感谢TVC,感谢老爸,感谢老妈,感谢老外。
- Android开发心得——网页通过webview调用Android的图片或文件选择
- 网页通过webview调用Android的图片或文件选择
- 网页通过webview调用Android的图片或文件选择
- 在Android中通过WebView调用相机拍照/选择文件
- Android WebView 网页实现选择文件
- Android WebView 选择图片并上传(调用相机拍照/相册/选择文件)
- Android 调用相册或相机选择图片
- 在Android浏览器中通过WebView调用相机拍照/选择文件 上传到服务器
- 在Android浏览器中通过WebView调用相机拍照/选择文件 上传到服务器
- Android WebView选择文件
- android开发 通过拍照或选择本地图片并剪裁图片设置成头像
- android 通过WebView显示网页
- android中自定义WebView显示网页或本地html文件
- android中自定义WebView显示网页或本地html文件
- android开发 之 android和js通过WebView调用
- android WebView的网页上传文件
- Android开发——相册拍照_02.将拍照得到或相册中选择的图片显示在ImageView中
- Android调用相机或选择相册后加载图片内存不足
- Django负载均衡session共享
- JQuery返回Json日期格式的問題 jquery对时间/Date(1387900800000)进行处理
- 不同需求影响架构的原理不同
- 用adblock过滤页面上固定位置的悬浮窗
- 什么是stream?
- Android开发心得——网页通过webview调用Android的图片或文件选择
- android系统中sendevent的妙用
- modem是什么
- [Ext.Net]TreePanel 异步加载数据
- 复习笔记之三--内核对象线程同步---事件
- 顺序栈实现
- 论计算机语言
- myeclipse 85 js插件安装
- DBCC大全集之(适用版本MS SQLServer 2008 R2)----DBCC DBREINDEX对指定数据库中的表重新生成一个或多个索引