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)这个方法给写出来,代码如下:

 

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 TestWebChromeClientextends 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 TestWebChromeClientextends 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 0