Reputation: 5893
I'm firing a Camera Intent to take photos with the Camera Application. It's working as expected in my default version of the App.
I've implemented the same code for "Android for Work"
version of my application which ended up with a weird behaviour. Normally, according to "Android for Work"
videos, an Intent cannot be handled if it's in a different profile. E.g, if I don't have a Camera Application installed in my Work Profile, Camera Intent should be null after it's resolved, which is expected.
But in my case, Camera Intent is handled by the Camera Application installed in my default user profile (Work Profile
doesn't have a Camera Application). And when the picture is taken, it comes back to onActivityResult
with a resultCode
Activity.RESULT_CANCELED
.
So, my questions is, How can I distinguish the User's Real Cancel Event
and this situation ? Both of them has the same result, Activity.RESULT_CANCELED
Here is the Code Below showing how I fire the Camera Intent.
/* Create Camera Intent */
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
/* Check if the Camera Intent is Available */
if (cameraIntent.resolveActivity(getActivity().getPackageManager()) == null) {
/* Notify User in Error Case */
UIUtils.notifyUser(getActivity(), getString(R.string.error), getString(R.string.no_camera_application_found));
} else {
/* Create a new File with Random Photo Name */
takenPhoto = new File(FileUtils.getExternalPhotoCacheDirectory(), generatePhotoName());
takenPhoto.createNewFile();
/* Create Uri to send to within the Intent */
Uri outputFileUri = Uri.fromFile(takenPhoto);
/* Set Photo destination File Uri */
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
/* Start Activity for Result */
startActivityForResult(cameraIntent, ACTION_TAKE_PHOTO);
}
EDIT : Here some Screen Shots from my admin panel.
Upvotes: 3
Views: 2487
Reputation: 199805
As per the setCameraDisabled() method for DevicePolicyManager:
Called by an application that is administering the device to disable all cameras on the device, for this user. After setting this, no applications running as this user will be able to access any cameras on the device.
Hence, only apps running on the work profile will be unable to access the Camera - as it reads, this does not affect the default user profile.
The admin app would need to call addCrossProfileIntentFilter() with the FLAG_PARENT_CAN_ACCESS_MANAGED to disable intents from work profile apps being able to be resolved on the parent (default user) apps if they don't want any intents being sent from the Work profile to the user profile.
Now, if you want your app using ACTION_IMAGE_CAPTURE
to work on a work profile, you can follow these instructions:
Each user on Android has an entirely sandboxed storage space, including public storage directories. This means that the default user profile Camera app cannot read any file directories accessible to a work profile app.
Instead, you need to provide a URI that they can write to such as one returned by a FileProvider as explained in the file sharing training.
/* Create a new File with Random Photo Name */
takenPhoto = new File(getActivity().getCacheDir(), generatePhotoName());
takenPhoto.createNewFile();
/* Create Uri to send to within the Intent */
Uri outputFileUri = FileProvider.getUriForFile(getActivity(),
"your.authority.read.the.docs", takenPhoto);
/* Set Photo destination File Uri */
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
Important to note that the file here is being saved to your app's cache directory - not to a public storage location.
You'll also need to include Uri based permissions as well:
cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
cameraIntent.setClipData(ClipData.newRawUri(null, outputFileUri));
Usually, only the Uri included in setData(uri)
is given permission, but any Uri also included in clip data will be given permission as well, allowing the Camera app the ability to read and write your MediaStore.EXTRA_OUTPUT
Uri.
Upvotes: 1