Android WebView upload file support full resolution _android

Source: Internet
Author: User

By default, webview that use Android are not able to support uploading files. And this, is also after our front end engineer informs to understand. Because there is a difference in the implementation of each version of Android, you need to webview different versions. It took a little time to refer to someone else's code, and the problem was solved, and here I shared the pit I stepped on.
The main idea is to rewrite the webchromeclient, and then in the webviewactivity to receive the selected file URI, to the page to upload it.
create an internal class of webviewactivity

public class Xhswebchromeclient extends Webchromeclient {//for Android 3.0+ public void Openfilechooser (VALUECALLB
    Ack<uri> uploadmsg) {clog.i ("Upfile", "in OpenFile Uri Callback");
    if (muploadmessage!= null) {muploadmessage.onreceivevalue (null);
    } muploadmessage = uploadmsg;
    Intent i = new Intent (intent.action_get_content);
    I.addcategory (intent.category_openable);
    I.settype ("*/*");
  Startactivityforresult (Intent.createchooser (i, "File Chooser"), Filechooser_resultcode); }//For Android 3.0+ public void Openfilechooser (Valuecallback uploadmsg, String accepttype) {clog.i ("Upfile",
    "In OpenFile Uri Callback has accept Type" + accepttype);
    if (muploadmessage!= null) {muploadmessage.onreceivevalue (null);
    } muploadmessage = uploadmsg;
    Intent i = new Intent (intent.action_get_content);
    I.addcategory (intent.category_openable); String type = Textutils.isempty (accepttype)?
    "*/*": accepttype; I. SetType (type);
  Startactivityforresult (Intent.createchooser (i, "File Chooser"), Filechooser_resultcode); }//For Android 4.1 public void Openfilechooser (valuecallback<uri> uploadmsg, String accepttype, String Captur
    e) {clog.i ("Upfile", "in OpenFile Uri Callback has accept Type" + Accepttype + "has capture" + capture);
    if (muploadmessage!= null) {muploadmessage.onreceivevalue (null);
    } muploadmessage = uploadmsg;
    Intent i = new Intent (intent.action_get_content);
    I.addcategory (intent.category_openable); String type = Textutils.isempty (accepttype)?
    "*/*": accepttype;
    I.settype (type);
  Startactivityforresult (Intent.createchooser (i, "File Chooser"), Filechooser_resultcode); //android 5.0+ @Override @SuppressLint ("Newapi") public boolean Onshowfilechooser (WebView WebView, Valuecallback <Uri[]> Filepathcallback, Filechooserparams filechooserparams) {if (muploadmessage!= null) {muploadmess Age.oNreceivevalue (NULL);
    } clog.i ("Upfile", "File Chooser params:" + filechooserparams.tostring ());
    Muploadmessage = Filepathcallback;
    Intent i = new Intent (intent.action_get_content);
    I.addcategory (intent.category_openable); if (filechooserparams!= null && filechooserparams.getaccepttypes ()!= null && FILECHOOSERPARAMS.G
    Etaccepttypes (). length > 0) {i.settype (filechooserparams.getaccepttypes () [0]);
    else {i.settype ("*/*");
    } startactivityforresult (Intent.createchooser (i, "File Chooser"), Filechooser_resultcode);
  return true;

 }
}

The above openfilechooser is the system is not exposed interface, so do not need to add override annotation, while different versions have different parameters, the parameters, the first valuecallback for us after the selection of files, receive file callback to the Web page processing, Accepttype is the accepted file MIME type. After Android 5.0, the system provides onshowfilechooser to enable us to choose the file, still has valuecallback, in the Filechooserparams parameter, also includes Accepttype. We can open the system according to Accepttype or we create the file selector ourselves. Of course, if you need to open the camera to take pictures, you can also use the intent to open the camera to open it. The
handles the selected file
above is the interface to open the selection file for the response, and we also need to process the received file and pass it to the Web page to respond. Because we are using Startactivityforresult to open the selection page, we will receive the result of the selection in Onactivityresult. Show Code:

