4

I'm developing an app, that uses a WebView to access some logic. The logic, has a part where the user can upload a picture, but, I can't seem to find a way for the app to do so.
The code I'm using as example is in this link.

As you will see, a custom Intent is set from the WebChromeClient, however, the file chooser does not open at all. Code:

public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType){  

                // Update message
                mUploadMessage = uploadMsg;

                try{    

                    // Create AndroidExampleFolder at sdcard

                    File imageStorageDir = new File(
                                           Environment.getExternalStoragePublicDirectory(
                                           Environment.DIRECTORY_PICTURES)
                                           , "AndroidExampleFolder");

                    if (!imageStorageDir.exists()) {
                        // Create AndroidExampleFolder at sdcard
                        imageStorageDir.mkdirs();
                    }

                    // Create camera captured image file path and name 
                    File file = new File(
                                    imageStorageDir + File.separator + "IMG_"
                                    + String.valueOf(System.currentTimeMillis()) 
                                    + ".jpg");

                    mCapturedImageURI = Uri.fromFile(file); 

                    // Camera capture image intent
                    final Intent captureIntent = new Intent(
                                                  android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

                    captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);

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

                    // Create file chooser intent
                    Intent chooserIntent = Intent.createChooser(i, "Image Chooser");

                    // Set camera intent to file chooser 
                    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS
                                           , new Parcelable[] { captureIntent });

                    // On select image call onActivityResult method of activity
                    startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);

                  }
                 catch(Exception e){
                     Toast.makeText(getBaseContext(), "Exception:"+e, 
                                Toast.LENGTH_LONG).show();
                 }

            }

Thanks in advance!
EDIT

So, after @JoxTraex enlightened me, I realized that the file chooser was not triggering because I was not overriding any methods of the WebChromeClient. Now, the file chooser is prompting, but, if a select an image, the image doesn't get uploaded.
The code I'm using for the file chooser:

@Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                openFileChooser(filePathCallback, "");
                return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
            }

            public void openFileChooser(ValueCallback<Uri[]> uploadMsg, String acceptType){
                // Update message
                //mUploadMessage = uploadMsg.this;
                try{
                    // Create AndroidExampleFolder at sdcard
                    File imageStorageDir = new File(
                            Environment.getExternalStoragePublicDirectory(
                                    Environment.DIRECTORY_PICTURES)
                            , "AndroidExampleFolder");

                    if (!imageStorageDir.exists()) {
                        // Create AndroidExampleFolder at sdcard
                        imageStorageDir.mkdirs();
                    }

                    // Create camera captured image file path and name
                    File file = new File(
                            imageStorageDir + File.separator + "IMG_"
                                    + String.valueOf(System.currentTimeMillis())
                                    + ".jpg");

                    mCapturedImageURI = Uri.fromFile(file);

                    // Camera capture image intent
                    final Intent captureIntent = new Intent(
                            android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

                    captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);

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

                    // Create file chooser intent
                    Intent chooserIntent = Intent.createChooser(i, "Image Chooser");

                    // Set camera intent to file chooser
                    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS
                            , new Parcelable[] { captureIntent });

                    // On select image call onActivityResult method of activity
                    startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);

                }
                catch(Exception e){
                    Toast.makeText(getBaseContext(), "Exception:"+e,
                            Toast.LENGTH_LONG).show();
                }

            }

Thanks in advance!

pamobo0609
  • 812
  • 10
  • 21
  • 1
    Are you sure some app can actually handle that particular intent? – JoxTraex May 19 '16 at 03:06
  • @JoxTraex I added some permissions to the manifest file, like the internet one, read external storage, camera – pamobo0609 May 19 '16 at 03:06
  • I don't know if you mean like declaring a broadcast receiver kind of thing – pamobo0609 May 19 '16 at 03:08
  • Well you should first validate that your code is getting called by using logs and then confirm that the intent you are sending is resolvable. – JoxTraex May 19 '16 at 03:10
  • @JoxTraex I just ran the app, with a Log like you suggested, but it's not logging anything... – pamobo0609 May 19 '16 at 03:15
  • That means your code is not working.. so of course it won't even trigger the intent. Debug your code and find out why its not working. – JoxTraex May 19 '16 at 03:17
  • 1
    I would start by going here @ https://developer.android.com/studio/debug/index.html – JoxTraex May 19 '16 at 03:21
  • @JoaxTraex I know how to debug dude, it's just that the method is set when the new instance of the WebChromeClient is set, and if the debugger is not entering, obviously it's not executing. By reading at other blogs and posts, there's a rare issue with the file chooser and it's usage in webviews... I'm starting to get desperate – pamobo0609 May 19 '16 at 03:25
  • 1
    I dont see how that is possible (could be wrong), but when you launch the intent if someone can handle it they will. The 2 explanations is 1) the code path you're expecting is not showing or 2) the intent you're building can't be serviced by anyone. Without any confirmation on any safe assumptions we're basically guessing what you're problem is. You need to provide more explicit guidance on what you have if you hope to have someone help. Specifically if you know of an issue that may be occuring probably including that in your post will help someone validate your assumption – JoxTraex May 19 '16 at 03:27
  • And another thing is how are you linking up the webview to do the call to actually call this method? – JoxTraex May 19 '16 at 03:33
  • @JoxTraex pls check my edit above. – pamobo0609 May 19 '16 at 04:02

2 Answers2

9

Well, after struggling with some listeners, I found a code that resolved my situation. Nevertheless, thanks to @JoxTraex and this dude.

pamobo0609
  • 812
  • 10
  • 21
  • This is not working in Nexus , what can be done for that ? Only option from gallery work but from camera, it opens but photo is not selected or nothing happens. If you have solve this, or any idea, please do share. – Satan Pandeya Oct 26 '16 at 05:54
  • @SatanPandeya, I tested the code recently on my Nexus 5X and everything seems fine. However, I'm going to create a gist with the most recent code I made for this. I'll be back. – pamobo0609 Nov 01 '16 at 14:02
  • @SatanPandeya here's the gist: https://gist.github.com/pamobo0609/1650a73d0478f5aeabc95f67f1457ba5 let me know if you have any doubts. – pamobo0609 Nov 01 '16 at 15:29
5

The accepted answer is correct, but I will post my code if it helps anyone. I used the code below, which is to be added inside webChrome class.

public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> uploadMsg, WebChromeClient.FileChooserParams fileChooserParams) {
            mFilePathCallback = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
            return true;
        }

And use the code in onActivityResult

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        if (requestCode != FILECHOOSER_RESULTCODE || mFilePathCallback == null) {
            super.onActivityResult(requestCode, resultCode, intent);
            return;
        }
        Uri[] results = null;
        // Check that the response is a good one
        if (resultCode == Activity.RESULT_OK) {
                String dataString = intent.getDataString();
                if (dataString != null) {
                    results = new Uri[]{Uri.parse(dataString)};
            }
        }
        mFilePathCallback.onReceiveValue(results);
        mFilePathCallback = null;
    }

You will also need runtime permissions for Marshmallow and up. This code will work fine in Lollipop. You have to add conditions for other android versions as well to make it work on other versions

Bibaswann Bandyopadhyay
  • 3,389
  • 2
  • 31
  • 30