App keep crashing when I try to save image to gallery - java

I wanted to take a photo and save it to gallery. Then read this photo from gallery and convert it to text( using ocr)
But my app keep crashing when I try to save it with this line of code
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
I debug my app and found this line is the responsible for crash. But without this line I can't save my image. How can I do that ?
package com.example.takepicture;
import ...
public class MainActivity extends AppCompatActivity {
private static final int CAMERA_REQUEST = 1888;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnCamera = (Button) findViewById(R.id.btnCamera);
imageView = (ImageView) findViewById(R.id.ImageView);
btnCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File pictureDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String pictureName = getPictureName();
File imageFile = new File(pictureDirectory,pictureName);
Uri pictureUri = Uri.fromFile(imageFile);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
//capturarFoto();
}
});
}
private String getPictureName() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
return "Img" + timeStamp + ".jpg";
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_OK) {
if (requestCode == CAMERA_REQUEST) {
}
}
}
}

Fastest solution is adding:
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
somewhere before calling:
startActivityForResult(...)
But the correct one (for API >24) is:
creating URI via FileProvider.getUriForFile(...) and
creating provider (and adding it to Manifest file)
You can find more info there: https://stackoverflow.com/a/50265329/5529263

Related

Once you have recovered an image of the user how to save it in Drawable

Once you have recovered an image of the user, how to save it in drawable in the app ?
For use it in other activities.
Retrieve the image from the user's gallery and put it in ImageView :
public class Profil extends AppCompatActivity {
private Button btnImport;
public ImageView selectedImg;
static final int RESULT_LOAD_IMG = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.profil);
ImageView btn_supervisor = findViewById(R.id.btn_supervisor);
ImageView btn_add = findViewById(R.id.btn_add);
ImageView btn_profile = findViewById(R.id.btn_profile);
btnImport = findViewById(R.id.modifie_button);
selectedImg = findViewById(R.id.modifie_image);
btnImport.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, RESULT_LOAD_IMG);
}
});
}
#Override
protected void onActivityResult(int reqCode, int resultCode, Intent data) {
super.onActivityResult(reqCode, resultCode, data);
if (resultCode == RESULT_OK) {
try {
final Uri imageUri = data.getData();
final InputStream imageStream = getContentResolver().openInputStream(imageUri);
final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
selectedImg.setImageBitmap(selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Une erreur s'est produite",Toast.LENGTH_LONG).show();
}
}else {
Toast.makeText(getApplicationContext(),"Vous n'avez pas choisi d'image", Toast.LENGTH_LONG).show();
}
}
}
Thank you in advance.
You should never save the image drawable/ bitmap to use in other activities. Instead, you can save the Uri of the image file in some variable in your application class or some static properties holder and then can fetch bitmap from that Uri accross all your activities.
you can use BitmapDrawable to achieve this
//Convert bitmap to drawable.
Drawable drawable = new BitmapDrawable(context.getResources(), bitmap);

My app keeps resetting after I close it

My app keeps resetting after I close it.
public class MainActivity extends AppCompatActivity {
public static final int FILE_REQUEST_CODE = 1;
ImageView IMG ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IMG = (ImageView) findViewById(R.id.imageView1);
Button pickBtn = (Button) findViewById(R.id.pickBtn);
pickBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pickImg();
}
});
}
private void pickImg() {
new MaterialFilePicker()
.withActivity(this)
.withRequestCode(1)
.withFilter(Pattern.compile(".*\\.(jpg|jpeg|png)$"))
.withHiddenFiles(true)
.withTitle("Sample title")
.start();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == FILE_REQUEST_CODE && resultCode == RESULT_OK) {
String filePath = data.getStringExtra(FilePickerActivity.RESULT_FILE_PATH);
// Do anything with file
File imgFile = new File(filePath);
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
IMG.setImageBitmap(myBitmap);
}
}
}
}
My app is only filled with one button and one image default. With the button I can pick an image to replace the default image.
But when I close the app and open it again the image is back to default.
How to make it show the last picked image when I start the app??
If this app is performing simple and offline task, you could use Shared Preference to store the location of the Image. When onCreate, check whether the sharedpreference object is null or not, if not, load with the value stored.

