I am developing an app and part of it is selecting image from phone gallery and post it as a string to web api. The problem is with my selection of image and turning it to string to send. Here is my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_media_picker);
((Button) findViewById(R.id.buttonSelectMedia))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
photoPickerIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(photoPickerIntent, 2);
}
});
}
and my onActivityResult:
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
if (resultCode == RESULT_OK) {
Uri selectedImage = imageReturnedIntent.getData();
InputStream imageStream = null;
try {
imageStream = getContentResolver().openInputStream(selectedImage);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yourSelectedImage.compress(Bitmap.CompressFormat.PNG,100, baos);
byte [] arr = baos.toByteArray();
String stringImage = Base64.encodeToString(arr, Base64.DEFAULT);
String fileName = imageReturnedIntent.getData().getLastPathSegment();
}
I am getting an out of memmory exc on
String stringImage = Base64.encodeToString(arr, Base64.DEFAULT);
Regards to all.
I have found different path to the final result I am looking for. This is part of my OnActivityResult:
Uri selectedImage = imageReturnedIntent.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
String extension = filePath.substring(filePath.lastIndexOf(".")+1);
isBusy = true;
File file = new File(filePath);
FileInputStream mediaStream = new FileInputStream(file);
from this code I am able to do things like:
mediaStream.available()
and do my work. Regards to all and thanks for the help.
For avoiding the Out of Memory ecxeption in android while dealing with images you can use BitmapFactory.Options,Here is more information and code Loading Large Bitmaps Efficiently.
Related
The following code is able to save images in pictures directory, but I'm not able to find the perfect way to save image files to the desired app directory using URI.
Edit: The perfect way to store image files to a new directory which can be accessed by other apps is the requirement
SaveActivity.java
final MediaManager mediaManager = new MediaManager(this);
Uri imageURI = mediaManager.GetImageUri();
final ImageView imageHolder = findViewById(R.id.imageHolder);
Glide.with(this).load(imageURI).into(imageHolder);
final String filename = mediaManager.getFileName(imageURI);
save.setOnClickListener(new View.OnClickListener() {#Override public void onClick(View v) {
imageHolder.setDrawingCacheEnabled(true);
Bitmap bitmap = imageHolder.getDrawingCache();
MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, filename, "description");
}
});
MainActivity.java
ImageButton btImgSettings = findViewById(R.id.btnPhoto);
btnPhoto.setOnClickListener(new View.OnClickListener() {#Override public void onClick(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent, 1);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
Uri uri = data.getData();
switch (requestCode){
case 1: if (uri != null) {
String stringUri = uri.toString();
Intent intent = new Intent(this, SaveActivity.class);
intent.putExtra("imageId", stringUri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
break;
default:
break;
}
}
}
MediaManager
public class MediaManager {
Activity activity;
public MediaManager(Activity activity) {
this.activity = activity;
}
public Uri GetImageUri() {
Uri imageURI = null;
Bundle bundle = activity.getIntent().getExtras();
if (bundle != null) {
String imageId = bundle.getString("imageId");
imageURI = Uri.parse(imageId);
}
return imageURI;
}
}
Thank you :)
Copy the file to your directory and then use.
Bitmap image= MediaStore.Images.Media.getBitmap(getContentResolver(), data.getData());
File root = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "YourDirectory");
if (!root.exists()) root.mkdirs();
String file = root.toString() + File.separator + "FileName" + ".jpg";
try {
FileOutputStream fOutputStream = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fOutputStream);
image.compress(Bitmap.CompressFormat.JPEG, 100, bos);
fOutputStream.flush();
fOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
MediaScannerConnection.scanFile(context, new String[]{file}, null, null);
//This line notifies the system that an image was added and to show it in the gallery.
Hope this helps. Feel free to ask for any clarifications.
trying to let users add profile pictures, but I want to compress the image file before sending it to the server.
How can i compress the:
File imageFile = new File(resultUri.getPath());
Tried and searched but couldn't get to work
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if (resultCode == RESULT_OK) {
Uri resultUri = result.getUri();
btnConfirm.setVisibility(View.VISIBLE);
btnConfirm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
File imageFile = new File(resultUri.getPath());
progressDialog.show();
AndroidNetworking.upload("https://myweb.com/uploadImg.php")
.addMultipartFile("image", imageFile)
Would love to get some advice, Thanks in advance.
Check this
Uri selectedImage = imageReturnedIntent.getData();
InputStream imageStream = null;
try {
imageStream = getContentResolver().openInputStream(
selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bmp = BitmapFactory.decodeStream(imageStream);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
try {
stream.close();
stream = null;
} catch (IOException e) {
e.printStackTrace();
}
I'm trying to pick multiple images from users gallery and upload (parse server) this images to parse object then retrieve it and set it in an image view
and also i need to pick one image from gallery and save to the users profile
what i have already tried:
//Before OnCreate
String da = "13412412412412414124ASDASDASDASDAD";
////After OnCreate
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
final Uri imageUri = data.getData();
final InputStream imageStream;
try {
imageStream = getContentResolver().openInputStream(imageUri);
final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
String encodedImage = encodeImage(selectedImage);
da=encodedImage;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private String encodeImage(Bitmap bm) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG,100,baos);
byte[] b = baos.toByteArray();
String encImage = Base64.encodeToString(b, Base64.DEFAULT);
return encImage;
}
private void ChooseImage() {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, RESULT_LOAD_IMG);
}
private void CreateThing() {
ParseObject thing = new ParseObject("Things");
thing.put("Image",da);
thing.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e==null)
Toast.makeText(class.this, "Done", Toast.LENGTH_SHORT).show();
else
Toast.makeText(class.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
i have tried the code from these question at StackOverflow.
The sending routine is in a AsyncTask. The other code is similar to the code in the question.
When i am trying to send a image to the PC, i get a java.lang.NullPointerException caused at SendImageTask.java line 25 and line 14.
I cannot understand the Exception. Can somebody help me?
Here is the code:
MainActivity:
public class MainActivity extends Activity {
/** Called when the activity is first created. */
private static final int SELECT_PICTURE = 1;
public static String selectedImagePath;
private ImageView img;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("34");
img = (ImageView) findViewById(R.id.ivPic);
System.out.println("36");
((Button) findViewById(R.id.bBrowse))
.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
System.out.println("40");
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(
Intent.createChooser(intent, "Select Picture"),
SELECT_PICTURE);
System.out.println("47");
}
});
;
System.out.println("51");
Button send = (Button) findViewById(R.id.bSend);
final TextView status = (TextView) findViewById(R.id.tvStatus);
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
new SendImageTask().execute();
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
TextView path = (TextView) findViewById(R.id.tvPath);
path.setText("Image Path : " + selectedImagePath);
img.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);
}
}
SendImageTask
class SendImageTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
Socket sock;
try {
sock = new Socket("myip", 8000);
System.out.println("Connecting...");
// sendfile
File myFile = new File (MainActivity.selectedImagePath);
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
sock.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
Do away with getPath().
FileInputStream fis = new FileInputStream(myFile);
Change that to
InputStream is = getContentResolver().openInputStream(data.getData());
And use that stream like you did before.
As you can see your app crash at this line
FileInputStream fis = new FileInputStream(myFile);
You can test with debugger and try to create a FileInputStream with your path, you will get "not file found"
This is because your path is not correct, your getpath function is not correct.
If you want the path for an image take from the gallery you need to change your getPath function to this :
public String getPath(Uri uri) {
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(projection[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
}
I'm trying to encode an image to 64 base ,
after choosing the image from gallery and trying to save it I am getting this error:
outOfMemory Exception
can any one suggest how to to get this image to base 64 without memory error?
MotorImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent i = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, RESULT_LOAD_IMAGE);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
//
ImageView imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setImageBitmap(BitmapFactory.decodeFile(picturePath));
String imageString = null;
try {
Bitmap bm = BitmapFactory.decodeFile(picturePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); //bm is the bitmap object
bm.recycle();
byte[] b = baos.toByteArray();
imageString = Base64.encodeToString(b, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), imageString, Toast.LENGTH_SHORT).show();
I suspect you need to scale and resample your image to fit within the constraints on the device, try something like this
// decodes image and scales it to reduce memory consumption
private Bitmap decodeImage(String picturePath) {
try {
File file = new File(picturePath);
// Get image size
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(file), null, opts);
// The new size we want to scale to
final int MIN_SIZE = 70;
// Find the correct scale value.
int scale = 1;
while (((opts.outWidth / scale) >> 1) >= MIN_SIZE
&& ((opts.outHeight / scale) >> 1) >= MIN_SIZE) {
scale <<= 1;
}
BitmapFactory.Options opts2 = new BitmapFactory.Options();
opts2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(file), null, opts2);
} catch (FileNotFoundException e) {
}
return null;
}
Try to use android:largeHeap="true" inside the application tag on AndroidManifest, then your app will have more ram available and will not throw a oom exception.
If you read the official document of android you will come to know that this is a common issue with android and the recommended solution is to resize image according to your need. you can refer developer.android for this as well