Cannot open certain images - android

I have a program that allows the user to pick images from the gallery, saves it in a database and shows it on screen. This works for most images , but for certain images, the app crashes. There is no error message in the Logcat. But when i restart the app, i get a error message that says:
Couldn't read row 0, col 1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
(Tested on ANDROID SDK 24)
new AlertDialog.Builder(this).setTitle("Take or Pick?").setMessage("Choose to click a new picture or choose from existing").
setNegativeButton("CHOOSE PHOTO", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent i = new Intent(
Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, REQUEST_IMAGE_PICKER);
}
}).create().show();
onActivityResult code goes like this:
if (requestCode == REQUEST_IMAGE_PICKER && resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
Bitmap bmp= null;
try { //GET BITMAP FROM URI , TRY CATCH USED TO TACKLE
bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage)); // IO STREAM FILE NOT FOUND ERROR
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(cameraTeamStatus==1) {
img1.setImageBitmap(bmp); //SET IMAGE
image1_to_save = convertToBlob(bmp); //CONVERT TO BLOB
}

This crash is due to large size of picture taken by camera and cursor not able to handle it ,cursor initialize fails.
In order to fix this I would suggest considering one of the following methods to reduce image size before upload Link:1 , Link:2 ,Link:3
or you can check this link Whatsapp like Image Compression.
Hope it Helps!

Related

Reducing the size of the photo

I'm recording the photos taken by my application in the sqlite database, I know it's not very recommended anymore I need to transfer these photos to a central database that unifies all data from all applications.
The way I'm reducing and writing to sqlite bank is this way:
Android.Graphics.Drawables.BitmapDrawable bd = (Android.Graphics.Drawables.BitmapDrawable)imageView.Drawable;
Bitmap bitmap = bd.Bitmap;
MemoryStream stream = new MemoryStream();
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);
byte[] ba = stream.ToArray();
string bal = Base64.EncodeToString(ba, Base64.Default);
Personally, I am editing my question because the problem is not in the select as I had thought it could be, but at the time of writing to the database. The code above works great when searching for a photo or image on the device. The problem is when it takes the photo for the application, then I get this error that is below.
I think I need to compress App.bitmap, which gets the shot taken right away. I just do not know how to do it yet. As I said the above code works great with the pictures taken by the device, but when I shoot through my application I get this error.
I'm going to post my OnActivityResult method so that you can help me figure out what this error is.
Error:
Java.Lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
Searching on the internet this error is returning because of the size of the cursor that have a maximum of 2MB.
OnActivityResult Method:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
// Make it available in the gallery
try
{
Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
Uri contentUri = Uri.FromFile(App._file);
mediaScanIntent.SetData(contentUri);
SendBroadcast(mediaScanIntent);
// Display in ImageView. We will resize the bitmap to fit the display.
// Loading the full sized image will consume to much memory
// and cause the application to crash.
int height = Resources.DisplayMetrics.HeightPixels;
int width = imageView.Height;
App.bitmap = App._file.Path.LoadAndResizeBitmap(width, height);
if (App.bitmap != null)
{
imageView.SetImageBitmap(App.bitmap);
// App.bitmap = null;
}
// Dispose of the Java side bitmap.
GC.Collect();
}
catch
{
}
try
{
if (resultCode == Result.Ok)
{
var imageView =
FindViewById<ImageView>(Resource.Id.imageView1);
imageView.SetImageURI(data.Data);
}
}
catch
{
}
}
Without fetching the photo, the select does not return the error quoted above. I'm counting on your help.
Use EncoderParameter to specify the level of compression for an image.
see https://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoderparameter(v=vs.110).aspx
and https://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoder.quality(v=vs.110).aspx

Intent chooser stays open when using a Thread to get an image resource