App crashes when an uploaded large image is sent to the next activity

I have searched through google and even youtube for videos. The code works perfectly when uploading and displaying the large image but crashes when sending it to the next activity. I have tried images with smaller quality or size and it worked perfectly
public class MainActivity extends AppCompatActivity {
private static final int PICK_IMAGE_REQUEST = 123;
public static Bitmap bitmap;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.img);
}
public void upload(View view) {
Intent intent = new Intent();
// Show only images, no videos or anything else
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
// Always show the chooser (if there are multiple options available)
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK)
switch (requestCode) {
case PICK_IMAGE_REQUEST:
Uri filePath = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
imageView.setImageBitmap(bitmap);
} catch (IOException e) {
Log.i("TAG", "Some exception" + e);
}
break;
}
}
public void Submit(View view) {
Intent intent = new Intent(getApplicationContext(), Main2Activity.class);
if(bitmap !=null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 40, stream);
byte[] byteArray = stream.toByteArray();
intent.putExtra("bitmap", byteArray);
}
startActivity(intent);
}
}
This is where the image sent from the MainActivity.java is displayed:
public class Main2Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ImageView img = (ImageView) findViewById(R.id.imgg);
Bundle extras = getIntent().getExtras();
byte[] byteArray = extras.getByteArray("bitmap");
Bitmap bitmap = null;
try {
if (byteArray != null) {
bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
}
} catch (IndexOutOfBoundsException e){
e.printStackTrace();
}
img.setImageBitmap(bitmap);
}
}
Here is the error message:
java.lang.OutOfMemoryError: Failed to allocate a 3244812 byte allocation with 1765075 free bytes and 1723KB until OOM
You can't send big image via Intent, from the documentation:
When sending data via an intent, you should be careful to limit the
data size to a few KB. Sending too much data can cause the system to
throw a TransactionTooLargeException exception.
So, it's better if you send the Uri and process the Uri in the receiver Activity.
First, you need to send the Uri instead of Bitmap in the First Activity:
private Uri mFileUri;
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK)
switch (requestCode) {
case PICK_IMAGE_REQUEST:
// Save uri for submit process.
mFileUri = data.getData();
...
break;
}
}
public void Submit(View view) {
Intent intent = new Intent(this, Main2Activity.class);
intent.setData(mFileUri);
startActivity(intent);
}
Then handle it in your receiver activity:
public class Main2Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ImageView img = (ImageView) findViewById(R.id.imgg);
// get the fileUri from the intent
Uri fileUri = getIntent().getData();
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
img.setImageBitmap(bitmap);
} catch (IndexOutOfBoundsException e){
// handle the exception.
}
}
}
This:
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
This line drains memory so hard. Now you have the URI of the image right?
Uri filePath = data.getData();
Now use Picasso to load the image like below
1. If you want to send the image somewhere else:
com.squareup.picasso.Target mTarget = new com.squareup.picasso.Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
imageView.setImageBitmap(bitmap);
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
Picasso.with(mContext).load(filePath).into(mTarget);
If you want to Use the image in lower quality, Just do this:
Picasso.with(mContext).load(filePath).centerInside().resize(YourWidth,YourHeight).into(imageview);
The answers simple. Store the image in a the devices file storage, pass the Uri of the image in storage to the Intent that is launching another activity, then fetch the Uri from said intent, and load from the file.
Your Bitmap object in MainActivity is marked as static, I doubt why is that necessary.
Making it static makes Android cannot GC it when you start Main2Activity,
A potential reason of why you are running out of memory.
Try to change it to private Bitmap bitmap. It might solves your problem.
But generally passing a bitmap object over an Activity is rare.
Since you mentioned that the image is uploaded, it is much better to get an image URL from server after you have uploaded it, and then use some Image Library such as Glide or Fresco to load it from the internet.

Intent camera crash

