Camera intent is not working properly in android version 11 - java

I have try some following solution to captured image on android version 11. But this solution are not working. when I use bitmap that time I get blur image this Is not visible properly.I have added the below code in the manifest.
android:requestLegacyExternalStorage="true" ` Add this top stored image in external storage`
<queries>
<intent>`
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
</queries>
// add code in class call image Intent
public static Intent getPickImageIntent(Context context) {
mContext = context;
Intent chooserIntent = null;
List<Intent> intentList = new ArrayList<>();
Intent pickIntent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// takePhotoIntent.putExtra("return-data", true);
// takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile(context)));
intentList = addIntentsToList(context, intentList, pickIntent);
intentList = addIntentsToList(context, intentList, takePhotoIntent);
if (intentList.size() > 0) {
chooserIntent = Intent.createChooser(intentList.remove(intentList.size() - 1),
context.getString(R.string.pick_image_intent_text));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new Parcelable[]{}));
}
return chooserIntent;
}
when I add temp file path then this is not working in above API level 30
// pass image uri to activity set image in imageview
public static Uri getImageFromResultUri(Context context, int resultCode,
Intent imageReturnedIntent) {
File imageFile = getTempFile(context);
Uri selectedImage = null;
int sdkVersion = Build.VERSION.SDK_INT;
if (resultCode == Activity.RESULT_OK) {
boolean isCamera = (imageReturnedIntent == null ||
imageReturnedIntent.getData() == null ||
imageReturnedIntent.getData().toString().contains(imageFile.toString()));
if (isCamera) { /** CAMERA **/
// selectedImage = Uri.fromFile(imageFile);
Bitmap photo = (Bitmap) imageReturnedIntent.getExtras().get("data");
selectedImage = getImageUri(context,photo);
} else { /** ALBUM **/
selectedImage = imageReturnedIntent.getData();
}
}
return selectedImage;
}
when I convert Bitmap image to URI
public static Uri getImageUri(Context mContext, Bitmap inImage){
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG,100,bytes);
String path = MediaStore.Images.Media.insertImage(mContext.getContentResolver(),inImage,"Title",null);
return Uri.parse(path);
}
when I convert the image bitmap to URI I get a thumbnail so this is a blur so how can I get an image in android version 11 without using a bitmap. And I don't what to store this image in the gallery. Image is getting blur in every device.
When I use takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile(context))); this code then this is working properly in below version 11. but how can I use same code for android version 11

Uri.fromFile(getTempFile(context)));
You should use FileProvider and FileProvider.getUriForFile() instead to provide a valid uri to camera intent.
Also for versions below Android 11;

which is your target API version? requestLegacyExternalStorage will work only when targetting at most Android 10, when targetting Android 11 you have to use Scoped Storage, thus implement support for this feature. without this implementation you won't be able to access files outside your private app folder on Android 11+ devices

Related

how to save high quality image to phone gallery by camera intent

I am trying to develop app which save image to gallery.
I want to call the camera through intent, capture images, and save it locally in the gallery
but the issue is image quality is very poor. can anyone help me figure out why?
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
someActivityResultLauncher.launch(cameraIntent);}
#Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == RESULT_OK) {
bitmap = (Bitmap) Objects.requireNonNull(result.getData()).getExtras().get("data");
}
imageView.setImageBitmap(bitmap);
saveimage(bitmap);
}
private void saveimage(Bitmap bitmap){
Uri images;
ContentResolver contentResolver = getContentResolver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
images = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
}else {
images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, System.currentTimeMillis() +".jpg");
contentValues.put(MediaStore.Images.Media.MIME_TYPE, "images/*");
Uri uri = contentResolver.insert(images, contentValues);
try {
OutputStream outputStream = contentResolver.openOutputStream(Objects.requireNonNull(uri));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
Objects.requireNonNull(outputStream);
//
}catch (Exception e){
//
e.printStackTrace();
}
}
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
if you get image from data directly, it's in bad quality
Your code is the legacy equivalent of using ActivityResultContracts.TakePicturePreview. It is specifically set up to return a low-resolution bitmap, suitable for a preview.
Instead, use ActivityResultContracts.TakePicture, and supply your destination Uri as part of the contract.
See this and this for more.

Converting Bitmap into a valid Uri

I am developing an android app where user is selecting the image either from gallery or capture from camera. When user get the image from gallery i get the image uri then i pass this uri to other activity in string form. then in next activity i convert that string into uri and then uri into bitmap and set the image bitmap in imageview. Now when i capture the image from camera i get the image bitmap.
Now i want to convert this bitmap into valid uri and pass to next activity
if(requestCode==GET_FROM_GALLERY && resultCode == Activity.RESULT_OK) {
Uri selectedImage = data.getData();
System.out.println("URLLL "+selectedImage);
Log.v("PhotoActivity", "Captured image");
//Create intent
Intent intent = new Intent(MainActivity.this, FlagDisplayActivity.class);
intent.putExtra("URI", selectedImage.toString());
//Start Flag Display activity
startActivity(intent);
Log.v("PHOTO ACTIVITY", " uri: " + selectedImage);
}
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK)
{
Bitmap photo = (Bitmap) data.getExtras().get("data");
Intent intent = new Intent(MainActivity.this, FlagDisplayActivity.class);
intent.putExtra("URI", photo);
//Start Flag Display activity
startActivity(intent);
}
This is how i get the uri in next activity
String imageUriString=getIntent().getStringExtra("URI");
final Uri selectedImage=Uri.parse(imageUriString);
and then convert the uri into bitmap like this
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),
selectedImage);
} catch (IOException e) {
e.printStackTrace();
bitmap=StringToBitMap(imageUriString);
}
My main goal is to convert the bitmap into uri
You write your Bitmap into the local Cache of the Application and retrieve it from there.
Bitmap photo = (Bitmap) data.getExtras().get("data");// Get the Bitmap
val file = File(context.cacheDir,"CUSTOM NAME") //Get Access to a local file.
file.delete() // Delete the File, just in Case, that there was still another File
file.createNewFile()
val fileOutputStream = file.outputStream()
val byteArrayOutputStream = ByteArrayOutputStream()
photo.compress(Bitmap.CompressFormat.PNG,100,byteArrayOutputStream)
val bytearray = byteArrayOutputStream.toByteArray()
fileOutputStream.write(bytearray)
fileOutputStream.flush()
fileOutputStream.close()
byteArrayOutputStream.close()
val URI = file.toURI()
Now you can send the URI to another Activity as a String and retrieve the URI from the String and get the Bitmap from the URI.
Intent intent = new Intent(MainActivity.this, FlagDisplayActivity.class);
intent.putExtra("URI", URI.toString());
//Start Flag Display activity
startActivity(intent);
Provide the path of image it will provide you image uri
Uri selectedImageURI = data.getData();
File imageFile = new File(getRealPathFromURI(selectedImageURI));
Uri yourUri = Uri.fromFile(f);
Use the following function so you will get image
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
Try this:
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
imageView.setImageBitmap(bitmap);

I can't save file to gallery after taking photo by camera by using the FileProvider for Android 7.1.1

I build my app with FileProvider and I want to save the image after I take it. But I can't find the image in the gallery.
I found these source codes from the Android Studio tutorial. I don't know what is the problem. I tried use debugger and I think the createFile() is correct. I also have my bitmap works. It can display the image I take but I can't add the image to the gallery.
I have this in my Manifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.temp.test"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"/>
</provider>
And in the file_paths.xml I have
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external" path="Android/data/com.temp.test/files/Pictures" />
</paths>
This is how I write the activity
private String mCurrentPhotoPath;
private ImageView mImageView;
private ImageButton StartCameraBtn;
private File photoFile = null;
//requestCode
private static final int REQUEST_IMAGE_CAPTURE = 1;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo_note);
mImageView = (ImageView) findViewById(R.id.imageView);
StartCameraBtn = (ImageButton) findViewById(R.id.StartCamera);
StartCameraBtn.setOnClickListener(this);
}
public void onClick(View view)
{
clearAllFocus();
switch (view.getId())
{
case R.id.StartCamera:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null)
{
try
{
photoFile = createFile();
}
catch (IOException e)
{
e.printStackTrace();
}
if(photoFile != null){
Uri photoURI = FileProvider.getUriForFile(this,
"com.temp.test",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
break;
...
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
mImageView.setImageBitmap(null);
switch (requestCode)
{
case REQUEST_IMAGE_CAPTURE:
if (resultCode == RESULT_OK)
{
setPic();
galleryAddPic();
}
break;
}
}
private File createFile() throws IOException
{
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
private void galleryAddPic()
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
private void setPic()
{
// Get the dimensions of the View
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
mImageView.setImageBitmap(bitmap);
}
Please help! Thank you!
I use debugger to test the galleryaddpic() and the URI has been accessed sucessfully, but I don't know why I can't add it to the gallery. I can't find the image file in the android VM directory either.
This is the debug log:
https://i.stack.imgur.com/JN9uJ.png
I'm using chickendinner as my domian, and keep is the name of my app.
Thank you!
Call this function in onActivityResult. It worked for me!
It is in fragment.In activity you can use "this" instead of "getActivity()".
private void galleryAddPic() {
File f = new File(imageFilePath); //set your picture's path
try {
MediaStore.Images.Media.insertImage(getActivity().getContentResolver(),
f.getAbsolutePath(), f.getName(), null);
getActivity().sendBroadcast(new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Your code handles
write new photo as a jpg-file to the filesystem
add new photo to media-db via broadcst Intent.ACTION_MEDIA_SCANNER_SCAN_FILE
create a FileProvider that allow other apps to access private //Android/data/com.temp.test/files/Pictures/... files through a content-uri content://com.temp.test/...
I assume that the media-db scanner has no read-permission to your app-s private data directory Android/data/com.temp.test/files/Pictures via a file-uri and therefore cannot add the new photo to media-db.
Whatsapp and other apps store their received/send photo in public readable internal memory (i.e. /sdcard/PICTURES/WhatsApp/ ) where the media scanner can read it via file-uri via Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.
I donot know, if the media scanner can handle content: -uris instead of file uri-s: You can try this:
private void galleryAddPic()
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
// assume that mCurrentPhotoPath ="Android/data/com.temp.test/files/Pictures/myTestImage.jpg"
// can be accessed from outside as "content://com.temp.test/myTestImage.jpg"
Uri contentUri = Uri.parse("content://com.temp.test/myTestImage.jpg");
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
Please let us know if this works.
If this does not work you can try to manually insert a "content://com.temp.test/..." entry into media database.
using public readable internal memory directories should work without a fileprovider

Issue with an intent working on Lollipop and older, but not on newer

I am currently working on an activity that will let the user select an image from the gallery, and then put that image's URI into an SQLite database.
I have another activity where I take that URI and display it on an ImageView. I have this working perfectly on Lollipop and older. But anything newer it crashes when I pull up the activity that displays the image.
Here is the LOGCAT line of the crash:
Caused by: java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.contentprovider.MediaContentProvider from ProcessRecord{8193e94 13574:jeremy.com.wineofmine/u0a97} (pid=13574, uid=10097) that is not exported from uid 10044
This makes it seem like a permissions thing, but I am requesting the WRITE_EXTERNAL_STORAGE and READ_EXTERNAL STORAGE in the manifest, as well as requesting those permissions on run-time on the activity where it displays the image.
And here is the exact line where it's crashing (this is in the activity where it displays the image:)
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageURI);
And this is imageURI:
imageURI = Uri.parse(cursor.getString(cursor.getColumnIndexOrThrow(WineContract.WineEntry.COLUMN_WINE_IMAGE)));
//This code returns this: content://com.google.android.apps.photos.contentprovider/-1/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F62/ACTUAL/860591124
Here is the code to the relevant bits.
This is the intent to open up the gallery:
Intent intentGallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intentGallery, SELECT_IMAGE);
And this is the onActivityResult method. The main goal of this method is to set the imageThumbail ImageView as the thumbnail, and also to set "photoURI" as the selected image's URI.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//This is if they choose an image from the gallery
if (requestCode == SELECT_IMAGE && resultCode == RESULT_OK) {
if (requestCode == SELECT_IMAGE) {
// Get the url from data
Uri selectedImageUri = data.getData();
if (null != selectedImageUri) {
// Get the path from the Uri
String path = getPathFromURI(selectedImageUri);
Log.i("ADDACTIVITY", "Image Path : " + path);
bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImageUri);
} catch (IOException e) {
e.printStackTrace();
}
bitmapThumbnail = ThumbnailUtils.extractThumbnail(bitmap,175,175);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmapThumbnail.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byteArray = stream.toByteArray();
// Set the image in ImageView
imageThumbnail.setImageBitmap(bitmapThumbnail);
//Setting photoURI (which gets put into the database) as the gallery's image URI
photoURI = data.getData();
}
}
}
}
Any pointers to what I could be doing wrong, would be great.

How to persist permission in android API 19 (KitKat)?

In my application I store the path of image in my SQlite db for further use. The path that I get is
content://com.android.providers.media.documents/document/image%3A71964
When I retrieve this path from the database and try to retrieve the image from that path android throws
java.lang.SecurityException: Permission Denial: opening provider
com.android.providers.media.MediaDocumentsProvider
from ProcessRecord{42c84ec8 23911:com.gots.gb/u0a248} (pid=23911, uid=10248)
requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
According https://developer.android.com/guide/topics/providers/document-provider.html#permissions I need to persist permission by adding the following code
final int takeFlags = intent.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(uri, takeFlags);
When I added this code to my ImageAdapter class which extends BaseAdapter android throws
08-21 02:14:38.530: W/System.err(24452): java.lang.SecurityException:
No permission grant found for UID 10248 and Uri
content://com.android.providers.media.documents/document/image:71964
This is the relevant part of my ImageAdapter code
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView ;
if (convertView == null){
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(185, 185));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
}
else{
imageView = (ImageView)convertView ;
}
InputStream is = null;
Bitmap bitmap = null ;
try {
Log.d(TAG,String.valueOf(list.get(position)));
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
final int takeFlags = intent.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
if (Build.VERSION.SDK_INT >= 19){
mContext.getContentResolver().takePersistableUriPermission(list.get(position), takeFlags);
}
is = mContext.getContentResolver().openInputStream(list.get(position));
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
bitmap = BitmapFactory.decodeStream(is,null, options);
is.close();
imageView.setImageBitmap(bitmap);
return imageView;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
what am I doing wrong?
Thanks
I believe I've solved it. The request intent:
Intent intent;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
}else{
intent = new Intent(Intent.ACTION_GET_CONTENT);
}
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent, getResources().getString(R.string.form_pick_photos)), REQUEST_PICK_PHOTO);
and onActivityResult
...
// kitkat fixed (broke) content access; to keep the URIs valid over restarts need to persist access permission
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final int takeFlags = data.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION;
ContentResolver resolver = getActivity().getContentResolver();
for (Uri uri : images) {
resolver.takePersistableUriPermission(uri, takeFlags);
}
}
...
I haven't tested this pre-kitkat, my phone is running 5.1, can anyone verify this on older phones?
The code listed below,
// kitkat fixed (broke) content access; to keep the URIs valid over restarts need to persist access permission
if(Utils.isKitkat())
{
final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION);
ContentResolver resolver = getActivity().getContentResolver();
for (Uri uri : images)
{
resolver.takePersistableUriPermission(uri, takeFlags);
}
}
worked fine for me, anyway I noticed that the max number of persistable uri granted to my app is limited to 128. If I select more than 128 uri, I get the error:
java.lang.SecurityException: Permission Denial: opening provider........
just when I try to process an image for which I wasn't able to persist the permission. Can you figure out any solution?

Categories

Resources