1

I am developing a webview app that allows people upload images from their phone, i got more confused when i read this post.

enter image description here

i noticed that when i click on the chose file button...it does not open my gallery or access my files.

This is my code:

    package com.benaija.benaija.Fragments;


import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.benaija.benaija.MainActivity;
import com.benaija.benaija.R;


/**
 * Created by Oto-obong on 10/01/2018.
 */

public class HomeFragement extends Fragment {

    private WebView webView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_home, container, false);

        webView = rootView.findViewById(R.id.webview);


        webView.setWebViewClient(new WebViewClient());

        webView.loadUrl("https://www.benaija.com");

        WebSettings webSettings = webView.getSettings();

        webSettings.setJavaScriptEnabled(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(false);
        webSettings.setAllowFileAccess(true);
        webSettings.setAllowContentAccess(true);
        webSettings.setLoadsImagesAutomatically(true);


        return rootView;
    }




}

Please how can i solve this ?

Thanus
  • 411
  • 2
  • 8
  • 21
  • @ViaTech , the link doesnt solve the answer, the problem still persists – Thanus Aug 18 '18 at 11:35
  • did the updated example I provided give you what you needed or do you need something different put together? – ViaTech Aug 19 '18 at 18:54
  • i havent yet tried it, will try it soon, but the other example i got before i updated it allowed me to open system files, but when i picked a file, i wasnt able to upload it – Thanus Aug 19 '18 at 21:06
  • Okay, let me know. It worked with my example, if it doesn't with your site: **https://www.benaija.com**, I may need more of your code to mimic what you are trying to do... Also, based on your example the upload should happen on the server, not the application's WebView specifically. It is a web based upload, my code allows local files to be selected for upload from the web application, again the upload happens from the server – ViaTech Aug 19 '18 at 23:09
  • @ViaTech can i send you the source code ? – Thanus Aug 19 '18 at 23:16
  • @ViaTech, this is the source code https://github.com/eshiett1995/BeNaija – Thanus Aug 20 '18 at 01:20
  • I am a bit confused what your issue is because the updated code you have provided in your Git works. I have downloaded your project and run it, and everything works as expected with my test website **https://files.fm/**, so I could test the uploading of a file to a webform and it works flawlessly. I suspect your **uploading** issues have nothing to do with the Application you are using for your **WebView**. For example, the website you are viewing is some server language like PHP, the PHP is what physically uploads the file to your server from the webform, not the Android app – ViaTech Aug 20 '18 at 13:14
  • okay, the client i am doing the project for said it doesnt work, could it be as a resut of the android version – Thanus Aug 20 '18 at 20:27

1 Answers1

2

Overall you are going to need to alter your code for the WebView to allow a WebChromeClient to be set, and then implement an onFileChooser() method to enable the WebView to communicate that your device should open the system's file explorer when a type="file" input button is pressed

My code below opens a file chooser and allows a file to be chosen for uploading via a web form, from a WebView

MainActivity.java

package com.viatechsystems.test;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;


public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
    }
}

HomeFragment.java

package com.viatechsystems.test;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import static android.app.Activity.RESULT_OK;

public class HomeFragment extends Fragment {

