1

I'm playing around with the WebView in the Android browser, but is wondering if anyone have used the browser together with the html5 to use the camera and gps of the local device? Or will I need to do a Javascript connection to the Java source code for this?

Will this also work in IOS?

This is, without using PhoneGap.

best, Henrik

Hiny
  • 195
  • 7
  • 21
  • And after posting you find what you were looking for... http://stackoverflow.com/questions/10345973/how-can-i-access-iphone-or-android-camera-using-html5 Anyone that have an idé of when this will be done? – Hiny Dec 11 '12 at 07:26

3 Answers3

2

It might be a bit late, but just in case I will give you an example to do that. (Camera)

1////add this to your webChromeClient

myWebView.setWebChromeClient(new WebChromeClient() 
{
    public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType ) 
    { 
        mUploadMessage = uploadMsg;
        Intent cameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");
        Calendar cal = Calendar.getInstance();
        cal.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
        File photo = new File(Environment.getExternalStorageDirectory(), sdf.format(cal.getTime()) +".jpg");
        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
        picUri = Uri.fromFile(photo);
        startActivityForResult(cameraIntent, TAKE_PICTURE);                 
    }
}); 

2///add this function

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    switch(requestCode)
    {
        case TAKE_PICTURE:
            if(resultCode == Activity.RESULT_OK)
            {
                Uri mypic = picUri;
                mUploadMessage.onReceiveValue(mypic);
                mUploadMessage = null;
            }
            else
            {
                mUploadMessage.onReceiveValue(null);
                mUploadMessage = null;
                return;
            }

        default:
        {
            return;
        }   
    }
}   

3// and the HTML looks like this

<input type="file" id="files" name="files"  accept="image/*" capture="camera" >

The above code will open the native camera app.

P.S. This is a mix of code from different sources.

Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
Christian
  • 773
  • 7
  • 11
  • Hi @Christian, the `Uri mypic = picUri;` line makes reference to a `picUri` variable not defined in the `onActivityResult` scope. Since it doesn't has the `m` prefix, I undestand that it isn't a class field. So, is it an error? Which value it's supposed to have? – JavierCane Jul 09 '15 at 12:28
  • 1
    hey Javier, sorry about that. define that variable as private field. Example: private Uri picUri;. – Christian Jul 10 '15 at 02:30
  • Thanks @Christian, it's what I supposed :) I'm having troubles with what you called `myWebView` now. Where do you get it? I'm trying to declare it in the `public class MainActivity extends CordovaActivity` class `onCreate` method as: `WebView webView = new WebView(this);` but then it doesn't launch the image capture intent :-/ The other possibility is to call the `setWebChromeClient` method from the `appView` inherited from the `CordovaActivity` parent, but it's a `CordovaWebView` and it doest has the `setWebChromeClient` method :S – JavierCane Jul 27 '15 at 10:10
  • 1
    I've already found the solution. I've posted an answer to this question in order to show the complete code. Thanks for your answers @Christian! – JavierCane Jul 28 '15 at 08:49
  • 1
    sorry for my late reply @JavierCane. thanks for updating the solution. cheers! – Christian Jul 29 '15 at 02:38
0

It's worth pointing out where the code shown here should live, as it's not obvious for a newbie - it goes in your Activity class, i.e.

public class MyActivity extends Activity {

    @Override  
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        ...
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        ...

        myWebView.setWebChromeClient(new WebChromeClient()
        {
            public void openFileChooser(ValueCallback<Uri> uploadMsg) {  
                ...
            }
        });
    }
}
Will
  • 94
  • 1
  • 2
0

In my case, I've override the makeWebViewEngine method in order to be able to modify the CordovaWebViewEngine casted to a SystemWebViewEngine as follows (based on this answer):

public class MainActivity extends CordovaActivity {

    private static final int FILECHOOSER_RESULTCODE = 12345;

    private ValueCallback<Uri> mUploadMessage;

    private Uri mPicUri;

    private ValueCallback<Uri[]> mFilePathCallback;

    private String mCameraPhotoPath;

    @Override
    protected CordovaWebViewEngine makeWebViewEngine() {
        SystemWebViewEngine systemWebViewEngine = (SystemWebViewEngine) super.makeWebViewEngine();

        SystemWebView systemWebView = (SystemWebView) systemWebViewEngine.getView();

        systemWebView.setWebChromeClient(new SystemWebChromeClient(systemWebViewEngine) {
            // For Android 4.1
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                mUploadMessage = uploadMsg;
                Intent cameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");
                Calendar cal = Calendar.getInstance();
                cal.getTime();
                SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
                File photo = new File(Environment.getExternalStorageDirectory(), sdf.format(cal.getTime()) + ".jpg");
                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
                mPicUri = Uri.fromFile(photo);

                startActivityForResult(cameraIntent, FILECHOOSER_RESULTCODE);
            }

            // For Android 5.0+
            public boolean onShowFileChooser(
                    WebView webView, ValueCallback<Uri[]> filePathCallback,
                    WebChromeClient.FileChooserParams fileChooserParams) {

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

                // Set up the take picture intent
                Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                if (takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null) {
                    // Create the File where the photo should go
                    File photoFile = null;
                    try {
                        photoFile = createImageFile();
                        takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
                    } catch (IOException ex) {
                        // Error occurred while creating the File
                        Log.e(TAG, "Unable to create Image File", ex);
                    }

                    // Continue only if the File was successfully created
                    if (photoFile != null) {
                        mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
                        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                                Uri.fromFile(photoFile));
                    } else {
                        takePictureIntent = null;
                    }
                }

                // Set up the intent to get an existing image
                Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
                contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
                contentSelectionIntent.setType("image/*");

                // Set up the intents for the Intent chooser
                Intent[] intentArray;
                if (takePictureIntent != null) {
                    intentArray = new Intent[]{takePictureIntent};
                } else {
                    intentArray = new Intent[0];
                }

                Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
                chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
                chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);

                startActivityForResult(chooserIntent, MainActivity.FILECHOOSER_RESULTCODE);

                return true;
            }
        });

        return systemWebViewEngine;
    }

    // …

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set by <content src="index.html" /> in config.xml
        loadUrl(launchUrl);
    }
}

Furthermore, based on this other answer, I've had to specify the openFileChooser method for Android 4.1 and, for Android 5.0+, I've had to specify the onShowFileChooser method.

By the way, I've modified the onActivityResult method as follows:

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (Build.VERSION.SDK_INT >= 21) {

            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)};
                } else {
                    // If there is not data, then we may have taken a photo
                    if (mCameraPhotoPath != null) {
                        results = new Uri[]{Uri.parse(mCameraPhotoPath)};
                    }
                }
            }

            mFilePathCallback.onReceiveValue(results);
            mFilePathCallback = null;
        } else {
            if (requestCode == FILECHOOSER_RESULTCODE) {
                if (null == this.mUploadMessage) {
                    return;
                }

                Uri result;
                if (resultCode != RESULT_OK) {
                    result = null;
                } else {
                    result = intent == null ? this.mPicUri : intent.getData(); // retrieve from the private variable if the intent is null
                }

                this.mUploadMessage.onReceiveValue(result);
                this.mUploadMessage = null;
            }
        }
    }

Thanks to @Will and @Christian for pointing the good direction in this answer BTW :)

Community
  • 1
  • 1
JavierCane
  • 2,324
  • 2
  • 22
  • 19