I'm now making a simple android app. It's just allow user to take an Photo and then show it.
When i test it in Virtual device, it's ok. But when i download apk to my android device, after i take a photo in Back camera, the app has stopped and return to main menu. Just problem in Back Camera.
In addition, in virtual device, after taking photo, the photo will show successfully. But it's empty in my phone
In MainActivity, i click on "Take Photo", it will start the camera and same my image to folder. Then it send the path of Photo to the next activity and show it.
This is my MainActivity
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_ID_IMAGE_CAPTURE = 100;
Button TakePhoto, InsertPhoto, Exit;
String mCurrentPhotoPath;
private File createImageFile() 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,".jpg",storageDir);
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TakePhoto = (Button) findViewById(R.id.button);
InsertPhoto = (Button) findViewById(R.id.button3);
Exit = (Button) findViewById(R.id.button2);
//Start Camera
TakePhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
System.out.println(ex);
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = Uri.fromFile(photoFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(intent,REQUEST_ID_IMAGE_CAPTURE);
}
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_ID_IMAGE_CAPTURE) {
if (resultCode == RESULT_OK) {
//Bitmap bp = (Bitmap)data.getExtras().get("data");
//ByteArrayOutputStream stream = new ByteArrayOutputStream();
// bp.compress(Bitmap.CompressFormat.PNG, 100, stream);
// byte[] images = stream.toByteArray();
File imgFile = new File(mCurrentPhotoPath);
if(imgFile.exists()){
System.out.println("This is file"+mCurrentPhotoPath.toString());
Intent Show = new Intent(MainActivity.this, ShowPhoto.class);
Show.putExtra("image",imgFile);
startActivity(Show);
}
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Action canceled", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Action Failed", Toast.LENGTH_LONG).show();
}
}
}
}
This is The ShowPhoto Activity
public class ShowPhoto extends Activity {
private LinearLayout Image;
Button Back,Next;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_photo);
Image=(LinearLayout)findViewById(R.id.linearLayout);
//Get Image from previous Activity
File image = (File)getIntent().getExtras().get("image");
Bitmap bmp = BitmapFactory.decodeFile(image.getAbsolutePath());
ImageView imageView = new ImageView(getApplicationContext());
imageView.setImageBitmap(Bitmap.createScaledBitmap(bmp, bmp.getWidth()*2, bmp.getHeight()*2, true));
Image.addView(imageView);
}
}
This is what's in my logcat when i run app
enter image description here
enter image description here
Use should ask for the permission at runtime and declare the permission in Manifest
if (ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale((Activity)
getContext(), Manifest.permission.CAMERA)) {
} else {
ActivityCompat.requestPermissions((Activity) getContext(),
new String[]{Manifest.permission.CAMERA},
MY_PERMISSIONS_REQUEST_CAMERA);
}
}
For your Manifest
<uses-permission android:name="android.permission.CAMERA"/>

saving a bitmap in android using camera intent

I'm trying to follow this tutorial however the problem is when I click the checkmark that is supposed to confirm the image it doesn't do anything at all. I feel like I'm missing some kind of permission to access the SD card or something. I am testing on a nexus 7 in debug mode. All help appreciated thank you.
public class MainActivity extends Activity {
private static final int CAMERA_REQUEST = 1888;
private static ImageView imageView;
protected String _path;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.imageView = (ImageView)this.findViewById(R.id.imageView1);
Button photoButton = (Button) this.findViewById(R.id.button1);
_path = Environment.getExternalStorageDirectory() + "/images/camocr";
photoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
File file = new File( _path );
Uri outputFileUri = Uri.fromFile( file );
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE );
intent.putExtra( MediaStore.EXTRA_OUTPUT, outputFileUri );
//Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult( intent, 0 );
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == -1) {
// Bitmap photo = (Bitmap) data.getExtras().get("data");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile( _path, options );
imageView.setImageBitmap(bitmap);
}
}
protected static void identifyunicode() {
// DATA_PATH = Path to the storage
// lang for which the language data exists, usually "eng"
}
}
Try changing your requestCode to -1 in the onCreate method. That should solve your problem.
in your startActivity for result the request code is 0, and in onActivity result your checking for -1 also you have to use:
sendBroadcast(new Intent(
Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())));
for the picture to show up, if not it wont show up until the next time you turn the phone on

Categories