    private static final int INPUT_FILE_REQUEST_CODE = 1;
    private static final int FILECHOOSER_RESULTCODE = 1;
    private static final String TAG = MainActivity.class.getSimpleName();
    private WebView webView;
    private WebSettings webSettings;
    private ValueCallback<Uri> mUploadMessage;
    private Uri mCapturedImageURI = null;
    private ValueCallback<Uri[]> mFilePathCallback;
    private String filePath;

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
            super.onActivityResult(requestCode, resultCode, data);
            return;
        }else{
            Toast.makeText(getActivity().getApplicationContext(),
                    "Upload may take as long as you see this message.",
                    Toast.LENGTH_LONG).show();
            }

        Uri[] results = null;

        //check good response
        if (resultCode == Activity.RESULT_OK) {
            if (data == null) {
                if (filePath != null) {
                    results = new Uri[]{Uri.parse(filePath)};
                }
            } else {
                String dataString = data.getDataString();
                if (dataString != null) {
                    results = new Uri[]{Uri.parse(dataString)};
                }
            }
        }

        mFilePathCallback.onReceiveValue(results);
        mFilePathCallback = null;


        if (requestCode != FILECHOOSER_RESULTCODE || mUploadMessage == null) {
            super.onActivityResult(requestCode, resultCode, data);
            return;
        }

        Uri result = null;

        try {
            if (resultCode != RESULT_OK) {
                result = null;
            } else {
                // retrieve from the private variable if the intent is null
                result = data == null ? mCapturedImageURI : data.getData();
            }
        } catch (Exception e) {
            Toast.makeText(getActivity().getApplicationContext(),
                    "activity :" + e, Toast.LENGTH_LONG).show();
        }
        mUploadMessage.onReceiveValue(result);
        mUploadMessage = null;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        View rootView = inflater.inflate(R.layout.fragment_home, container, false);

        webView = rootView.findViewById(R.id.webview);

        webView.setWebViewClient(new WebViewClient());
        webView.setWebChromeClient(new ChromeClient());     //set with custom class below

        webView.loadUrl("https://files.fm/"); //changed so I could test a button

        WebSettings webSettings = webView.getSettings();

        webSettings.setJavaScriptEnabled(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(false);
        webSettings.setAllowFileAccess(true);
        webSettings.setAllowContentAccess(true);
        webSettings.setLoadsImagesAutomatically(true);

        return rootView;
    }


    private class ChromeClient extends WebChromeClient {

        /*NOTE: method openFileChooser() is different for different Android Versions*/

        // For Android 3.0+
        public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            HomeFragment.this.startActivityForResult(
                    Intent.createChooser(i, "File Selection"),
                    FILECHOOSER_RESULTCODE);
        }

        //For Android 4.1
        public void openFileChooser(ValueCallback<Uri> uploadMsg,
                                    String acceptType, String capture) {
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            HomeFragment.this.startActivityForResult(Intent.createChooser(i, "File Selection"),
                    HomeFragment.FILECHOOSER_RESULTCODE);

        }

        // For Android 5.0+ --- this is the method that will be called most of the time
        public boolean onShowFileChooser(WebView view,
                                         ValueCallback<Uri[]> filePath,
                                         WebChromeClient.FileChooserParams fileChooserParams) {

            // Double check that we don't have any existing callbacks
            if (mFilePathCallback != null) {
                mFilePathCallback.onReceiveValue(null);
            }
            mFilePathCallback = filePath;

            Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
            contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
            contentSelectionIntent.setType("*/*");

            Intent[] intentArray = new Intent[0];

            Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
            chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
            chooserIntent.putExtra(Intent.EXTRA_TITLE, "Select Option:");
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);

            startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);

            return true;
        }
    }
}

fragment_home.xml - A layout resource

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

</LinearLayout>

main_activity.xml - A layout resource

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <fragment android:name="com.viatechsystems.test.HomeFragment"
        android:id="@+id/home_fragment"
        android:layout_weight="2"
        android:layout_width="0dp"
        android:layout_height="match_parent" />

</LinearLayout>
ViaTech
  • 2,143
  • 1
  • 16
  • 51
  • it worked perfectly, but does this code only support lollipop version of android ? – Thanus Aug 18 '18 at 16:23
  • No my code supports Android 5.0 (lollipop) and up, the lower versions of Android use slightly different code for **onActivityResult()**, which I can show if absolutely needed, but they are less used these days – ViaTech Aug 18 '18 at 19:23
  • No worries, and sorry I meant the **onShowFileChooser()** method was different for different Android versions, I have updated my code as you requested. I didn't need the Lollipop check in **onActivityResult()** – ViaTech Aug 18 '18 at 22:27