1

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,

  1. someone's wordpress blog-posts related to webview
  2. stackoverflow: #SO1, #SO2, #SO3, #SO4, #SO5, #SO6, #SO7
  3. google android issue
  4. 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;
  1. I want someone to help me add code to the ToDo sections marked by comments and tags [noHTML like noSQL]
  2. I want help using TargetApi annotation correctly, and the SuppressLint one too. for the final block meant for Android OS Version 5.0.
  3. Additionally, am I missing any necessary Overrides?
  4. 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'
  }
}                                      
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
computingfreak
  • 4,939
  • 1
  • 34
  • 51
  • 1
    According to [WebViewContentsClientAdapter](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/com/android/webview/chromium/WebViewContentsClientAdapter.java/) source codes, this is a matter of target API assigned in your project. If you set it to KITKAT, you'll get `openFileChooser` as on Android pre-4.4. If it's LOLLIPOP+, it'll invoke `onShowFileChooser`. – Stan Apr 04 '16 at 13:50
  • Did you find any solution to this? – Ahsan Zaheer Feb 21 '18 at 13:33

0 Answers0