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
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的时候了。设置方法如下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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的完整代码。

 

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
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需要添加的方法。

 

1
2
3
4
5
6
7
8
9
10
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,感谢老爸,感谢老妈,感谢老外。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值