I am building a photo upload form which has to grab an image either from the camera or gallery or whatever other resource is available (Dropbox/Google Drive/Astro File Manager, etc.). I think I have it all working except for one small component.
When the selected image is coming from a network resource, such as Google Drive, it can take a long time to return back to the activity. I would like to make this asynchronous to avoid having the user stare at a black screen while the image downloads.
There's a lot of code that I've written to get this whole thing to work, but here's the general process of it:
The Activity starts and displays the form.
The Intent chooser automatically opens and asks the user to select an image from either the camera or another app.
The user selects some app such as Google Drive, selects an image and that app closes, returning the selected image Uri as the result.
Cache the contents of the file to workaround KitKat permissions which can block from re-reading the image if the Activity closes and needs to resume.
Asynchronously display the scaled bitmap using the cached file as the source.
The Intent chooser closes, the image is displayed in an ImageButton and the form is visible to the user to be filled out before submission.
Once the submit button is tapped, an asynchronous task starts which allows for the multipart upload to the server.
The asynchronous upload uses a callback function to notify the user of the upload progress.
I'm getting stuck in the transition between #3 and #4.
If I use a Thread or AsyncTask
The Intent chooser will remain open, but the image will also be displayed on the form.
If I simply force the user to wait (serially)
The user is stuck looking at a black screen, then the Intent Chooser closes and the image is displayed on the form.
Opening the Intent chooser
/**
* see http://stackoverflow.com/a/12347567/940217
*/
private void openImageIntent() {
// Camera.
final List<Intent> cameraIntents = new ArrayList<Intent>();
final PackageManager packageManager = getPackageManager();
Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile;
try {
uploadableImage.makeCameraTempFile();
photoFile = uploadableImage.getCameraTempFile();
uploadableImage.setCameraFilepath(photoFile.getAbsolutePath());
} catch (IOException ex) {
// Error occurred while creating the File
photoFile = null;
uploadableImage.invalidate();
Log.e(TAG, "Error while creating the temporary file needed for image capture from camera.");
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null && packageManager != null) {
final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
for (ResolveInfo res : listCam) {
// Create the File where the photo should go
if (res.activityInfo == null) {
continue;
}
final String packageName = res.activityInfo.packageName;
final Intent intent = new Intent(captureIntent);
intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
intent.setPackage(packageName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
cameraIntents.add(intent);
}
} else {
Toast.makeText(this, "Could not make temporary file.", Toast.LENGTH_LONG).show();
}
// Filesystem.
final Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
// Chooser of filesystem options.
final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source");
// Add the camera options.
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[cameraIntents.size()]));
startActivityForResult(chooserIntent, REQUEST_IMAGE_CAPTURE);
}
onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_IMAGE_CAPTURE) {
if (tempUpFile != null){
tempUpFile.invalidate();
}
if (data == null) {
Log.d(TAG, "Data was null -- source was from camera");
uploadableImage.preserveCameraFile();
setPic();
} else {
Uri selectedImageUri = data.getData();
if (selectedImageUri == null) {
Log.e(TAG, "An error that should never occur has occurred -- selectedImageUri was null when trying to get the data from the Image Capture activity result.");
Toast.makeText(this, "Unexpected error when trying to get an image from the gallery or file manager.", Toast.LENGTH_LONG).show();
return;
}
uploadableImage.setSourceImageUri(selectedImageUri, imageButton);
setPic(); // only do this if doing this serially.
}
} else if (resultCode == RESULT_CANCELED){
uploadableImage.invalidate();
if (tempUpFile != null){
uploadableImage = tempUpFile;
}
setPic();
}
}
UploadableImage#setSourceImageUri
public void setSourceImageUri(Uri selectedImageUri, final ImageView iView) {
// Important!! - clean up after ourselves!
deleteFile(this.cameraFile);
this.cameraFile = null;
InputStream tempInStream = null;
OutputStream tempOutStream = null;
try {
this.cacheFile = createFile();
tempInStream = context.getContentResolver().openInputStream(selectedImageUri);
tempOutStream = new FileOutputStream(this.cacheFile);
} catch (IOException e) {
Toast.makeText(context, "Error while trying to read the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "IOException while trying to copy the selected image to our cache file");
e.printStackTrace();
}
if (tempInStream == null || tempOutStream == null){
Toast.makeText(context, "Error while trying to "+(tempInStream == null ? "read" :"store")+" the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "Error while trying to get the " + (tempInStream == null ? "input" : "output") + " stream");
return;
}
// Works, but makes the UI hang on a black screen while waiting for the resource.
try {
copy(tempInStream, tempOutStream);
}catch (IOException e){
Toast.makeText(context, "Error while trying to read the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "IOException while trying to copy the selected image to our cache file");
e.printStackTrace();
}
/*
// Works, but leaves the IntentChooser open
final InputStream inStream = tempInStream;
final OutputStream outStream = tempOutStream;
new Thread(new Runnable() {
public void run() {
try {
copy(inStream, outStream);
// FIXME: somehow notify/display the bitmap in the UI
// --maybe use Message and Handler? callback Interface?
} catch (IOException e) {
Toast.makeText(context, "Error while trying to read the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "IOException while trying to copy the selected image to our cache file");
e.printStackTrace();
}
}
}).start();
*/
}
Edit:
I've found that this will/will not occur depending on API level.
Does not occur:
KitKat (Nexus 4)
ICS MR1 (emulator)
Does occur:
KitKat (emulator)
ICS MR1 (Galaxy Tab 10.1)
Edit 2:
Here are some screenshots of what should not happen; images are from KitKat emulator.
Start the Activity
Select an image from the gallery or some other resource
The onActivityResult returns and the chooser remains open
This is how it should look after onActivityResult
Feeling pretty stupid, but I found the solution.
The issue was in step two: "The Intent chooser automatically opens..."
In order to do this, I was checking to see if a bitmap was available, and if it wasn't then it should display the placeholder image and then open the Intent chooser. I had this logic inside the onStart method which normally gets run after onActivityResult. However, because this was all happening asynchronously, I could not rely on this order.
What I had to do was put in a boolean flag which could tell me if we were waiting for a bitmap, and then not open the chooser if we were.

Updating gallery after taking pictures Gallery not showing all the pictures Android Camera

I am using a onClick over a button to capture an image.
PictureCallback myPictureCallback_JPG = new PictureCallback() {
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
FileOutputStream outStream = null;
try {
// Write to SD Card
outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
outStream.write(arg0);
outStream.close();
Toast.makeText(Photo.this, "Image Saved to SD Card", Toast.LENGTH_SHORT).show();
System.out.println();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
}};
The image gets saved in the SD card.
Then the user clicks on Send button and a layout opens, on Click of ImageView an Image Gallery opens and clicking on a particular image, the URI gets selected.
imageAttachPhoto = (ImageView)findViewById(R.id.imageViewPhotoOne);
imageAttachPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select Picture"), SELECT_PICTURE);
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
System.out.println("Image Path : " + selectedImagePath);
imageAttachPhoto.setImageURI(selectedImageUri);
}
}
}
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
But I am not able to view images snapped in Gallery code, but could see the images through FileBrowser and when I open the SD card in PC I can see the image and then the Android shows the image in Gallery also with in the code.
Let me know what the issue is and how to solve it, looking forward to your reply.
Thanks.
Even if this is a little bit older! But I just had the same problem. Soni´s answer works but requires the Media Scanner every time to look for new files in the whole directory. You can also just register your new file that seems a bit more performant
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+f.getAbsolutePath())));
f is the File you want to register.
Android scan media file and those are shown when using content provider...when your run your app and take new camera at that time you just took new pics but default gallery doesn't know about that new pics cause they are not in content provider's list of media.
I think adding this line after taking picture and before calling gallery will show the all latest pics taken from camera.
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
This will throw a SecurityException in KitKat+. Try Vossi's method, or use MediaScannerConnection as used here: stackoverflow – #absk
simple answer is that first run the application, capture the image from camera of your application then simple see in gallery of your device.
you can't see last capture image image by your application at that time one time restart your device and can see that your last capture image is in gallery of your device.
one more thing, after your device restart then again open your own application and again capture one image from your application and see that your second capture image can see in gallery without any action in your device.

using android intent to call and receive a result from camera app no matter if it is custom built

here is the problem: i have searched for an answer for this and so far i made it work for the custom camera app that comes with htc phones.
i have the folowing
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == REQUEST_FROM_CAMERA && resultCode == RESULT_OK) {
InputStream is=null;
File file=mInterface.getTempFile();
try {
is=new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if(is==null){
try {
u = data.getData();
is=getContentResolver().openInputStream(u);
mInterface.saveStringPreferences(GlobalInterface.URI_SAVENAME, u.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//Now "is" stream contains the required photo, you can process it
setImage(is);
}
//and this is the code to the function that calls the intent:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(mInterface.getTempFile()));
startActivityForResult(intent, REQUEST_FROM_CAMERA);
the remaining functions getTempFile() is to create a temp file on /sdcard/blabla.tmp
and a function to set the captured image in an image view.
so the problem is that i tested this code on the custom camera on a lg phone and it crashes. the question is: is there a way to get an uri for the image location (i dont need a specific save location it could be the default set from the camera) and there were also some issues i came across which i dont need to solve like getting a smaller resolution image. i just need one image and to be able to set it in an imageView and the method to work for every camera app that is there, custom or native regardless.
is this possible or i need to create a new camera class for this? in my opinion the camera apps that come with the phone are more adjusted to the phone model so i would prefer using them against building a custom one.
tnx.
Try this:
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
Source

How do I save data from Camera to disk using MediaStore on Android?

For my application, I'd been using my own Camera class for taking images and my own database but soon enough I couldn't really keep up with changes and I decided to use the built in camera application in Android to do the job, but I can't seem to get it to save file. What am I missing here? The application seems to save the file but it's just 0 bytes. I looked up the source code of the Camera application and it's looking for the "output" in Extras to save the file. Any help would be greatly appreciated.
Public class CameraTest extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button cameraButton = (Button) findViewById(R.id.cameraButton);
cameraButton.setOnClickListener( new OnClickListener(){
public void onClick(View v ){
ContentValues values = new ContentValues();
values.put(Images.Media.TITLE, "title");
values.put(Images.Media.BUCKET_ID, "test");
values.put(Images.Media.DESCRIPTION, "test Image taken");
Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra("output", uri.getPath());
startActivityForResult(intent,0);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode== 0 && resultCode == Activity.RESULT_OK){
((ImageView)findViewById(R.id.pictureView)).setImageURI(data.getData());
}
}
}
This worked with the following code, granted I was being a little dumb with the last one. I still think there's got to be a better way so that the original image is still saved somewhere. It still sends me the smaller 25% size image.
public class CameraTest extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button cameraButton = (Button) findViewById(R.id.cameraButton);
cameraButton.setOnClickListener( new OnClickListener(){
public void onClick(View v ){
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
startActivityForResult(intent,0);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode== 0 && resultCode == Activity.RESULT_OK) {
Bitmap x = (Bitmap) data.getExtras().get("data");
((ImageView)findViewById(R.id.pictureView)).setImageBitmap(x);
ContentValues values = new ContentValues();
values.put(Images.Media.TITLE, "title");
values.put(Images.Media.BUCKET_ID, "test");
values.put(Images.Media.DESCRIPTION, "test Image taken");
values.put(Images.Media.MIME_TYPE, "image/jpeg");
Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
OutputStream outstream;
try {
outstream = getContentResolver().openOutputStream(uri);
x.compress(Bitmap.CompressFormat.JPEG, 70, outstream);
outstream.close();
} catch (FileNotFoundException e) {
//
} catch (IOException e) {
//
}
}
}
Also, I do know that the cupcake release of Android should fix the small image size soon.
The below code will start the default camera and have the camera save the image to the specified uri. The key is to put the extra "MediaStore.EXTRA_OUTPUT" along with the desired uri.
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/Images/" + image_name + ".jpg");
Uri imageUri = Uri.fromFile(file);
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, 0);
In your first attempt, it could be that the Camera app crashes when it reads your "output" extra, since it expects it to be a Uri, while you provide a String. The Camera app seems to read the extra flag after capturing the photo. You should just provide uri, and not uri.getPath(). Then, since you already know the URI to the photo, it will not be returned in the onResult call. You need to remember the URI in a member variable.
In the second attempt you will get a scaled down (50%) bitmap back. It is primarily intended for views. I think the full sized bitmap is too large for the memory budget of the application. This may be the reason for the downscale.
FYI , found this on docs :
The caller may pass an extra EXTRA_OUTPUT to control where this image will be written. If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap object in the extra field. This is useful for applications that only need a small image. If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri value of EXTRA_OUTPUT.
located here :http://developer.android.com/reference/android/provider/MediaStore.html
so the app can save full size image for you , if you tell it where.
**Edit : This is not the case with HTC devices. HTC (not nexus) that uses htc sense ui have branched from android 1.5 and carry a bug that always save the image in low res. you can lunch activity for camera and use the share function from camera to use the full sized image.
I got the same Problem with the Emulator,
I tried it on a real Phone an it worked,
maybe it is because the Virtual Phone can't really take Picures.

Categories

Resources