`
king_tt
  • 浏览: 2268715 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Android开发心得——网页通过webview调用Android的图片或文件选择

 
阅读更多

本博文欢迎转载,转载请注明来自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)这个方法给写出来,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
abstractclassTestWebChromeClient extendsWebChromeClient
{
privateWebChromeClient mWrappedClient;
protectedTestWebChromeClient(WebChromeClient wrappedClient)
{
mWrappedClient = wrappedClient;
}
/** {@inheritDoc} */
@Override
publicvoidonProgressChanged(WebView view, intnewProgress)
{
mWrappedClient.onProgressChanged(view, newProgress);
}
/** {@inheritDoc} */
@Override
publicvoidonReceivedTitle(WebView view, String title)
{
mWrappedClient.onReceivedTitle(view, title);
}
/** {@inheritDoc} */
@Override
publicvoidonReceivedIcon(WebView view, Bitmap icon)
{
mWrappedClient.onReceivedIcon(view, icon);
}
/** {@inheritDoc} */
@Override
publicvoidonReceivedTouchIconUrl(WebView view, String url, booleanprecomposed)
{
mWrappedClient.onReceivedTouchIconUrl(view, url, precomposed);
}
/** {@inheritDoc} */
@Override
publicvoidonShowCustomView(View view, CustomViewCallback callback)
{
mWrappedClient.onShowCustomView(view, callback);
}
/** {@inheritDoc} */
@Override
publicvoidonHideCustomView()
{
mWrappedClient.onHideCustomView();
}
/** {@inheritDoc} */
@Override
publicbooleanonCreateWindow(WebView view, booleandialog, booleanuserGesture,
Message resultMsg)
{
returnmWrappedClient.onCreateWindow(view, dialog, userGesture, resultMsg);
}
/** {@inheritDoc} */
@Override
publicvoidonRequestFocus(WebView view)
{
mWrappedClient.onRequestFocus(view);
}
/** {@inheritDoc} */
@Override
publicvoidonCloseWindow(WebView window)
{
mWrappedClient.onCloseWindow(window);
}
/** {@inheritDoc} */
@Override
publicbooleanonJsAlert(WebView view, String url, String message, JsResult result)
{
returnmWrappedClient.onJsAlert(view, url, message, result);
}
/** {@inheritDoc} */
@Override
publicbooleanonJsConfirm(WebView view, String url, String message, JsResult result)
{
returnmWrappedClient.onJsConfirm(view, url, message, result);
}
/** {@inheritDoc} */
@Override
publicbooleanonJsPrompt(WebView view, String url, String message,
String defaultValue, JsPromptResult result)
{
returnmWrappedClient.onJsPrompt(view, url, message, defaultValue, result);
}
/** {@inheritDoc} */
@Override
publicbooleanonJsBeforeUnload(WebView view, String url, String message,
JsResult result)
{
returnmWrappedClient.onJsBeforeUnload(view, url, message, result);
}
/** {@inheritDoc} */
@Override
publicvoidonExceededDatabaseQuota(String url, String databaseIdentifier,
longcurrentQuota, longestimatedSize, longtotalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
mWrappedClient.onExceededDatabaseQuota(url, databaseIdentifier, currentQuota,
estimatedSize, totalUsedQuota, quotaUpdater);
}
/** {@inheritDoc} */
@Override
publicvoidonReachedMaxAppCacheSize(longspaceNeeded, longtotalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
mWrappedClient
.onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota, quotaUpdater);
}
/** {@inheritDoc} */
@Override
publicvoidonGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback)
{
mWrappedClient.onGeolocationPermissionsShowPrompt(origin, callback);
}
/** {@inheritDoc} */
@Override
publicvoidonGeolocationPermissionsHidePrompt()
{
mWrappedClient.onGeolocationPermissionsHidePrompt();
}
/** {@inheritDoc} */
@Override
publicbooleanonJsTimeout()
{
returnmWrappedClient.onJsTimeout();
}
/** {@inheritDoc} */
@Override
@Deprecated
publicvoidonConsoleMessage(String message, intlineNumber, String sourceID)
{
mWrappedClient.onConsoleMessage(message, lineNumber, sourceID);
}
/** {@inheritDoc} */
@Override
publicbooleanonConsoleMessage(ConsoleMessage consoleMessage)
{
returnmWrappedClient.onConsoleMessage(consoleMessage);
}
/** {@inheritDoc} */
@Override
publicBitmap getDefaultVideoPoster()
{
returnmWrappedClient.getDefaultVideoPoster();
}
/** {@inheritDoc} */
@Override
publicView getVideoLoadingProgressView()
{
returnmWrappedClient.getVideoLoadingProgressView();
}
/** {@inheritDoc} */
@Override
publicvoidgetVisitedHistory(ValueCallback<String[]> callback)
{
mWrappedClient.getVisitedHistory(callback);
}
/** {@inheritDoc} */
publicvoidopenFileChooser(ValueCallback<Uri> uploadFile)
{
((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile);
}
}
 

以上代码我是在eoe上发现的,并不是我自己参详发现的哈。但是原作是谁我就不知道了,因为这段代码你只要百度一下openFileChooser这个方法你就能找到。

当你这样写好,然后就是去设置WebChromeClient的时候了。设置方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mContentView.web_main_web.setWebChromeClient(newTestWebChromeClient(
newWebChromeClient())
{
publicvoidopenFileChooser(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的完整代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
abstractclassTestWebChromeClient extendsWebChromeClient
{
privateWebChromeClient mWrappedClient;
protectedTestWebChromeClient(WebChromeClient wrappedClient)
{
mWrappedClient = wrappedClient;
}
/** {@inheritDoc} */
@Override
publicvoidonProgressChanged(WebView view, intnewProgress)
{
mWrappedClient.onProgressChanged(view, newProgress);
}
/** {@inheritDoc} */
@Override
publicvoidonReceivedTitle(WebView view, String title)
{
mWrappedClient.onReceivedTitle(view, title);
}
/** {@inheritDoc} */
@Override
publicvoidonReceivedIcon(WebView view, Bitmap icon)
{
mWrappedClient.onReceivedIcon(view, icon);
}
/** {@inheritDoc} */
@Override
publicvoidonReceivedTouchIconUrl(WebView view, String url, booleanprecomposed)
{
mWrappedClient.onReceivedTouchIconUrl(view, url, precomposed);
}
/** {@inheritDoc} */
@Override
publicvoidonShowCustomView(View view, CustomViewCallback callback)
{
mWrappedClient.onShowCustomView(view, callback);
}
/** {@inheritDoc} */
@Override
publicvoidonHideCustomView()
{
mWrappedClient.onHideCustomView();
}
/** {@inheritDoc} */
@Override
publicbooleanonCreateWindow(WebView view, booleandialog, booleanuserGesture,
Message resultMsg)
{
returnmWrappedClient.onCreateWindow(view, dialog, userGesture, resultMsg);
}
/** {@inheritDoc} */
@Override
publicvoidonRequestFocus(WebView view)
{
mWrappedClient.onRequestFocus(view);
}
/** {@inheritDoc} */
@Override
publicvoidonCloseWindow(WebView window)
{
mWrappedClient.onCloseWindow(window);
}
/** {@inheritDoc} */
@Override
publicbooleanonJsAlert(WebView view, String url, String message, JsResult result)
{
returnmWrappedClient.onJsAlert(view, url, message, result);
}
/** {@inheritDoc} */
@Override
publicbooleanonJsConfirm(WebView view, String url, String message, JsResult result)
{
returnmWrappedClient.onJsConfirm(view, url, message, result);
}
/** {@inheritDoc} */
@Override
publicbooleanonJsPrompt(WebView view, String url, String message,
String defaultValue, JsPromptResult result)
{
returnmWrappedClient.onJsPrompt(view, url, message, defaultValue, result);
}
/** {@inheritDoc} */
@Override
publicbooleanonJsBeforeUnload(WebView view, String url, String message,
JsResult result)
{
returnmWrappedClient.onJsBeforeUnload(view, url, message, result);
}
/** {@inheritDoc} */
@Override
publicvoidonExceededDatabaseQuota(String url, String databaseIdentifier,
longcurrentQuota, longestimatedSize, longtotalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
mWrappedClient.onExceededDatabaseQuota(url, databaseIdentifier, currentQuota,
estimatedSize, totalUsedQuota, quotaUpdater);
}
/** {@inheritDoc} */
@Override
publicvoidonReachedMaxAppCacheSize(longspaceNeeded, longtotalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
mWrappedClient
.onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota, quotaUpdater);
}
/** {@inheritDoc} */
@Override
publicvoidonGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback)
{
mWrappedClient.onGeolocationPermissionsShowPrompt(origin, callback);
}
/** {@inheritDoc} */
@Override
publicvoidonGeolocationPermissionsHidePrompt()
{
mWrappedClient.onGeolocationPermissionsHidePrompt();
}
/** {@inheritDoc} */
@Override
publicbooleanonJsTimeout()
{
returnmWrappedClient.onJsTimeout();
}
/** {@inheritDoc} */
@Override
@Deprecated
publicvoidonConsoleMessage(String message, intlineNumber, String sourceID)
{
mWrappedClient.onConsoleMessage(message, lineNumber, sourceID);
}
/** {@inheritDoc} */
@Override
publicbooleanonConsoleMessage(ConsoleMessage consoleMessage)
{
returnmWrappedClient.onConsoleMessage(consoleMessage);
}
/** {@inheritDoc} */
@Override
publicBitmap getDefaultVideoPoster()
{
returnmWrappedClient.getDefaultVideoPoster();
}
/** {@inheritDoc} */
@Override
publicView getVideoLoadingProgressView()
{
returnmWrappedClient.getVideoLoadingProgressView();
}
/** {@inheritDoc} */
@Override
publicvoidgetVisitedHistory(ValueCallback<String[]> callback)
{
mWrappedClient.getVisitedHistory(callback);
}
/** {@inheritDoc} */
publicvoidopenFileChooser(ValueCallback<Uri> uploadFile)
{
((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile);
}
/** {@inheritDoc} */
publicvoidopenFileChooser(ValueCallback<Uri> uploadFile, String acceptType)
{
((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile, acceptType);
}
/** {@inheritDoc} */
publicvoidopenFileChooser(ValueCallback<Uri> uploadFile, String acceptType,
String capture)
{
((TestWebChromeClient) mWrappedClient).openFileChooser(uploadFile, acceptType,
capture);
}
}

一下是setWebChromeClient需要添加的方法。

1
2
3
4
5
6
7
8
9
10
publicvoidopenFileChooser(ValueCallback<Uri> uploadFile, String acceptType)
{
openFileChooser(uploadFile);
}
publicvoidopenFileChooser(ValueCallback<Uri> uploadFile, String acceptType,
String capture)
{
openFileChooser(uploadFile);
}

尽管前面很多部分都不难找到,但是后面这段3.0和4.0坑爹隐藏代码实在让人惨死。我当初都差点放弃了,国内论坛我还没有发现到关于这个描述,所以我就在这里分享一下,也当作是马克,省得以后忘记了。

这回终于不用再被骂娘了,感谢CCAV,感谢TVC,感谢老爸,感谢老妈,感谢老外。

分享到:
评论

相关推荐

    Android使用Html实现登录功能——重点掌握Webview js的使用

    这里,我们添加了一个表单,当用户点击登录按钮时,阻止表单的默认提交行为,而是通过JavaScript调用`window.android.onLogin()`方法,这个方法是在Android端定义的JavaScript接口。 为了实现JavaScript与Android的...

    Android下WebView中调用系统相机拍照范例

    在网页的JavaScript中,你可以通过`window.MyBrowserAPI.CapturePhoto`来调用Android端的方法。如上述`index.html`所示,当用户点击拍照按钮时,`TakePhoto`函数会被调用,它会调用`CapturePhoto`方法,并将返回的...

    Android APP使用WebView调用H5页面完成摄像头扫描二维码软件源码.rar

    在Android应用开发中,WebView是一个非常重要的组件,它允许开发者在APP内部加载并显示网页内容。这个源码示例展示了如何在WebView中调用H5页面,并利用Android原生的摄像头功能来扫描二维码,实现二维码识别。下面...

    安卓Android源码——BTWebViewSelection(webview选择文字).zip

    本资源“安卓Android源码——BTWebViewSelection(webview选择文字).zip”专注于讲解如何在Webview中实现文字的选择功能,这对于阅读类、资讯类应用或者任何需要用户进行文本操作的应用来说是必不可少的。...

    安卓Android源码——BTAndroidWebViewSelection(webview选择文字).7z

    如果项目中涉及到了JavaScript与Java的交互,那么可能使用了`WebView.addJavascriptInterface()`方法,将Java对象暴露给JavaScript,以便在网页中调用Android的API。同时,也可能使用`WebView.evaluateJavascript()...

    Android WebView H5调用拍照

    在Android应用开发中,WebView是一个非常重要的组件,它允许开发者在原生应用中展示网页内容。混合开发(Hybrid Development)结合了Web技术与原生应用的优势,使得开发者可以使用HTML5、CSS3和JavaScript来构建应用...

    Android webview调用相机和相册

    在Android应用开发中,WebView是一个非常重要的组件,它允许开发者在原生应用内展示网页内容。然而,随着用户对交互性需求的提升,单纯展示网页已经不能满足需求,因此,集成像调用系统相机和相册这样的原生功能就...

    Android使用WebView调用H5完成摄像头扫描二维码

    在Android应用开发中,WebView是一个非常重要的组件,它允许我们加载和显示网页内容。这篇教程将详细介绍如何在Android中利用WebView来调用H5页面,从而实现摄像头扫描二维码的功能。 首先,我们需要理解WebView的...

    安卓Android源码——BTAndroidWebViewSelection(webview选择文字).zip

    【标题】"安卓Android源码——BTAndroidWebViewSelection(webview选择文字)"涉及的核心知识点是Android系统中的WebView组件以及其对于文字选择和处理的功能。WebView是Android平台中用于显示网页内容的重要组件,...

    Android源码——BTAndroidWebViewSelection(webview选择文字).zip

    在Android开发中,WebView是一个非常重要的组件,它允许我们在应用程序中内嵌网页内容,并与网页进行交互。这个压缩包“Android源码——BTAndroidWebViewSelection(webview选择文字).zip”显然包含了针对WebView...

    Android通过WEBVIEW调用HTTPS

    在Android开发中,WebView是一个非常重要的组件,它允许我们在应用程序中内嵌网页内容,实现与网页的交互。当涉及到安全的网络通信时,HTTPS协议因其数据加密和身份验证特性成为首选。本文将深入探讨如何在Android...

    webview不能调用手机文件选择、相机和图库的问题demo

    在Android应用开发中,WebView是一个常见的组件,用于加载和显示网页内容。然而,在实际使用过程中,开发者时常会遇到WebView无法调用手机上的文件选择器、相机以及图库功能的问题。这些问题通常涉及到Android权限...

    安卓Android源码——BTAndroidWebViewSelection(webview选择文字).rar

    在Android开发中,WebView是一个非常重要的组件,它允许开发者在应用程序中内嵌网页内容。这个项目“BTAndroidWebViewSelection”专注于WebView中的文本选择功能,这在许多应用中都有所需求,比如阅读器、浏览器或者...

    Android webview调用摄像头扫描二维码

    Webview是Android SDK提供的一种视图组件,它能够加载和显示网页内容。在Android Studio中创建一个新的项目,我们需要在布局XML文件(如activity_main.xml)中添加一个WebView元素: ```xml &lt;WebView android:id=...

    Android原生WebView与网页js相互调用

    在Android开发中,WebView是一个非常重要的组件,它允许我们在应用程序中加载和显示HTML内容,从而实现类似网页的应用体验。本文将深入探讨如何在Android原生的WebView中与嵌入的JavaScript进行交互,使得两者可以...

    安卓Android源码——android通过js调用安卓系统功能.rar

    这个压缩包“安卓Android源码——android通过js调用安卓系统功能.rar”似乎包含了关于如何实现这一功能的示例代码和截图。下面,我们将详细讨论如何在Android应用中通过JavaScript调用安卓系统的功能。 首先,我们...

    Android开发WebView获取SD卡图片并显示

    在Android应用开发中,WebView是一个非常重要的组件,它允许开发者在应用程序内嵌入网页内容,实现类似浏览器的功能。本文将详细讲解如何在Android的WebView中加载并显示SD卡上的图片,以及如何解决自Android 4.4...

    android webview调用系统相机和图库

    android webview调用系统相机和图库支持5.0通过了小米2s(android5.0.2)小米4(android 4.4.4)还有LG的nexus(android 5.0)的测试,在三星GT-I9300I(android 4.3 在这款手机上测试的时候,拍照后有的时候在...

Global site tag (gtag.js) - Google Analytics