简体   繁体   中英

Android App- Popup Menu with the Camera App

I've been trying to get my first Android app to work. I have one activity that uses a webview, and I use it to open web pages that have html forms on them.

There was some trouble getting the "Choose File" button (for file inputs) to work, but I finally solved it thanks to the help posted here File Upload in WebView . From there, I'm pretty much using the Main Activity java code they made available on Github.

My actual problem is that when clicking a file input button, I don't get the option for the user to use the device's Camera , which I'd like to have. At first I thought it might be related to having to ask for Camera permission for the app, but I implemented it and I was wrong on that one. The problem here is I'm unexperienced with the Intents to get the popup menus, like:

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

Some guidance on finding a way to get a "Camera" option to come up would be much appreciated.

Let me show you what I mean by this, opening the same html form on Chrome, and my app on 2 different Android OS versions (4.4.4 and 6.0). Using my Samsung Galaxy Tab, running Android 4.4.4. When opening a page that has an html form, on Google Chrome , clicking the Choose File button, I get this menu

That is what I want to have in my app

GETing using the same URL and displaying it in my App (on 4.4.4) , using my webview, when clicking the Choose File button, I get this menu

(Also, I've tried clicking that Choose File button on my app, on an Android 6.0 emulator , and it goes straight to the gallery , and there's no Camera option there):

This is the relevant part of the code:

        //For Android 4.1+
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
            mUM = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            MainActivity.this.startActivityForResult(Intent.createChooser(i, "Choose an Image please"), MainActivity.FCR);
        }
        //For Android 5.0+
        public boolean onShowFileChooser(
                WebView webView, ValueCallback<Uri[]> filePathCallback,
                FileChooserParams fileChooserParams){
            if(mUMA != null){
                mUMA.onReceiveValue(null);
            }
            mUMA = filePathCallback;
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if(takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null){
                File photoFile = null;
                try{
                    photoFile = createImageFile();
                    takePictureIntent.putExtra("PhotoPath", mCM);
                }catch(IOException ex){
                    Log.e(TAG, "Image file creation failed", ex);
                }
                if(photoFile != null){
                    mCM = "file:" + photoFile.getAbsolutePath();
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                }else{
                    takePictureIntent = null;
                }
            }
            Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
            contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
            contentSelectionIntent.setType("image/*");
            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, FCR);
            return true;
        }

This is a helper function to offer both a Camera and Media Picker chooser intent. I think you're specifically asking about ACTION_IMAGE_CAPTURE, ie the first part of this sample code snippet.

private Intent getPhotoChooserIntent(String acceptType, String capture)
{
 try
 {
    //---------------------------------------------------------------------
    // camera Intent 
    //---------------------------------------------------------------------
    Intent intentCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat("HHmmss", Locale.US);

    // path to picture
    File dirPhotos = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File photo = new File(String.format("%s/Photo_%s.jpg", dirPhotos.getAbsolutePath(), sdf.format(cal.getTime())));
    mPhoto = Uri.fromFile(photo);
    intentCamera.putExtra (MediaStore.EXTRA_OUTPUT, mPhoto);

    // pass "camera" in this parameter for a Camera only picker 
    if (capture.equalsIgnoreCase("camera"))
    {
     if (intentCamera.resolveActivity(mContext.getPackageManager()) != null)
        return (intentCamera);
     return (null);
    }

    //---------------------------------------------------------------------
    // media picker Intent
    //---------------------------------------------------------------------
    Intent intentPicker = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

    // aggregate list of resolved intents
    List<Intent> intentsList = new ArrayList<>();

    List<ResolveInfo> resInfo = mContext.getPackageManager().queryIntentActivities(intentPicker, 0);
    for (ResolveInfo resolveInfo : resInfo)
    {
     Intent intentTarget = new Intent(intentPicker);
     intentTarget.setPackage(resolveInfo.activityInfo.packageName);
     intentsList.add(intentTarget);
    }   

    if (intentCamera.resolveActivity(mContext.getPackageManager()) != null)
     intentsList.add(intentCamera);

    if (intentsList.size() > 0)
    {
     Intent intentChooser = Intent.createChooser(intentsList.remove(intentsList.size() - 1), mContext.getResources().getString(R.string.mediapicker));
     intentChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentsList.toArray(new Parcelable[]{}));
     return (intentChooser);
    }
 }
 catch (Exception e)
 {
    e.printStackTrace();
 }
 return (null);
}

Assumes mContext = activity context. mPhoto is a class variable of type Uri, used for accessing the picture acquired from the camera in your onActivityResult handler.

Hope this helps!

看看Mario Velasco的 回答是否对您有帮助。

Ok, so I've figured out part of the problem in the meantime.

I had stated the needed permissions in the manifest, like:

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

But, I made a begginer mistake by not asking explicitly for access to the device's camera and storage, as in:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);
        }
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }
    }

The part for Android 5.0+ works (the code was ok to begin with), and there's a menu where you can choose between the camera or pics from the gallery.

Either way, I've also tested user CSmith's suggestion for 5.0+ and confirmed it also works, so if anyone ever runs into this, it's a viable alternative you can try.

For Android versions older than 5, I've managed to make clicking the "Choose file" (but no gallery option) button open the Camera app with some changes, like this:

public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
            mUM = uploadMsg;
            Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(i, 1);
        }

And I'm using this "fix" for 3 and 4, for now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM