Xamarin.Android - "resolveURI failed on bad bitmap URI" after parsing encoded string - android

I am trying to display an image from a local URI when this activity begins.
The user selects an image, triggering the OnActivityResult() method. When I first obtain the URI, it displays the image with no problem:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (requestCode == IMG_REQUEST_CODE && resultCode == Result.Ok)
{
Android.Net.Uri imageUri = null;
if (data != null)
{
imageUri = data.Data;
userPreferences.BackgroundImageURI = imageUri.ToString();
imgView.SetImageURI(imageUri);
imgView.Visibility = ViewStates.Visible;
}
}
}
As you can see, I am storing the URI as an encoded string in userPreferences. This is saved to the device, and can be loaded with no issue. In this case the string is content://com.android.providers.media.documents/document/image%3A38, and it is identical when loaded from memory (using Shared Preferences).
Here is my code for loading the encoded URI string, parsing the string to create a URI, and then setting URI of imgView to display that image.
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Preferences);
userPreferences = Helpers.LoadUserPreferences(this, new Shared.Model.UserPreferences());
imgView = FindViewById<ImageView>(Resource.Id.imgView);
if (!string.IsNullOrWhiteSpace(userPreferences.BackgroundImageURI))
{
var imgURI = Android.Net.Uri.Parse(userPreferences.BackgroundImageURI);
imgView.SetImageURI(imgURI);
imgView.Visibility = ViewStates.Visible;
}
else
{
imgView.Visibility = ViewStates.Invisible;
}
}
When it gets to the SetView(imgUri) line, I receive this output: resolveUri failed on bad bitmap uri: content://com.android.providers.media.documents/document/image%3A38
I have even tried hard-coding the URI to no avail. The main frustration is that the code is identical, just running in two different scenarios. Is it possible that it has to do with the Activity lifecycle? Or have I missed something bigger?

Try this:
if (!string.IsNullOrWhiteSpace(userPreferences.BackgroundImageURI))
{
var imgURI = Android.Net.Uri.Parse(userPreferences.BackgroundImageURI);
var input = Activity.ContentResolver.OpenInputStream(imgURI);
imgView.SetImageBitmap(BitmapFactory.DecodeStream(input));
imgView.Visibility = ViewStates.Visible;
}
else
{
imgView.Visibility = ViewStates.Invisible;
}
As alternative I have a class that get the real path for the image from a URI. It could be great if you want to give that path to a CropActivity for example.
You can download the class from here.
And use it like this:
if (!string.IsNullOrWhiteSpace(userPreferences.BackgroundImageURI))
{
var imgURI = Android.Net.Uri.Parse(userPreferences.BackgroundImageURI);
imgView.SetImageURI (Uri.Parse(PathUtils.PathUtils.GetPath(Activity, imgURI)));
imgView.Visibility = ViewStates.Visible;
}
else
{
imgView.Visibility = ViewStates.Invisible;
}

Related

Convert data from image picker intent into bitmap (Kotlin)?

I'm currently trying to save whatever image the user picks into a room database, and it looks like the only way to do this is to first save it as a bitmap. However, I'm not sure how I would do this.
This is the code that I have right now: it lets the user pick an image and displays it in an imageview after. However, I don't know how I could convert my data?.data into a bitmap.
I apologize if this wasn't a very good question, I'm very new to dealing with images and image types in android apps. Any help would be greatly appreciated!
// Opens gallery when image button clicked, gets image
view.image_et.setOnClickListener {
readStorageTask()
//Intent to pick image
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, 1001)
}
// Handle result of picked image
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && requestCode == 1001) {
preview_image.setImageURI(data?.data)
}
}
I've seen some StackOverflow questions similar to mine dealing with the same issue in Java, but the ones that I've tried just haven't worked for me. Any help would be greatly appreciated!
You can create a file in cache directory, then create bitmap
if (data != null && data.data != null) {
val uri = data.data!!
val inputStream = requireContext().contentResolver.openInputStream(uri)
val cursor = requireContext().contentResolver.query(uri, null, null, null, null)
cursor?.use { c ->
val nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME)
if (c.moveToFirst()) {
val name = c.getString(nameIndex)
inputStream?.let { inputStream ->
// create same file with same name
val file = File(requireContext().cacheDir, name)
val os = file.outputStream()
os.use {
inputStream.copyTo(it)
}
val bitmap = BitmapFactory.decodeFile(file.absolutePath)
}
}
}
}
Open an input stream for the obtained uri and then use BitmapFactory.decodeStream().
In Java:
InputStream is = getContentResolver().openInputStream(data.getData());
Bitmap bitmap = BitmapFactory.decodeStream(is);
That's all.

