WebView open Camera, file selector problems and workarounds

Source: Internet
Author: User
Tags deprecated

In recent years, front-end development is getting more and more fire, H5 page development of mobile page even took my native development half of the meaning of sadness. But from the actual situation, H5 a set of code running around features, our Android, IOS ... Also can only hehe. However, I still prefer the native application, the network quality requirements are low, after the H5 page load does not come out a blank will not be crazy! The Spit groove belongs to The spit groove, the matter cannot fall.

2 ways to tune the camera and the ones you know are not adverbial clauses: Know the pit completed the intention to adjust the system camera, the results of processing and some problems of the response. In fact the previous article is still because the theme of today's Web view calls the camera system- and since it involves calling the camera itself some of the problems are not very clear before , so specifically engaged in a bit, recorded, So if you have any questions or problems calling the camera operation itself , please Click to jump to the previous email to find out the answer, this is not repeated. Let's take a look at some of the problems with calling the camera in WebView.

Problem Description

Recently, there is a need to upload a positive and negative photo ID, said simple, but this part of the business is H5 page processing, so only through the H5 page to take pictures or choose local pictures, but the problem-this section of H5 code in the browser open can realize the function, but placed in the webview but no action.

<! DOCTYPE html>

Run normally in the browser:

according to the previous description, because this part of the Android source block, you need to webview.setwebchromeclient (new Webchromeclient ()) to rewrite the webchromeclient Openfilechooser () and so on, then we open the source to see.

Source Analysis

See the source code is the most direct and most effective way to meet the problem , although reading the source code is usually more difficult than looking at some of the online posts. , but it is the root of the problem. May sometimes encounter a lot of problems do not know specifically from the source, at this time can only use the problem to Baidu, Google went to, to see how predecessors are how to solve this problem , encountered in the source when the return to the back, This will be a profound understanding of the problem itself; Speaking of this, a recommended in English to view the source of the version of the address , after all, you will not download all versions of the source code . Gossip Less, it is said that different versions are not the same, that one look (Webchromeclient.java in the \ Robot \ WebKit Package ):

(Android 2.2) 8 <= API <= (Android 2.3)

take version 2.3.7_r1 (API 10) as an example ( There is no such method when API <8 ):

as you can see, the Openfilechooser () method is used to tell the client to open a file selector, and only one parameter Valuecallback object UPLOADMSG,UPLOADMSG is a callback value that sets the URI of the file to be uploaded. Use the Onreceivevalue () method to wake up the waiting thread (English is not good, no offense), and the method is hidden .

(Android 3.0) <= API <= (Android 4.0.3)

Take version 2.3.7_r1 (API 15) as an example:

as you can see, the method is also Hidden , but the Openfilechooser () method is more than the previous version. The accepted attribute value of the file selector setting for the input label declaration on the ACCEPTTYPE,H5 page is the line in the top H5 code:

<input type= "file" id= "pic" name= "camera" accept= "image/*" onchange= "Previewphoto (this.id, ' img ');" />

  

(Android 4.1.2) <= API <= (android 4.4w.2)

Take version 4.4W (API 20) as an example:

  

/** * Tell the client to open a file chooser. * @param uploadfile A valuecallback to set the URI of the file to upload.  *      Onreceivevalue must is called to wake up the THREAD.A * @param accepttype The value of the ' accept ' attribute of the Input tag *         associated with this file picker. * @param capture the value of the ' capture ' attribute of the input tag  *         associated with this file picker. * @hide */public void Openfilechooser (valuecallback<uri> uploadfile, String Accepttype, String capture) {    uploadfile.onreceivevalue (null);}

  

also has @hide The tag is more than the previous version of a string into the parameter capture, the same name as the input Tag property value (used to specify the device such as Capture = "camera", but it seems to use very little).

api> = (Android 5.0.1)

Take version 5.0 (API 21) as an example:

