I am new to Android application development. Been struggling since a month, and have worked on this issue since 2 weeks by now. I have done extensive research on Android WebViews across different versions. Checked most other posts related to my issue,
- someone's wordpress blog-posts related to webview
- stackoverflow: #SO1, #SO2, #SO3, #SO4, #SO5, #SO6, #SO7
- google android issue
- some more: #SO8, #SO9, #SO10
i need someone to help me with how to handle Android version 4.4 (KITKAT) to allow users to upload files via HTML forms inside of WebView.
I cannot use CrossWalk and don't want to use any of the github code made by others. i want to fix the methods that i can override for each API Level. Also, there is no chance of adding Javascript in Server side pages.
The onCreate method of my WebViewActivity contains the following code:
webView.setWebChromeClient(new WebChromeClient() {
        @Override
        public void onCloseWindow(WebView w) {
            super.onCloseWindow(w);
            finish();
        }
        @Override
        public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, Message resultMsg) {
            WebView childView = new WebView(WebViewActivity.this);
            final WebSettings settings = childView.getSettings();
            settings.setDomStorageEnabled(true);
            settings.setJavaScriptEnabled(true);
            settings.setAllowFileAccess(true);
            settings.setAllowContentAccess(true);
            childView.setWebChromeClient(this);
            WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
            transport.setWebView(childView);
            resultMsg.sendToTarget();
            return false;
        }
        // For Android Version < 3.0
        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            //System.out.println("WebViewActivity OS Version : " + Build.VERSION.SDK_INT + "\t openFC(VCU), n=1");
            mUploadMessage = uploadMsg;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType(TYPE_IMAGE);
            startActivityForResult(intent, INPUT_FILE_REQUEST_CODE);
        }
        // For 3.0 <= Android Version < 4.1
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
            //System.out.println("WebViewActivity 3<A<4.1, OS Version : " + Build.VERSION.SDK_INT + "\t openFC(VCU,aT), n=2");
            openFileChooser(uploadMsg, acceptType, "");
        }
        // For 4.1 <= Android Version < 5.0
        public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture) {
            //System.out.println("WebViewActivity 4.1<A<5, OS Version : " + Build.VERSION.SDK_INT + "\t openFC(VCU,aT,c), n=3");
            mUploadMessage = uploadFile;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType(TYPE_IMAGE);
            startActivityForResult(intent, INPUT_FILE_REQUEST_CODE);
        }
From Here.
{
        //For Android Version = 4.4.*
        public void showFileChooser(ValueCallback<String[]> filePathCallback, String acceptType, boolean paramBoolean) {
            //System.out.println("WebViewActivity 4.1<A<5, OS Version : " + Build.VERSION.SDK_INT + "\t showFC(VCS,aT,p), n=3");
            //ToDo,not supported yet, need to find a way to convert ValueCallback<String[]> to ValuCallback<Uri[]>
        }
        //For Android Version = 4.4.*
        public void showFileChooser(ValueCallback<String[]> uploadFileCallback, FileChooserParams fileChooserParams) {
            //System.out.println("WebViewActivity 4.1<A<5, OS Version : " + Build.VERSION.SDK_INT + "\t showFC(VCS,FCP), n=2");
            //ToDo,not supported yet, need to find a way to convert ValueCallback<String[]> to ValuCallback<Uri[]>
        }
}
Till Here.
        // For Android Version 5.0+
        // Ref: https://github.com/GoogleChrome/chromium-webview-samples/blob/master/input-file-example/app/src/main/java/inputfilesample/android/chrome/google/com/inputfilesample/MainFragment.java
        public boolean onShowFileChooser(WebView webView,
                                         ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
            System.out.println("WebViewActivity A>5, OS Version : " + Build.VERSION.SDK_INT + "\t onSFC(WV,VCUB,FCP), n=3");
            if (mFilePathCallback != null) {
                mFilePathCallback.onReceiveValue(null);
            }
            mFilePathCallback = filePathCallback;
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType(TYPE_IMAGE);
            startActivityForResult(intent, INPUT_FILE_REQUEST_CODE);
            return true;
        }
    });
The local variables have been initialized as follows:
private static final String TYPE_IMAGE = "image/*";
private static final int INPUT_FILE_REQUEST_CODE = 1;
private ValueCallback<Uri> mUploadMessage;
private ValueCallback<Uri[]> mFilePathCallback;
- I want someone to help me add code to the ToDo sections marked by comments and tags [noHTML like noSQL]
- I want help using TargetApi annotation correctly, and the SuppressLint one too. for the final block meant for Android OS Version 5.0.
- Additionally, am I missing any necessary Overrides?
- One more thing, i would like to understand why this piece of code is needed, or whether it can be skipped, i did debug testing, my code doesn't work without it. - if (mFilePathCallback != null) { mFilePathCallback.onReceiveValue(null); } 
The onActivityResult method is written like this:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == INPUT_FILE_REQUEST_CODE) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (mFilePathCallback == null) {
                super.onActivityResult(requestCode, resultCode, data);
                return;
            }
            Uri[] results = null;
            if (resultCode == RESULT_OK) {
                String dataString = data.getDataString();
                if (dataString != null) {
                    results = new Uri[]{Uri.parse(dataString)};
                }
            }
            mFilePathCallback.onReceiveValue(results);
            mFilePathCallback = null;
        } else {
            if (mUploadMessage == null) {
                super.onActivityResult(requestCode, resultCode, data);
                return;
            }
            Uri result = null;
            if (resultCode == RESULT_OK) {
                if (data != null) {
                    result = data.getData();
                }
            }
            mUploadMessage.onReceiveValue(result);
            mUploadMessage = null;
        }
    } else {
        super.onActivityResult(requestCode, resultCode, data);
    }
For reference, this is my module build.gradle file (not project build.gradle file):
android {
//using 21 [Android 5.0], in order to use LOLLIPOP constant in code above
compileSdkVersion 21
//https://developer.android.com/tools/revisions/build-tools.html
buildToolsVersion "23.0.2"
defaultConfig {
    applicationId "ab.cd.efghijklmo.pqrstuvwxyz"
    //need to support Honeycomb [Android 3.0]
    minSdkVersion 11
    versionCode 16
    versionName "1.0.15"
}
buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
    }
}
packagingOptions {
    exclude 'META-INF/DEPENDENCIES.txt'
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/NOTICE.txt'
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/LICENSE'
    exclude 'META-INF/DEPENDENCIES'
    exclude 'META-INF/notice.txt'
    exclude 'META-INF/license.txt'
    exclude 'META-INF/dependencies.txt'
  }
}                                      
 
    