4

From Android 4.1 to Android 4.3, you could subclass WebChromeClient on Android and implement the following (hidden, thus no @Override) method:

public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { ... }

You would open a file picker in that method, and when your Activity receives the result in onActivityResult(...), just call the single method that is available on the ValueCallback<Uri> instance with the file URI. That's it.

Unfortunately, this method was removed from the API in Android 4.4 and is not being called anymore.

Is there any way you can work around this, e.g. with reflection?

I mean, you could set an onclick="..." listener on the <input type="file"> element in HTML, which would still be called.

After intercepting the onclick="..." callback in Java (maybe via addJavascriptInterface(...)) you could open a file picker as usual. But the problem is that there's no ValueCallback<Uri> instance available that you could send your result (the file that was picked) to.

Setting the value="..." of the <input type="file"> in HTML manually is not possible, either, because it's read-only. But the WebView implementation itself can certainly write the value, obviously. So could you use reflection to set the value there or find another workaround?

I'm searching for a cleaner and more comfortable solution than detecting the <input type="file"> click (e.g. via its onclick="..." listener) and doing the file selection and file upload manually from Java. Enabling file uploads in the WebView, as they should work, would be cleaner, certainly.

caw
  • 30,999
  • 61
  • 181
  • 291
  • Well I think a lot of dev's want this in 4.4. Unfortunately no one seems to have an answer. There is one comment in https://code.google.com/p/android/issues/detail?id=62220, regarding adding an entry in proguard file, have you tried that, no idea if it works, although doesnt make a lot of sense anyway(not going the reflection way) – Vrashabh Irde Feb 03 '15 at 10:14
  • @Slartibartfast Thanks! This thread in the Google issue tracker doesn't have a solution, unfortunately. This is why I thought a more complex solution may be possible that wasn't covered there. The ProGuard hint is true, but only required if it works generally and you don't want ProGuard to break it. On 4.4, it doesn't work at all, so the ProGuard rule is useless. – caw Feb 03 '15 at 21:37
  • Hello @MarcoW. Did you find an easier way to handle `` ? Crosswalk is about 40-50 mb, and the other WebView alternatives are not stable. – osrl Jan 25 '16 at 18:02
  • @osrl No, I'm afraid you either have to include Crosswalk or accept that users on Android 4.4.x don't have file uploads (which I did). – caw Jan 25 '16 at 23:51
  • @MarcoW. Do you think ignoring 4.4.x users are a good choice? There are so many kitkat users. I think I will use `JavascriptInterface` choice, which is not a good choice either. – osrl Jan 26 '16 at 09:30
  • @osrl Only you can decide this for your own case ;) 36.1% of all users are still on KitKat: http://developer.android.com/about/dashboards/index.html – caw Jan 26 '16 at 10:10
  • It's about %60 of my users :) – osrl Jan 26 '16 at 10:13
  • In 2018: forget all these shits and check https://stackoverflow.com/a/31606758/3063226 – Heitor Jan 02 '18 at 06:25
  • @Heitor Everybody knows the solution for versions above 4.4. If you don’t care about the [13.4%](https://developer.android.com/about/dashboards/index.html) that are still on 4.4, go ahead, that’s fine. – caw Jan 02 '18 at 18:39
  • @caw that answer is supposed to deal from API 11 to 23, have you read it? – Heitor Jan 03 '18 at 19:37

1 Answers1

6

If you're looking for a clean solution to do this this without using tricky Javascript codes and detectors. I'd recommend using a Webview alternative.

Crosswalk
I'd recommend this. It'll work similar to the official webview. It's open source and made by the same people behind ChromeView. They've got a great setup guide: https://crosswalk-project.org/documentation/embedding_crosswalk.html

Check it out: https://crosswalk-project.org/

Chromium Webview
Also inspired by ChromeView. They claim to have integrated the same API's as the official webview for easy migration. But they indicate that the Webview still might be a bit unstable.

Check it out: https://github.com/mogoweb/chromium_webview

GeckoView
Made by Mozilla. Here's a demo project that uses it. Mozilla warns: "This is not a drop webview replacement and very unstable", but it has file upload

Check it out: https://wiki.mozilla.org/Mobile/GeckoView

If you're open on using Javascript (perhaps usefull for others) try:

Kitkat Webview
It uses javascript to enable file upload in KitKat webview do this. The demo allows you to upload an image, but you should be able to edit it to fit your needs.

Check it out: https://github.com/henrychuangtw/Kitkat-WebView

Community
  • 1
  • 1
Mdlc
  • 7,128
  • 12
  • 55
  • 98
  • Thanks! I'm aware of these alternatives and it's not as clean as using reflection (which might not be possible). But it's definitely a great general overview. By the way, "Chromium WebView" is a great idea (compatible API) but it describes itself as not ready for production. "KitKat WebView", on the other hand, is the least convenient solution and uses JavaScript, as you said. This is what I don't want, as described in the question, because *cannot* use real file uploads with that solution. You have to do it asynchronously via AJAX, for example. – caw Feb 05 '15 at 22:45
  • @Marco W. Edited my answer to better match your question and your findings on Chrome Webview. Even though they indicate it might not be ready for production (like to use it as a full webbrowser), it might be stable enough to use it for displaying simple webpages and upload forms. In all honesty I wouldn't say vanilla webview is the most reliable solution either ;) – Mdlc Feb 06 '15 at 07:39
  • beware that crosswalk adds a huge extra weight to your project (20 - 80mb) depending on your architecture. And Tint browser is a fork of Chromium Webview which doesn't seem to be working for postimg.com i just tested it on android 4.4.2 – MaggotSauceYumYum Apr 23 '16 at 11:22