/** * Tell the client to open a file chooser. * @param uploadfile A valuecallback to set the URI of the file to upload.  *      Onreceivevalue must is called to wake up the THREAD.A * @param accepttype The value of the ' accept ' attribute of the Input tag *         associated with this file picker. * @param capture the value of the ' capture ' attribute of the input tag *         associated with this file picker. * * @deprecated use {@link #showFileChooser} instead. * @hide This method is not Published in any SDK version. */@Deprecatedpublic void Openfilechooser (valuecallback<uri> uploadfile, String accepttype, string capture) {    uploadfile.onreceivevalue (null);}

  before the @hide I don't know what to do with it, but here's the explanation--this method is not published in any SDK version, that is, the method is not public, so it will not be the same as other common methods of override, how to do? Said behind.
Also, this method has been marked by @deprecated, using a new method Showfilechooser () replaced, then I'll look for Showfilechooser:

/** * Tell the client to show a file chooser. * * This is called-handle HTML forms with ' file ' input type, in response to the * user pressing the "Select File" Butto N. * To cancel the request, call <code>filepathcallback.onreceivevalue (NULL) </code> and * return true. * * @param webView The WebView instance is initiating the request. * @param filepathcallback Invoke This callback to supply the list of paths to files to upload, * o R NULL to cancel. Must only be called if the * <code>showFileChooser</code> implementations returns True . * @param Filechooserparams describes the mode of file Chooser to being opened, and options to being * u Sed with it. * @return True if filepathcallback'll is invoked, false to use default handling. * * @see filechooserparams */public boolean onshowfilechooser (WebView WebView, valuecallback<uri[]> Filepathcallback, Filechooserparams FilechooserparAMS) {return false;} 

  

Look, this note is very attentive. The Onshowfilechooser () method and Openfilechooser () have the same effect, but have a more detailed explanation-

    • This method is used to process the declaration in an HTML form type = "File" the input tag, the response time the user presses the "Select File" button
    • If you want to cancel the operation (select a file operation), you need to call filepathcallback.onreceivevalue (empty); returns true;
    • Meaning of the return value: Returns true to recognize the filepathcallback operation that is overridden in the method, and returns false to indicate that the default processing is used (that is, empty methods, without any processing)

parameter filepathcallback Generic is changed from a URI to a URI [] , the description can support the selection of multiple files at once (of course, the call system camera directly photographed or only one shot, at this time the URI [] only 1 people, If you choose from the album or file system, you should be able to choose more (I do not now, I dare not say yes) );

Parameters Filechooserparams Filechooserparams should and the original is a truth, is the input tag attribute collection, you can look at the source code:

/** * Parameters used in the {@link #onShowFileChooser} method. */public static abstract class Filechooserparams {/** Open single file. Requires that the file exists before allowing the user to pick it.    */public static final int mode_open = 0; /** like Open and allows multiple files to be selected.    */public static final int mode_open_multiple = 1; /** like Open and allows a folder to be selected.        The implementation should enumerate all files selected by this operation.        This feature was not supported at the moment.    @hide */public static final int mode_open_folder = 2; /** allows picking a nonexistent file and saving it.    */public static final int mode_save = 3; /** * Parse The result returned by the file picker activity. This method should is used with * {@link #createIntent}.     Refer to {@link #createIntent}-for-to-use it.     * * @param resultcode The integer result code returned by the file picker activity. * @paraM data The intent returned by the file picker activity. * @return The Uris of selected file (s) or null if the ResultCode indicates * activity canceled or any other ER     Ror. */public static uri[] Parseresult (int resultcode, Intent data) {return Webviewfactory.getprovider (). getstatics    (). Parsefilechooserresult (ResultCode, data);     }/** * Returns file chooser mode.    */Public abstract int getmode (); /** * Returns An array of acceptable MIME types. The returned MIME type * could be partial such as audio/*.     The array would be empty if no * acceptable types is specified.    */public abstract string[] Getaccepttypes ();     /** * Returns preference for a live media captured value (e.g. Camera, microphone).     * True indicates capture is enabled, false disabled.     * Use <code>getAcceptTypes</code> to determine suitable capture devices.    */Public abstract Boolean iscaptureenabled (); /** * ReturnThe title of S to is use for this file selector, or null.     IF NULL a default * title should be used.    */Public abstract charsequence getTitle ();     /** * The file name of a default selection if specified, or null.    */Public abstract String getfilenamehint ();     /** * Creates an intent, would start a file picker for file selection. * The Intent supports choosing files from simple file sources available * on the device. Some Advanced sources (for example, live media capture) * Could not is supported and applications wishing to support the     SE sources * or more advanced file operations should build their own Intent. * * <pre> * How to use: * 1. Build an intent using {@link #createIntent} * 2.     Fire the intent using {@link Android.app.activity#startactivityforresult}. * 3.     Check for Activitynotfoundexception and take a user friendly action if thrown. * 4. Listen the result using {@link Android.app.activity#onactivityresult} * 5.     Parse the result using {@link #parseResult} only if media capture is not requested. * 6.  Send the result using filepathcallback of {@link Webchromeclient#onshowfilechooser} * </pre> * * @return     An Intent that supports basic file chooser sources. */Public abstract Intent createintent ();}

  

There are comments, not explanations.

Solutions

after reading the source of everything is clear, how to do, rewrite the above methods are good. But @hide method can not override what to do-simple rude, direct write (no code hint is not a little guilty?) When it runs out, there is no heart.) In order to be compatible with all versions, it is best to write the Openfilechooser () method with different 3 parameters, Onshowfilechooser () normal override is good:

Webview.setwebchromeclient (New Webchromeclient () {/** * 8 (Android 2.2) <= API <= (Android 2.3) Callback this method */        public void Openfilechooser (valuecallback<uri> uploadmsg) {log.e ("Wangj", "Run Method OpenFileChooser-1");        (2) When the method callback is described in version API < 21, the result is assigned to Muploadcallbackbelow, so that this = null Muploadcallbackbelow = uploadmsg;    Takephoto (); }/** * One (Android 3.0) <= API <= (Android 4.0.3) Callback This method */public void Openfilechooser (valuecallback& Lt        Uri> uploadmsg, String accepttype) {log.e ("Wangj", "Run Method OpenFileChooser-2 (accepttype:" + Accepttype + ")");    Openfilechooser (UPLOADMSG); }/** * (Android 4.1.2) <= API <= (Android 4.4w.2) Callback This method */public void Openfilechooser (Valuecallba  Ck<uri> uploadmsg, String accepttype, String capture) {LOG.E ("Wangj", "Run Method openFileChooser-3 (accepttype:") + Accepttype + ";        Capture: "+ Capture +");    Openfilechooser (UPLOADMSG);   } /** * API >= (Android 5.0.1) Callback This method */@Override public boolean onshowfilechooser (WebView WebView, Value Callback<uri[]> Filepathcallback, Filechooserparams filechooserparams) {log.e ("WangJ", "Run method OnShowFileChoos        Er ");        (1) The method callback when the version of API >= 21, the result is assigned to Muploadcallbackabovel, so that it = null muploadcallbackabovel = Filepathcallback;        Takephoto ();    return true; }});/* Omit other content *//** * Call camera */private void Takephoto () {//Specify the way the camera is stored. String FilePath = environment.getexternal    Storagedirectory () + file.separator + environment.directory_pictures + file.separator;    String fileName = "Img_" + Dateformat.format ("Yyyymmdd_hhmmss", Calendar.getinstance (Locale.china)) + ". jpg";    Imageuri = Uri.fromfile (new File (FilePath + fileName));    Intent Intent = new Intent (mediastore.action_image_capture);    Intent.putextra (Mediastore.extra_output, Imageuri);    Startactivityforresult (Intent, Request_code); Select pictures (excluding camera photos),You do not have to succeed after the broadcast of the Refresh gallery//Intent i = new Intent (intent.action_get_content);//I.addcategory (intent.category_openable) ;//I.settype ("image/*");//Startactivityforresult (Intent.createchooser (i, "image Chooser"), Request_code);} @Overrideprotected void Onactivityresult (int requestcode, int resultcode, Intent data) {Super.onactivityresult (Request    Code, ResultCode, data); if (Requestcode = = Request_code) {//via Top (1), (2) Two assignment operations, here you can decide which processing method to use if the value is empty (muploadcallbackbelow! =        NULL) {Choosebelow (ResultCode, data);        } else if (muploadcallbackabovel! = null) {Chooseabove (ResultCode, data);        } else {Toast.maketext (this, "error occurred", Toast.length_short). Show (); }}}/** * Android API < (Android 5.0) version of callback processing * @param resultcode pick a file or take a photo of the return code * @param data to select a file or take a picture of the returned results */private    void Choosebelow (int resultcode, Intent data) {LOG.E ("Wangj", "return call Method--choosebelow");     if (RESULT_OK = = ResultCode) {   Updatephotos ();            if (data! = NULL) {//Here is a URI URI for the file path processing = Data.getdata ();                if (uri! = null) {LOG.E ("Wangj", "System return URI:" + uri.tostring ());            Muploadcallbackbelow.onreceivevalue (URI);            } else {muploadcallbackbelow.onreceivevalue (null);            }} else {//To specify the image storage path to the camera, after successful return data is empty LOG.E ("Wangj", "Custom result:" + imageuri.tostring ());        Muploadcallbackbelow.onreceivevalue (Imageuri);    }} else {muploadcallbackbelow.onreceivevalue (null); } Muploadcallbackbelow = null;} /** * Android API >= (Android 5.0) version of callback processing * @param resultcode pick a file or take a photo of the return code * @param data pick a file or take a picture of the return result */private void    Chooseabove (int resultcode, Intent data) {LOG.E ("Wangj", "Return to calling Method--chooseabove");        if (RESULT_OK = = ResultCode) {Updatephotos ();            if (data! = NULL) {//Here is a handle to the image selected from the file uri[] results; Uri Uridata = Data.getdata ();                if (uridata! = null) {results = new uri[]{uridata};                For (Uri Uri:results) {log.e ("Wangj", "System return URI:" + uri.tostring ());            } muploadcallbackabovel.onreceivevalue (results);            } else {muploadcallbackabovel.onreceivevalue (null);            }} else {log.e ("Wangj", "Custom result:" + imageuri.tostring ());        Muploadcallbackabovel.onreceivevalue (New Uri[]{imageuri});    }} else {muploadcallbackabovel.onreceivevalue (null); } muploadcallbackabovel = null;} private void Updatephotos () {//The broadcast does not matter if it is multiple (that is, it is sent when the photo is selected successfully), but only wakes the system to refresh the media file Intent Intent = new Intent (intent.action_med    Ia_scanner_scan_file);    Intent.setdata (Imageuri); Sendbroadcast (intent);}

  why separate Choosebelow (), chooseabove () processing?
because the Openfilechooser (), the Onshowfilechooser () method parameter has a different generic type of the callback parameter (an open, an open []), separate to deal with some.
Look at the results:

What do you think? After reading this result, rough write those few @hide method not guilty?

Why does the same HTML file open in the browser and we do not the same , the browser energy saving photos and can choose files?
that's because we're dead or we're using pictures. , either with a file selection, or you can specify a more personalized response based on the parameters in the Openfilechooser (), Onshowfilechooser () method, or as a browser, if you wish.

Possible problemsPermissions Issues

remind me again, don't forget Permissions Issues , don't be in the hole here again.

does not work after packaging is complete

Originally in the demo run good, but when we hit the release package test but found no pat, can not choose the picture!!! It's a real hole in the daddy!!! Think not strange, because the Openfilechooser () method is hidden by the system, and can not override, and our release package is open confusion, so in the packaging of the time to confuse the Openfilechooser (), This leads to the inability to callback Openfilechooser (). -
Keepclassmembers class * extends Android. Webkit. webchromeclient {
public void Openfilechooser (... );
}

Of course, as a good object-oriented developer, you can use an excuse to write the process a little more beautiful, I just can tell the problem, here is not to achieve this step.

seems to be nothing, think of the plus. The level is limited, if wrong, please correct me.
as usual, Demo Source GitHub portal, if harvested, welcome star

http://blog.csdn.net/a_running_wolf/article/details/77983739

WebView open Camera, file selector problems and workarounds

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.