How to convert a content Uri into a File

I know there are a ton of questions about this exact topic, but after spending two days reading and trying them, none seamed to fix my problem.
This is my code:
I launch the ACTION_GET_CONTENT in my onCreate()
Intent selectIntent = new Intent(Intent.ACTION_GET_CONTENT);
selectIntent.setType("audio/*");
startActivityForResult(selectIntent, AUDIO_REQUEST_CODE);
retrieve the Uri in onActivityResult()
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == AUDIO_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
if ((data != null) && (data.getData() != null)) {
audio = data.getData();
}
}
}
pass the Uri to another activity and retrieve it
Intent debugIntent = new Intent(this, Debug.class);
Bundle bundle = new Bundle();
bundle.putString("audio", audio.toString());
debugIntent.putExtras(bundle);
startActivity(debugIntent);
Intent intent = this.getIntent();
Bundle bundle = intent.getExtras();
audio = Uri.parse((String) bundle.get("audio"));
The I have implemented this method based on another SO answer. To get the actual Path of the Uri
public static String getRealPathFromUri(Activity activity, Uri contentUri) {
String[] proj = { MediaStore.Audio.Media.DATA };
Cursor cursor = activity.managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
and in the Debug activity's onCreate() I try to generate the file:
File audioFile = new File(getRealPathFromUri(this, audio));
This is how the error looks like:
Caused by: java.lang.NullPointerException
at java.io.File.(File.java:262)
at com.dancam.lietome.Debug.onCreate(Debug.java:35)
When I run the app I get a NPE on this last line. The audio Uri, isn't NULL though so I don't understand from what it is caused.
I'd really appreciate if you helped me out.
This is the library I'm trying to work with.
Note: I know exactly what NPE is, but even debugging I couldn't figure out from what it is caused in this specific case.
pass the Uri to another activity and retrieve it
Your other activity does not necessarily have rights to work with the content identified by the Uri. Add FLAG_GRANT_READ_URI_PERMISSION to the Intent used to start that activity, and pass the Uri via the "data" facet of the Intent (setData()), not an extra.
To get the actual Path of the Uri
First, there is no requirement that the Uri that you get back be from the MediaStore.
Second, managedQuery() has been deprecated for six years.
Third, there is no requirement that the path that MediaStore has be one that you can use. For example, the audio file might be on removable storage, and while MediaStore can access it, you cannot.
How to convert a content Uri into a File
On a background thread:
Get a ContentResolver by calling getContentResolver() on a Context
Call openInputStream() on the ContentResolver, passing in the Uri that you obtained from ACTION_GET_CONTENT, to get an InputStream on the content identified by the Uri
Create a FileOutputStream on some File, where you want the content to be stored
Use Java I/O to copy the content from the InputStream to the FileOutputStream, closing both streams when you are done
I ran into same problem for Android Q, so I end up creating a new file and use input stream from content to fill that file
Here's How I do it in kotlin:
private var pdfFile: File? = null
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
when (requestCode) {
REQUEST_CODE_DOC -> {
data.data?.let {
if (it.scheme.equals("content")) {
val pdfBytes =
(contentResolver?.openInputStream(it))?.readBytes()
pdfFile = File(
getExternalFilesDir(null),
"Lesson ${Calendar.getInstance().time}t.pdf"
)
if (pdfFile!!.exists())
pdfFile!!.delete()
try {
val fos = FileOutputStream(pdfFile!!.path)
fos.write(pdfBytes)
fos.close()
} catch (e: Exception) {
Timber.e("PDF File", "Exception in pdf callback", e)
}
} else {
pdfFile = it.toFile()
}
}
}
}
}
}
}
Daniele, you can get path of file directly from data like below in onActivityResult():
String gilePath = data.getData().getPath();

activityForResult has no extras, trying to start camera [duplicate]

