Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android webview, file input field filechooser doesn't show up

Tags:

android

I am supposed to display a web page in a webview in an app. The page contains a html form where one of the fields is file. So it goes something like...

<input type="file" name="file">

If I open the page in the browser and press the Choose File button, file chooser pops up and everything is good, but when I press the Choose File button in the webview nothing happens :/

Any ideas how to make this work?

like image 402
m0s Avatar asked Feb 09 '11 11:02

m0s


2 Answers

WebView by default doesn't open file chooser. However it is possible to make this work. WebChromeClient has hidden method openFileChooser, which needs to be overridden to pop up a file chooser and then return the result to WebView. According to gurus one should never use hidden methods of Android SDK so this is not a good solution, and probably shouldn't be used in enterprise apps. However Android's stock Browser does exactly this way. Little more information how I overrode this method is in my this question. If anyone needs the source let me know Ill post it somewhere.

like image 158
m0s Avatar answered Nov 05 '22 19:11

m0s


Is it possible to upload files via webview?

This feature is available in version 1.3.0 and newer. For older versions of the app, yes it is possible, but you need to add some extra code to make it work. Add following code into your AndroidManifest.xml file. Place it below other uses-permission elements:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Copy/paste this java class MediaUtility.java into the project. Place it into com/robotemplates/webviewapp/utility directory.

Open MainFragment.java in fragment package. Find renderView() method and replace “webView.setWebChromeClient(new WebChromeClient());” by following code:

webView.setWebChromeClient(new WebChromeClient()
{
    public void openFileChooser(ValueCallback<Uri> filePathCallback)
    {
        mFilePathCallback4 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
    }

    public void openFileChooser(ValueCallback filePathCallback, String acceptType)
    {
        mFilePathCallback4 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
    }

    public void openFileChooser(ValueCallback<Uri> filePathCallback, String acceptType, String capture)
    {
        mFilePathCallback4 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
    }

    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
    {
        mFilePathCallback5 = filePathCallback;
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
        return true;
    }
});

Finally add following code somewhere inside the MainFragment object (for instance below this line “private boolean mLocal = false;”):

private static final int REQUEST_FILE_PICKER = 1;
private ValueCallback<Uri> mFilePathCallback4;
private ValueCallback<Uri[]> mFilePathCallback5;

@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
    if(requestCode==REQUEST_FILE_PICKER)
    {
        if(mFilePathCallback4!=null)
        {
            Uri result = intent==null || resultCode!=Activity.RESULT_OK ? null : intent.getData();
            if(result!=null)
            {
                String path = MediaUtility.getPath(getActivity(), result);
                Uri uri = Uri.fromFile(new File(path));
                mFilePathCallback4.onReceiveValue(uri);
            }
            else
            {
                mFilePathCallback4.onReceiveValue(null);
            }
        }
        if(mFilePathCallback5!=null)
        {
            Uri result = intent==null || resultCode!=Activity.RESULT_OK ? null : intent.getData();
            if(result!=null)
            {
                String path = MediaUtility.getPath(getActivity(), result);
                Uri uri = Uri.fromFile(new File(path));
                mFilePathCallback5.onReceiveValue(new Uri[]{ uri });
            }
            else
            {
                mFilePathCallback5.onReceiveValue(null);
            }
        }

        mFilePathCallback4 = null;
        mFilePathCallback5 = null;
    }
}

Don’t forget to add necessary imports: “import android.webkit.ValueCallback;”, “import com.robotemplates.webviewapp.utility.MediaUtility;”, “import java.io.File;”. If you still have a problem, try to add a rule in Proguard script: https://code.google.com/p/android/issues/detail?id=62220#c120.

like image 38
aven Avatar answered Nov 05 '22 18:11

aven