1

I have this code which allows users to access the camera to take photos and select images from gallery, it works on my Sony Xperia Z3 running Android 5.1.1.

I now have upgraded to a Nexus 5X running Android 6.0, but when i try to use the camera or save an image i get errors any help?

My Code to use Camera

Intent CameraImage = new Intent("android.media.action.IMAGE_CAPTURE");
Intent SelectedCameraImage = Intent.createChooser(CameraImage, "Take A Photo With");
startActivityForResult(SelectedCameraImage, SELECTED);

My Result Handler

public void onActivityResult(int RequestCode, int ResultCode, Intent Data) {
    if (ResultCode == RESULT_OK) {
        if (RequestCode == SELECTED) {
            Uri SelectedImageUri = Data.getData();
            SelectedImagePath = getPath(SelectedImageUri);
            Log.d("DatabaseOperations", "Image Path :  " + SelectedImagePath);
            Img.setImageURI(SelectedImageUri);

            try {
                FileInputStream FileInpStream = new FileInputStream(SelectedImagePath);
                BufferedInputStream BufInputStream = new BufferedInputStream(FileInpStream);
                DBByte = new byte[BufInputStream.available()];
                BufInputStream.read(DBByte);
                Log.d("DatabaseOperations", "Image Size :  " + DBByte.length + " KB");
            }

            catch (IOException e) {
                Log.d("DatabaseOperations", "Error :  " + SelectedImagePath);
                Log.d("DatabaseOperations", e.getMessage(), e);
            }
        }
    }
}

public String getPath(Uri Uris) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor Cursor = managedQuery(Uris, projection, null, null, null);
    int ColumnIndex = Cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    Cursor.moveToFirst();
    return Cursor.getString(ColumnIndex);
}

My Manifest Permissions

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

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

The Errors (Logcat)

FATAL EXCEPTION: main
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime: Process: rajancorporations.database, PID: 3768
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime: java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE cmp=com.google.android.GoogleCamera/com.android.camera.CaptureActivity } from ProcessRecord{c9f94d7 3768:rajancorporations.database/u0a80} (pid=3768, uid=10080) with revoked permission android.permission.CAMERA
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.os.Parcel.readException(Parcel.java:1620)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.os.Parcel.readException(Parcel.java:1573)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2658)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.app.Instrumentation.execStartActivity(Instrumentation.java:1507)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.app.Activity.startActivityForResult(Activity.java:3930)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.app.Activity.startActivityForResult(Activity.java:3890)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:784)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at rajancorporations.database.Reg$2.onClick(Reg.java:75)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.view.View.performClick(View.java:5204)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.view.View$PerformClick.run(View.java:21153)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:739)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:148)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5417)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
03-01 22:12:44.071 3768-3768/rajancorporations.database E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
RexDough
  • 181
  • 1
  • 11
  • 1
    Always show the errors. – Doug Stevenson Mar 01 '16 at 22:39
  • it just says for image storage /storage/emulated/0/Pictures/RajanDP.jpg: open failed: EACCES (Permission denied) – RexDough Mar 01 '16 at 22:42
  • and for the camera java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE cmp=com.google.android.GoogleCamera/com.android.camera.CaptureActivity } from ProcessRecord{c9f94d7 3768:rajancorporations.database/u0a80} (pid=3768, uid=10080) with revoked permission android.permission.CAMERA – RexDough Mar 01 '16 at 22:43
  • It's advisable to edit the question and format your logcat errors as code to make them easy to read. – Doug Stevenson Mar 01 '16 at 22:45
  • What errors are you getting? Is your `compileSdkVersion = 23`? If so, you need to make sure you are asking for [permission in run-time](http://developer.android.com/training/permissions/requesting.html). – Chris Arriola Mar 01 '16 at 22:43
  • my errors are shown in the comments and i am building in API 23 max but API 22 min. the code is ok in API 22 Devices but not on API 23 Devices – RexDough Mar 01 '16 at 22:44
  • ` java.lang.SecurityException` typically means the user has not yet granted permission. Requesting for permission in run-time should solve your problem. See the link above. – Chris Arriola Mar 01 '16 at 23:09

2 Answers2

3

Here is my complete code for taking image from camera or Gallery and it is working fine in marshmallow with others.

Here i am Declaring Varriables

protected static final int CAMERA_REQUEST = 0;
protected static final int GALLERY_REQUEST = 1;
private static final int REQUEST_ACESS_STORAGE=3;
private static final int REQUEST_ACESS_CAMERA=2;
private Uri uri;

Here i have some Methods for permission in marshmallow

public static boolean checkPermission(String permission, Context context) {
    int statusCode = ContextCompat.checkSelfPermission(context, permission);
    return statusCode == PackageManager.PERMISSION_GRANTED;
}

public static void requestPermission(AppCompatActivity activity, String[] permission, int requestCode) {
    if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission[0])) {
        Toast.makeText(activity, "Application need permission", Toast.LENGTH_SHORT).show();
    }
    ActivityCompat.requestPermissions(activity, permission, requestCode);
}

public static void requestPermission(Fragment fragment, String[] permission, int requestCode) {
    fragment.requestPermissions(permission, requestCode);
}

My onclick method

if (v.getId()==R.id.idOfPhoto){
            handleCamera();
        }

Details of handle camera method

private void handleCamera(){
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M) {
            if (checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, this)) {
                startDilog();
            }else{
               requestPermission(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},REQUEST_ACESS_STORAGE);
            }
        }else{
            startDilog();
        }
    }