I have an android application which contains multiple activities.
In one of them I'm using a button which will call the device camera :
public void onClick(View view) {
Intent photoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(photoIntent, IMAGE_CAPTURE);
}
In the same activity I call the OnActivityResult method for the image result :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IMAGE_CAPTURE) {
if (resultCode == RESULT_OK) {
Bitmap image = (Bitmap) data.getExtras().get("data");
ImageView imageview = (ImageView) findViewById(R.id.pic);
imageview.setImageBitmap(image);
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "CANCELED ", Toast.LENGTH_LONG).show();
}
}
}
The problem is that the intent data is null and the OnActivityResult method turns directly to the (resultCode == RESULT_CANCELED) and the application returns to the previous avtivity.
How can I fix this issue and after calling the camera, the application returns to the current activity which contains an ImageView which will contains the picture taken?
Thanks
The default Android camera application returns a non-null intent only when passing back a thumbnail in the returned Intent. If you pass EXTRA_OUTPUT with a URI to write to, it will return a null intent and the picture is in the URI that you passed in.
You can verify this by looking at the camera app's source code on GitHub:
https://github.com/android/platform_packages_apps_camera/blob/gingerbread-release/src/com/android/camera/Camera.java#L1186
Bundle newExtras = new Bundle();
if (mCropValue.equals("circle")) {
newExtras.putString("circleCrop", "true");
}
if (mSaveUri != null) {
newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri);
} else {
newExtras.putBoolean("return-data", true);
}
I would guess that you're either passing in EXTRA_OUTPUT somehow, or the camera app on your phone works differently.
I found an easy answer. it works!!
private void openCameraForResult(int requestCode){
Intent photo = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = Uri.parse("file:///sdcard/photo.jpg");
photo.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(photo,requestCode);
}
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
File file = new File(Environment.getExternalStorageDirectory().getPath(), "photo.jpg");
Uri uri = Uri.fromFile(file);
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
bitmap = cropAndScale(bitmap, 300); // if you mind scaling
profileImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if you would like to crop and scale this image
public static Bitmap cropAndScale (Bitmap source, int scale){
int factor = source.getHeight() <= source.getWidth() ? source.getHeight(): source.getWidth();
int longer = source.getHeight() >= source.getWidth() ? source.getHeight(): source.getWidth();
int x = source.getHeight() >= source.getWidth() ?0:(longer-factor)/2;
int y = source.getHeight() <= source.getWidth() ?0:(longer-factor)/2;
source = Bitmap.createBitmap(source, x, y, factor, factor);
source = Bitmap.createScaledBitmap(source, scale, scale, false);
return source;
}
I´ve had experienced this problem, the intent is not null but the information sent via this intent is not received in onActionActivit()
This is a better solution using getContentResolver() :
private Uri imageUri;
private ImageView myImageView;
private Bitmap thumbnail;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
...
...
myImageview = (ImageView) findViewById(R.id.pic);
values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "MyPicture");
values.put(MediaStore.Images.Media.DESCRIPTION, "Photo taken on " + System.currentTimeMillis());
imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, PICTURE_RESULT);
}
the onActivityResult() get a bitmap stored by getContentResolver() :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_TAKE_PHOTO && resultCode == RESULT_OK) {
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
myImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Check my example in github:
https://github.com/Jorgesys/TakePicture
Simple working camera app avoiding the null intent problem
- all changed code included in this reply; close to android tutorial
I've been spending plenty of time on this issue, so I decided to create an account and share my outcomes with you.
The official android tutorial "Taking Photos Simply" turned out to not quite hold what it promised.
The code provided there did not work on my device: a Samsung Galaxy S4 Mini GT-I9195 running android version 4.4.2 / KitKat / API Level 19.
I figured out that the main problem was the following line in the method invoked when capturing the photo (dispatchTakePictureIntent in the tutorial):
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
It resulted in the intent subsequently catched by onActivityResult being null.
To solve this problem, I pulled much inspiration out of earlier replies here and some helpful posts on github (mostly this one by deepwinter - big thanks to him; you might want to check out his reply on a closely related post as well).
Following these pleasant pieces of advice, I chose the strategy of deleting the mentioned putExtra line and doing the corresponding thing of getting back the taken picture from the camera within the onActivityResult() method instead.
The decisive lines of code to get back the bitmap associated with the picture are:
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
I created an exemplary app which just has the ability to take a picture, save it on the SD card and display it.
I think this might be helpful to people in the same situation as me when I stumbled on this issue, since the current help suggestions mostly refer to rather extensive github posts which do the thing in question but aren't too easy to oversee for newbies like me.
With respect to the file system Android Studio creates per default when creating a new project, I just had to change three files for my purpose:
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.android.simpleworkingcameraapp.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="takePicAndDisplayIt"
android:text="Take a pic and display it." />
<ImageView
android:id="#+id/image1"
android:layout_width="match_parent"
android:layout_height="200dp" />
</LinearLayout>
MainActivity.java :
package com.example.android.simpleworkingcameraapp;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.Image;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private ImageView image;
static final int REQUEST_TAKE_PHOTO = 1;
String mCurrentPhotoPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.image1);
}
// copied from the android development pages; just added a Toast to show the storage location
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmm").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();
Toast.makeText(this, mCurrentPhotoPath, Toast.LENGTH_LONG).show();
return image;
}
public void takePicAndDisplayIt(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
File file = null;
try {
file = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
}
}
#Override
protected void onActivityResult(int requestCode, int resultcode, Intent intent) {
if (requestCode == REQUEST_TAKE_PHOTO && resultcode == RESULT_OK) {
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
image.setImageBitmap(bitmap);
}
}
}
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.simpleworkingcameraapp">
<!--only added paragraph-->
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- only crucial line to add; for me it still worked without the other lines in this paragraph -->
<uses-permission android:name="android.permission.CAMERA" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Note that the solution I found for the problem also led to a simplification of the android manifest file: the changes suggested by the android tutorial in terms of adding a provider are no longer needed since I am not making use of any in my java code. Hence, only few standard lines -mostly regarding permissions- had to be added to the manifest file.
It might additionally be valuable to point out that Android Studio's autoimport may not be capable of handling java.text.SimpleDateFormat and java.util.Date. I had to import both of them manually.
Probably because you had something like this?
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri fileUri = CommonUtilities.getTBCameraOutputMediaFileUri();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(takePictureIntent, 2);
However you must not put the extra output into the intent, because then the data goes into the URI instead of the data variable. For that reason, you have to take the two lines in the middle out, so that you have
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePictureIntent, 2);
That´s what caused the problem for me, hope that helped.
To Access the Camera and take pictures and set ImageView on Android
You have to use Uri file = Uri.fromFile(getOutputMediaFile()); for marshmallow.
Use below link to get path
https://androidkennel.org/android-camera-access-tutorial/
Kotlin code that works for me:
private fun takePhotoFromCamera() {
val intent = Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(intent, PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA)
}
And get Result :
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
val photo: Bitmap? = MediaStore.Images.Media.getBitmap(this.contentResolver, Uri.parse( data!!.dataString) )
// Do something here : set image to an ImageView or save it ..
imgV_pic.imageBitmap = photo
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.i(TAG, "Camera , RESULT_CANCELED ")
}
}
}
and don't forget to declare request code:
companion object {
const val PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA = 300
}
After much try and study, I was able to figure it out. First, the variable data from Intent will always be null so, therefore, checking for !null will crash your app so long you are passing a URI to startActivityForResult.Follow the example below.
I will be using Kotlin.
Open the camera intent
fun addBathroomPhoto(){
addbathroomphoto.setOnClickListener{
request_capture_image=2
var takePictureIntent:Intent?
takePictureIntent =Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if(takePictureIntent.resolveActivity(activity?.getPackageManager()) != null){
val photoFile: File? = try {
createImageFile()
} catch (ex: IOException) {
// Error occurred while creating the File
null
}
if (photoFile != null) {
val photoURI: Uri = FileProvider.getUriForFile(
activity!!,
"ogavenue.ng.hotelroomkeeping.fileprovider",photoFile)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
photoURI);
startActivityForResult(takePictureIntent,
request_capture_image);
}
}
}
}`
Create the createImageFile().But you MUST make the imageFilePath variable global. Example on how to create it is on Android official documentation and pretty straightforward
Get Intent
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 1 && resultCode == RESULT_OK) {
add_room_photo_txt.text=""
var myBitmap=BitmapFactory.decodeFile(imageFilePath)
addroomphoto.setImageBitmap(myBitmap)
var file=File(imageFilePath)
var fis=FileInputStream(file)
var bm = BitmapFactory.decodeStream(fis);
roomphoto=getBytesFromBitmap(bm) }}
The getBytesFromBitmap method
fun getBytesFromBitmap(bitmap:Bitmap):ByteArray{
var stream=ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
I hope this helps.
I used contentResolver to create the path and it worked.
var values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "MyPicture")
values.put(
MediaStore.Images.Media.DESCRIPTION,
"Photo taken on " + System.currentTimeMillis()
)
cameraUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, cameraUri);
startActivityForResult(cameraIntent, REQUEST_CODE)
it still occurs even now 2022, i fix it as follow:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // android7.0
photoUri= FileProvider.getUriForFile(
MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
new File(mCameraFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
} else {
photoUri = Uri.fromFile(new File(mCameraFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT,photoUri);
}
,oh...just add a viriable(photoUri) to your activity! then
filePathCallback.onReceiveValue(new Uri[]{ photoUri });
The following code works for me:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, 2);
And here is the result:
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent)
{
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
if(resultCode == RESULT_OK)
{
Uri selectedImage = imageReturnedIntent.getData();
ImageView photo = (ImageView) findViewById(R.id.add_contact_label_photo);
Bitmap mBitmap = null;
try
{
mBitmap = Media.getBitmap(this.getContentResolver(), selectedImage);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

Cannot use Poly Picker multiple image picker library in Android

I am developing an Android app. In my app, I want to let user to choose multiple when user clicks upload button. So I used this library. I can successfully pop up dialog and choose multiple files. But the problem is when I convert URI of selected images to bitmap in onActivityResult, it is giving me error.
This is how I pop up picker in activity:
private void getImages() {
Intent intent = new Intent(GalleryActivity.this, ImagePickerActivity.class);
nl.changer.polypicker.Config pickerConfig = new nl.changer.polypicker.Config(R.color.white,R.color.blue,10,R.color.green);
ImagePickerActivity.setConfig(pickerConfig);
startActivityForResult(intent, INTENT_REQUEST_GET_IMAGES);
}
This is how I am converting to bitmap on result:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == INTENT_REQUEST_GET_IMAGES) {
Parcelable[] parcelableUris = data.getParcelableArrayExtra(ImagePickerActivity.EXTRA_IMAGE_URIS);
if (parcelableUris == null) {
return;
}
// Java doesn't allow array casting, this is a little hack
Uri[] uris = new Uri[parcelableUris.length];
System.arraycopy(parcelableUris, 0, uris, 0, parcelableUris.length);
if (uris != null) {
bitmaps = new ArrayList<Bitmap>();
for (Uri uri : uris) {
try{
if(uri!=null)
{
Bitmap bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
bitmaps.add(bmp);
}
}
catch (IOException e)
{
Toast.makeText(getBaseContext(),e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
if(bitmaps.size()>0)
{
confirmFileUpload();
}
}
}
}
}
As you can see above my code, it will reach to io exception block of try-catch statement.
This is the example of error toasted:
That kind of error throw whatever image I select. What is wrong with my code and how can I fix it?
Finally I found the solution. I problem was when I parse uri to string, the format is something like this:
/sdcard/download/filename.png
The uri string must be in this format:
file:///sdcard/download/filename.png
No Content Provider Found exception throws because my uri string does not have required prefix. So I convert the uri to string. Then added the prefix. Then I parse that string to URI back. Then it worked successfully.

Android Camera : data intent returns null

I have an android application which contains multiple activities.
In one of them I'm using a button which will call the device camera :
public void onClick(View view) {
Intent photoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(photoIntent, IMAGE_CAPTURE);
}
In the same activity I call the OnActivityResult method for the image result :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IMAGE_CAPTURE) {
if (resultCode == RESULT_OK) {
Bitmap image = (Bitmap) data.getExtras().get("data");
ImageView imageview = (ImageView) findViewById(R.id.pic);
imageview.setImageBitmap(image);
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "CANCELED ", Toast.LENGTH_LONG).show();
}
}
}
The problem is that the intent data is null and the OnActivityResult method turns directly to the (resultCode == RESULT_CANCELED) and the application returns to the previous avtivity.
How can I fix this issue and after calling the camera, the application returns to the current activity which contains an ImageView which will contains the picture taken?
Thanks
The default Android camera application returns a non-null intent only when passing back a thumbnail in the returned Intent. If you pass EXTRA_OUTPUT with a URI to write to, it will return a null intent and the picture is in the URI that you passed in.
You can verify this by looking at the camera app's source code on GitHub:
https://github.com/android/platform_packages_apps_camera/blob/gingerbread-release/src/com/android/camera/Camera.java#L1186
Bundle newExtras = new Bundle();
if (mCropValue.equals("circle")) {
newExtras.putString("circleCrop", "true");
}
if (mSaveUri != null) {
newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri);
} else {
newExtras.putBoolean("return-data", true);
}
I would guess that you're either passing in EXTRA_OUTPUT somehow, or the camera app on your phone works differently.
I found an easy answer. it works!!
private void openCameraForResult(int requestCode){
Intent photo = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = Uri.parse("file:///sdcard/photo.jpg");
photo.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(photo,requestCode);
}
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
File file = new File(Environment.getExternalStorageDirectory().getPath(), "photo.jpg");
Uri uri = Uri.fromFile(file);
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
bitmap = cropAndScale(bitmap, 300); // if you mind scaling
profileImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if you would like to crop and scale this image
public static Bitmap cropAndScale (Bitmap source, int scale){
int factor = source.getHeight() <= source.getWidth() ? source.getHeight(): source.getWidth();
int longer = source.getHeight() >= source.getWidth() ? source.getHeight(): source.getWidth();
int x = source.getHeight() >= source.getWidth() ?0:(longer-factor)/2;
int y = source.getHeight() <= source.getWidth() ?0:(longer-factor)/2;
source = Bitmap.createBitmap(source, x, y, factor, factor);
source = Bitmap.createScaledBitmap(source, scale, scale, false);
return source;
}
I´ve had experienced this problem, the intent is not null but the information sent via this intent is not received in onActionActivit()
This is a better solution using getContentResolver() :
private Uri imageUri;
private ImageView myImageView;
private Bitmap thumbnail;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
...
...
myImageview = (ImageView) findViewById(R.id.pic);
values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "MyPicture");
values.put(MediaStore.Images.Media.DESCRIPTION, "Photo taken on " + System.currentTimeMillis());
imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, PICTURE_RESULT);
}
the onActivityResult() get a bitmap stored by getContentResolver() :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_TAKE_PHOTO && resultCode == RESULT_OK) {
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
myImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Check my example in github:
https://github.com/Jorgesys/TakePicture
Simple working camera app avoiding the null intent problem
- all changed code included in this reply; close to android tutorial
I've been spending plenty of time on this issue, so I decided to create an account and share my outcomes with you.
The official android tutorial "Taking Photos Simply" turned out to not quite hold what it promised.
The code provided there did not work on my device: a Samsung Galaxy S4 Mini GT-I9195 running android version 4.4.2 / KitKat / API Level 19.
I figured out that the main problem was the following line in the method invoked when capturing the photo (dispatchTakePictureIntent in the tutorial):
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
It resulted in the intent subsequently catched by onActivityResult being null.
To solve this problem, I pulled much inspiration out of earlier replies here and some helpful posts on github (mostly this one by deepwinter - big thanks to him; you might want to check out his reply on a closely related post as well).
Following these pleasant pieces of advice, I chose the strategy of deleting the mentioned putExtra line and doing the corresponding thing of getting back the taken picture from the camera within the onActivityResult() method instead.
The decisive lines of code to get back the bitmap associated with the picture are:
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
I created an exemplary app which just has the ability to take a picture, save it on the SD card and display it.
I think this might be helpful to people in the same situation as me when I stumbled on this issue, since the current help suggestions mostly refer to rather extensive github posts which do the thing in question but aren't too easy to oversee for newbies like me.
With respect to the file system Android Studio creates per default when creating a new project, I just had to change three files for my purpose:
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.android.simpleworkingcameraapp.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="takePicAndDisplayIt"
android:text="Take a pic and display it." />
<ImageView
android:id="#+id/image1"
android:layout_width="match_parent"
android:layout_height="200dp" />
</LinearLayout>
MainActivity.java :
package com.example.android.simpleworkingcameraapp;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.Image;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private ImageView image;
static final int REQUEST_TAKE_PHOTO = 1;
String mCurrentPhotoPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.image1);
}
// copied from the android development pages; just added a Toast to show the storage location
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmm").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();
Toast.makeText(this, mCurrentPhotoPath, Toast.LENGTH_LONG).show();
return image;
}
public void takePicAndDisplayIt(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
File file = null;
try {
file = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
}
}
#Override
protected void onActivityResult(int requestCode, int resultcode, Intent intent) {
if (requestCode == REQUEST_TAKE_PHOTO && resultcode == RESULT_OK) {
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
image.setImageBitmap(bitmap);
}
}
}
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.simpleworkingcameraapp">
<!--only added paragraph-->
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- only crucial line to add; for me it still worked without the other lines in this paragraph -->
<uses-permission android:name="android.permission.CAMERA" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Note that the solution I found for the problem also led to a simplification of the android manifest file: the changes suggested by the android tutorial in terms of adding a provider are no longer needed since I am not making use of any in my java code. Hence, only few standard lines -mostly regarding permissions- had to be added to the manifest file.
It might additionally be valuable to point out that Android Studio's autoimport may not be capable of handling java.text.SimpleDateFormat and java.util.Date. I had to import both of them manually.
Probably because you had something like this?
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri fileUri = CommonUtilities.getTBCameraOutputMediaFileUri();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(takePictureIntent, 2);
However you must not put the extra output into the intent, because then the data goes into the URI instead of the data variable. For that reason, you have to take the two lines in the middle out, so that you have
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePictureIntent, 2);
That´s what caused the problem for me, hope that helped.
To Access the Camera and take pictures and set ImageView on Android
You have to use Uri file = Uri.fromFile(getOutputMediaFile()); for marshmallow.
Use below link to get path
https://androidkennel.org/android-camera-access-tutorial/
Kotlin code that works for me:
private fun takePhotoFromCamera() {
val intent = Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(intent, PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA)
}
And get Result :
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
val photo: Bitmap? = MediaStore.Images.Media.getBitmap(this.contentResolver, Uri.parse( data!!.dataString) )
// Do something here : set image to an ImageView or save it ..
imgV_pic.imageBitmap = photo
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.i(TAG, "Camera , RESULT_CANCELED ")
}
}
}
and don't forget to declare request code:
companion object {
const val PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA = 300
}
After much try and study, I was able to figure it out. First, the variable data from Intent will always be null so, therefore, checking for !null will crash your app so long you are passing a URI to startActivityForResult.Follow the example below.
I will be using Kotlin.
Open the camera intent
fun addBathroomPhoto(){
addbathroomphoto.setOnClickListener{
request_capture_image=2
var takePictureIntent:Intent?
takePictureIntent =Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if(takePictureIntent.resolveActivity(activity?.getPackageManager()) != null){
val photoFile: File? = try {
createImageFile()
} catch (ex: IOException) {
// Error occurred while creating the File
null
}
if (photoFile != null) {
val photoURI: Uri = FileProvider.getUriForFile(
activity!!,
"ogavenue.ng.hotelroomkeeping.fileprovider",photoFile)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
photoURI);
startActivityForResult(takePictureIntent,
request_capture_image);
}
}
}
}`
Create the createImageFile().But you MUST make the imageFilePath variable global. Example on how to create it is on Android official documentation and pretty straightforward
Get Intent
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 1 && resultCode == RESULT_OK) {
add_room_photo_txt.text=""
var myBitmap=BitmapFactory.decodeFile(imageFilePath)
addroomphoto.setImageBitmap(myBitmap)
var file=File(imageFilePath)
var fis=FileInputStream(file)
var bm = BitmapFactory.decodeStream(fis);
roomphoto=getBytesFromBitmap(bm) }}
The getBytesFromBitmap method
fun getBytesFromBitmap(bitmap:Bitmap):ByteArray{
var stream=ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
I hope this helps.
I used contentResolver to create the path and it worked.
var values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "MyPicture")
values.put(
MediaStore.Images.Media.DESCRIPTION,
"Photo taken on " + System.currentTimeMillis()
)
cameraUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, cameraUri);
startActivityForResult(cameraIntent, REQUEST_CODE)
it still occurs even now 2022, i fix it as follow:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // android7.0
photoUri= FileProvider.getUriForFile(
MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
new File(mCameraFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
} else {
photoUri = Uri.fromFile(new File(mCameraFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT,photoUri);
}
,oh...just add a viriable(photoUri) to your activity! then
filePathCallback.onReceiveValue(new Uri[]{ photoUri });
The following code works for me:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, 2);
And here is the result:
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent)
{
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
if(resultCode == RESULT_OK)
{
Uri selectedImage = imageReturnedIntent.getData();
ImageView photo = (ImageView) findViewById(R.id.add_contact_label_photo);
Bitmap mBitmap = null;
try
{
mBitmap = Media.getBitmap(this.getContentResolver(), selectedImage);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

Categories

Resources