@Override protected void Onactivityresult (int requestcode, int resultcode, Intent data) {Super.onactivityresult (reques
  Tcode, ResultCode, data);
    if (Requestcode = = Filechooser_resultcode) {if (null = = Muploadmessage) return; Uri result = data = NULL | | ResultCode!= RESULT_OK?
    Null:data.getData ();
      if (result = = null) {muploadmessage.onreceivevalue (null);
      Muploadmessage = null;
    Return
    } clog.i ("Upfile", "Onactivityresult" + result.tostring ());
    String Path = Fileutils.getpath (this, result);
      if (textutils.isempty (path)) {muploadmessage.onreceivevalue (null);
      Muploadmessage = null;
    Return
    Uri uri = uri.fromfile (new File (path));
    CLOG.I ("Upfile", "Onactivityresult after parser URI:" + uri.tostring ()); if (Build.VERSION.SDK_INT >= build.version_codes.
    Lollipop) {Muploadmessage.onreceivevalue (new Uri[]{uri});
    else {muploadmessage.onreceivevalue (URI); } muploadmessage =Null

 }
}

The above code is basically called Valuecallback's Onreceivevalue method, which returns the results back to the web.
Note , others to say, important
due to differences in versions, Android 5.0 version, Valuecallback The Onreceivevalue receives the parameter type is the URI, 5.0 and above receives is the URI array, needs to pay attention when passes the value. The
Select file will use the components provided by the system or other supported apps, and the URI returned is directly the URL of the file, some contentprovider URI, so we need to unify the processing, into the file Uri, can refer to the following code (get the file path).
Call GetPath can convert the URI to the path of the real file, and then generate the URI of the file itself

public class FileUtils {/** * @param uri the URI to check.
   * @return Whether The Uri authority is externalstorageprovider. */public static Boolean isexternalstoragedocument (Uri uri) {return "com.android.externalstorage.documents". Equals (
  Uri.getauthority ());
   /** * @param uri the URI to check.
   * @return Whether The Uri authority is downloadsprovider. */public static Boolean isdownloadsdocument (Uri uri) {return "com.android.providers.downloads.documents". Equals (Ur
  I.getauthority ());
   /** * @param uri the URI to check.
   * @return Whether The Uri authority is mediaprovider. */public static Boolean ismediadocument (Uri uri) {return ' com.android.providers.media.documents '. Equals (Uri.getaut
  Hority ()); }/** * Get the value of the ' data column ' for this Uri.
   This is useful to * Mediastore Uris, and other file-based contentproviders.
   * * @param context.
   * @param uri the URI to query. * @param SelectIon (Optional) Filter used in the query.
   * @param Selectionargs (Optional) Selection arguments used in the query.
   * @return The value of the _data column, which is typically a file path. */public static String Getdatacolumn (context context, Uri Uri, String selection, string[] Selection
    Args) {Cursor Cursor = null;
    Final String column = "_data";

    Final string[] projection = {column};
      try {cursor = Context.getcontentresolver (). Query (URI, projection, selection, Selectionargs, null); if (cursor!= null && cursor.movetofirst ()) {final int column_index = Cursor.getcolumnindexorthrow (colum
        n);
      Return cursor.getstring (Column_index);
    Finally {if (cursor!= null) cursor.close ();
  return null; /** * Get A is a file path from a Uri. This'll get the "path for Storage Access * Framework Documents, as the" _data field for the MediaStorE and * other file-based contentproviders.
   * * @param context.
   * @param uri the URI to query. 

    * @author Paulburke */@SuppressLint ("Newapi") public static String GetPath (final context, final URI Uri) { Final Boolean Iskitkat = Build.VERSION.SDK_INT >= build.version_codes.

    KitKat; Documentprovider if (Iskitkat && documentscontract.isdocumenturi (context, URI)) {//EXTERNALSTORAGEP
        Rovider if (Isexternalstoragedocument (URI)) {final String docId = Documentscontract.getdocumentid (URI);
        Final string[] split = Docid.split (":");

        Final String type = split[0];
        if ("PRIMARY". Equalsignorecase (Type)) {return environment.getexternalstoragedirectory () + "/" + split[1]; }//TODO handle non-primary volumes}//Downloadsprovider else if isdownloadsdocument (ur
        i) {final String id = documentscontract.getdocumentid (URI); FinalUri Contenturi = Contenturis.withappendedid (Uri.parse ("Content://downloads/public_downloads"), Long.valueOf (i

        d));
      Return Getdatacolumn (context, Contenturi, NULL, NULL); }//Mediaprovider else if (ismediadocument (URI)) {final String docId = documentscontract.getdocument
        Id (URI);
        Final string[] split = Docid.split (":");

        Final String type = split[0];
        Uri Contenturi = null;
        if ("image". Equals (Type)) {Contenturi = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        else if ("video". Equals (Type)) {Contenturi = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        else if ("Audio". Equals (Type)) {Contenturi = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        Final String selection = "_id=?";

        Final string[] Selectionargs = new string[] {split[1]};
      Return Getdatacolumn (context, Contenturi, selection, Selectionargs);
 }   }//Mediastore (and general) else if ("Content" Equalsignorecase (Uri.getscheme ())) {return getdatacolum
    N (context, URI, NULL, NULL);
    }//File else if ("file". Equalsignorecase (Uri.getscheme ())) {return Uri.getpath ();
  return null;

 }

}

Again, even if the result is null, it is passed to the web, which calls Muploadmessage.onreceivevalue (null) directly, otherwise the Web page blocks.
Finally, in the release package, because we will confuse, to specifically set not to confuse the Webchromeclient subclass of the Openfilechooser method, because it is not an inherited method, so the default will be confused, and then can not select the file.
That's it.
Original address: http://blog.isming.me/2015/12/21/android-webview-upload-file/

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

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.