startdilog method

private void startDilog() {
    AlertDialog.Builder myAlertDilog = new AlertDialog.Builder(YourActivity.this);
    myAlertDilog.setTitle("Upload picture option..");
    myAlertDilog.setMessage("Where to upload picture????");
    myAlertDilog.setPositiveButton("Gallery", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            Intent picIntent = new Intent(Intent.ACTION_GET_CONTENT,null);
            picIntent.setType("image/*");
            picIntent.putExtra("return_data",true);
            startActivityForResult(picIntent,GALLERY_REQUEST);
        }
    });
    myAlertDilog.setNegativeButton("Camera", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
                if(checkPermission(Manifest.permission.CAMERA,YourActivity.this)){
                    openCameraApplication();
                }else{
                    requestPermission(YourActivity.this,new String[]{Manifest.permission.CAMERA},REQUEST_ACESS_CAMERA);
                }
            }else{
                openCameraApplication();
            }
        }
    });
    myAlertDilog.show();
}

openCameraApplication method

private void openCameraApp() {
    Intent picIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (picIntent.resolveActivity(getPackageManager())!= null){
        startActivityForResult(picIntent, CAMERA_REQUEST);
    }
}

Rest of code

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == GALLERY_REQUEST) {
        if (resultCode == RESULT_OK) {
            if (data != null) {
                uri = data.getData();
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                try {
                    BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                    options.inSampleSize =calculateInSampleSize(options, 100, 100);
                    options.inJustDecodeBounds = false;
                    Bitmap image = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                    imageview.setImageBitmap(image);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                Toast.makeText(getApplicationContext(), "Cancelled",
                        Toast.LENGTH_SHORT).show();
            }
        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplicationContext(), "Cancelled",
                    Toast.LENGTH_SHORT).show();
        }
    } else if (requestCode == CAMERA_REQUEST) {
        if (resultCode == RESULT_OK) {
            if (data.hasExtra("data")) {
                Bitmap bitmap = (Bitmap) data.getExtras().get("data");
                uri = getImageUri(YourActivity.this, bitmap);
                File finalFile = new File(getRealPathFromUri(uri));
                imageview.setImageBitmap(bitmap);
            } else if (data.getExtras() == null) {

                Toast.makeText(getApplicationContext(),
                        "No extras to retrieve!", Toast.LENGTH_SHORT)
                        .show();

                BitmapDrawable thumbnail = new BitmapDrawable(
                        getResources(), data.getData().getPath());
                owner_pic.setImageDrawable(thumbnail);

            }

        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplicationContext(), "Cancelled",
                    Toast.LENGTH_SHORT).show();
        }
    }
}

private String getRealPathFromUri(Uri tempUri) {
    Cursor cursor = null;
    try {
        String[] proj = {MediaStore.Images.Media.DATA};
        cursor = this.getContentResolver().query(tempUri, proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}
private Uri getImageUri(YourActivity youractivity, Bitmap bitmap) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
    String path = MediaStore.Images.Media.insertImage(youractivity.getContentResolver(), bitmap, "Title", null);
    return Uri.parse(path);

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }



@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode==REQUEST_ACESS_STORAGE && grantResults[0]== PackageManager.PERMISSION_GRANTED){
        startDilog();
    }
    if(requestCode==REQUEST_ACESS_CAMERA && grantResults[0]==PackageManager.PERMISSION_GRANTED){
        openCameraApp();
    }
}

it's working fine in witth all devices..

Tanmay Sahoo
  • 471
  • 1
  • 6
  • 16
1

First, you assume that Data.getData() is meaningful here. There is no Uri returned by ACTION_IMAGE_CAPTURE, according to the specification. Your options are either to supply EXTRA_OUTPUT (in which case, the image should be where you indicate in that extra), or to get a thumbnail back from Data.getExtra("data"). There may be a few camera apps that do return a Uri. But there are over 8,000 Android device models, with hundreds, if not thousands, of different default camera apps. The user might also be having your request be handled by a third-party camera app. Most camera apps will give you a null value for Data.getData().

Second, even if you get a Uri, you assume that the Uri is known to the MediaStore. That is not required.

Third, even if you get a Uri and it is is known to the MediaStore, you assume that the DATA column is a path to a local file that you can access. This is not required. For example, it might be a path to removable storage, which you cannot access on Android 4.4+.

To address those three problems, use EXTRA_OUTPUT to designate where you want the camera to store the picture, and get rid of getPath() and your dependence upon the Uri.

Fourth, when working with external storage on Android 6.0+, if your targetSdkVersion is 23 or higher, you need to request READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE from the user at runtime. The same holds true for the CAMERA permission.

Fifth, do not have <uses-permission> and <uses-permission-sdk-23> for the same permissions. In your case, use <uses-permission>.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • its easier to store the image path to a database which is what i do with the selected image, and i'll try the run time permissions, how will i do this in the activity code, can i see an example – RexDough Mar 01 '16 at 22:57
  • @RexDough: "its easier to store the image path to a database which is what i do with the selected image" -- what is "easier" does not matter. If you rely upon the `Uri`, **you may not have an image path**, as **you may not get a `Uri`**. "how will i do this in the activity code" -- https://github.com/commonsguy/cw-omnibus/tree/master/Permissions/tutorial/finish/RuntimePermTutorial – CommonsWare Mar 01 '16 at 23:02