Passing an image through getIntent() putExtra() - java

I am new to android studio and stack overflow so I may not make any sense but I want to pass some data from one activity to another. I have managed to do it through the putExtra() on the intent with all the text that I want passed to the activity. However, I do not know how to set a getIntent on an image that has to be produced with setImageResource().
FavActivity
Cursor cursor = (Cursor) mylist.getItemAtPosition(position);
String listName = cursor.getString(1);
String displayName = db.getName(listName);
if (!displayName.isEmpty()) {
String isleName = db.getIsle(listName);
String rowName = db.getRow(listName);
String locationImage = db.getLocationImage(listName);
Intent myIntent = new Intent(view.getContext(),MainActivity.class);
myIntent.putExtra("name", displayName);
myIntent.putExtra("isle", "Isle: " + isleName);
myIntent.putExtra("row", "Row: " +rowName);
myIntent.putExtra("image", locationImage);
startActivity(myIntent);
MainActivity
textView.setText(getIntent().getStringExtra("name"));
textView3.setText(getIntent().getStringExtra("isle"));
textView4.setText(getIntent().getStringExtra("row"));
Image location has to be set like this as its converting from database text
locationView.setImageResource(getResources().getIdentifier(locationImage, "drawable", getPackageName()));
How do I set an intent to do this?

Store the image in a file and pass the file path through the intent to the other activty and you can access the image from that file path in the other activity

You can pass an image but I would suggest storing the image in Internal storage and pass them using Intent.
As of API 24, there is 1 MB restriction else it would throw TransactionTooLarge Exception and may cost you too much memory
Saving image to Internal Storage-
public String createImageFromBitmap(Bitmap bitmap) {
String fileName = "myImage";//no .png or .jpg needed
try {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
FileOutputStream fo = openFileOutput(fileName, Context.MODE_PRIVATE);
fo.write(bytes.toByteArray());
// remember close file output
fo.close();
} catch (Exception e) {
e.printStackTrace();
fileName = null;
}
return fileName;
}
and then pass that file name in Bundle
Bitmap bitmap = BitmapFactory.decodeStream(context
.openFileInput("myImage"));
An another example to be used
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.my_layout);
Bitmap bitmap = getIntent().getParcelableExtra("image");
ImageView imageView = (ImageView) findViewById(R.id.imageview);
imageView.setImageBitmap(bitmap);
}

Hiii,
You can send an image in Base64 format and convert it to an image after receiving in next Activity.
Though make sure that you can send maximum 50kb data using Intents.
Otherwise, your app might misbehave on sending and receiving data.

Related

More efficient method to take picture from Android in-app-cam and upload it to server

I'm building an app that require method to take picture from in-app camera, but for some Android devices (old device or low ram), it's quite freeze when taking picture triggered. Is there any code i can modify or optimize to make user experience feels better?
//this function trigger to take picture (or screenshot) from user screen
private void captureImage() {
mPreview.setDrawingCacheEnabled(true);
final Bitmap[] drawingCache = {Bitmap.createBitmap(mPreview.getDrawingCache())};
mPreview.setDrawingCacheEnabled(false);
mCameraSource.takePicture(null, bytes -> {
int orientation = Exif.getOrientation(bytes);
Bitmap temp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Bitmap picture = rotateImage(temp, orientation);
assert picture != null;
Bitmap overlay = Bitmap.createBitmap(mGraphicOverlay.getWidth(), mGraphicOverlay.getHeight(), picture.getConfig());
Canvas canvas = new Canvas(overlay);
Matrix matrix = new Matrix();
matrix.setScale((float) overlay.getWidth() / (float) picture.getWidth(), (float) overlay.getHeight() / (float) picture.getHeight());
// mirror by inverting scale and translating
matrix.preScale(-1, 1);
matrix.postTranslate(canvas.getWidth(), 0);
Paint paint = new Paint();
canvas.drawBitmap(picture, matrix, paint);
canvas.drawBitmap(drawingCache[0], 0, 0, paint);
//this function to save picture taken and put it on app storage cache
try {
String mainpath = getApplicationContext().getFilesDir().getPath() + separator + "e-Presensi" + separator;
File basePath = new File(mainpath);
if (!basePath.exists())
Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success" : "Failed");
//this function to get directory path of saved photo
String path = mainpath + "photo_" + getPhotoTime() + ".jpg";
String namafotoo = "photo_" + getPhotoTime() + ".jpg";
filePath = path;
namafoto = namafotoo;
SessionManager.createNamaFoto(namafoto);
File captureFile = new File(path);
boolean sucess = captureFile.createNewFile();
if (!captureFile.exists())
Log.d("CAPTURE_FILE_PATH", sucess ? "Success" : "Failed");
FileOutputStream stream = new FileOutputStream(captureFile);
overlay.compress(Bitmap.CompressFormat.WEBP, 60, stream);
stream.flush();
stream.close();
if (!picture.isRecycled()) {
picture.recycle();
}
if (drawingCache[0] != null && !drawingCache[0].isRecycled()) {
drawingCache[0].recycle();
drawingCache[0] = null;
}
mPreview.setDrawingCacheEnabled(false);
uploadPicture();
finish();
} catch (IOException e) {
e.printStackTrace();
}
});
}
Thanks for your help.
In general, I would advise you to step through your code and look at large memory resources you're generating on each line and consider setting those to null aggressively as you move throughout the method if you're done.
For example, you have a variable called temp which is size "Y" bytes that you appear to rotate and then never use temp after that. If picture is a rotated copy of temp then you have now used 2Y bytes of memory to keep temp and picture. I suspect if you simply set temp to null after creating picture, you might free up half that memory that your older/slower phones are going to badly need.
Take that same concept and follow through with the rest of your method to see if you can find other optimizations. Basically anywhere you're creating a copy of the image data you're not going to use, you should immediately set it to null so the garbage collector can throw it away aggressively.
Firt you need some variables:
byte[] byteArray_IMG;
String currentPhotoPath;
static final int REQUEST_TAKE_PHOTO = 1;
ImageView imageView; // maybe you need show the photo before send it
Then define the method to take the photo:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Toast.makeText(getApplicationContext(),Error takin the photo",Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
path_img = photoFile.toString();
Uri photoURI = FileProvider.getUriForFile(this,"com.app.yournmamepackage.fileprovider" , photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
Create the method to create the file image
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, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
Override the activity result to:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode,resultCode,data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
/* Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(imageBitmap);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byteArray_IMG = stream.toByteArray();*/
MediaScannerConnection.scanFile(this, new String[]{path_img}, null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
Log.i("path",""+path);
}
});
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap imageBitmap = BitmapFactory.decodeFile(path_img);
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 14, stream);
imageView.setImageBitmap(imageBitmap);
byteArray_IMG = stream.toByteArray();
}
}
Remember this is very important
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 25, stream)
// 25 is photo quality 0-100
Then you can upload the picture usin an asynchronous process
Firstly Initialize these variables above onCreate() method in your activity/fragment
val FILE_NAME:String="photo.jpg" //give any name with.jpg extension
private var imageuri: Uri?=null
val REQUEST_IMAGE=111
Now open camera
val intent: Intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
photofile = getphotofile(FILE_NAME)
imageuri = activity?.let { it1 -> FileProvider.getUriForFile(it1, "//your package name here//.fileprovider", photofile) } //put your package name
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri)
startActivityForResult(int, REQUEST_IMAGE)
onActivityResult() method
if(requestCode==REQUEST_IMAGE && resultCode == Activity.RESULT_OK){
val progressdialog: ProgressDialog = ProgressDialog(activity)
progressdialog.setTitle("Sending Image....")
progressdialog.show() //start your progressdialog
val ref= FirebaseDatabase.getInstance().reference
val messagekey=ref.push().key //create a key to store image in firebase
var bmp: Bitmap?=null
try {
bmp=MediaStore.Images.Media.getBitmap(activity?.contentResolver,imageuri) //get image in bitmap
} catch (e: IOException) {
e.printStackTrace();
}
val baos= ByteArrayOutputStream()
bmp!!.compress(Bitmap.CompressFormat.JPEG,50,baos) //compress the quality of image to 50 from 100
val fileinBytes: ByteArray =baos.toByteArray()
val store: StorageReference = FirebaseStorage.getInstance().reference.child("Chat Images/") //create a child reference in firebase
val path=store.child("$messagekey.jpg") //store a message in above reference with the unique key created above with .jpg extension
val uploadTask: StorageTask<*>
uploadTask=path.putBytes(fileinBytes) //it will upload the image to firebase at given path
uploadTask.continueWithTask(Continuation<UploadTask.TaskSnapshot, Task<Uri>> { task ->
if (!task.isSuccessful) {
task.exception?.let {
throw it
}
Toast.makeText(activity, "Upload Failed", Toast.LENGTH_SHORT).show()
}
return#Continuation path.downloadUrl
}).addOnCompleteListener { task->
if(task.isSuccessful){
url=task.result.toString() //get the url of uploaded image
//Do what you want with the url of your image
progressdialog.dismiss()
Toast.makeText(activity, "Image Uploaded", Toast.LENGTH_SHORT).show()
}
}.addOnFailureListener { e->
progressdialog.dismiss()
Toast.makeText(activity, "Failed " + e.message, Toast.LENGTH_SHORT)
.show();
}
uploadTask.addOnProgressListener { task->
var progress:Double=(100.0*task.bytesTransferred)/task.totalByteCount
progressdialog.setMessage("Sending ${progress.toInt()}%") //this will show the progress in progress bar 0-100%
}
}

In Android, is it possible to capture screenshots from service

I'm developing an Android application to capture screenshots. What I'm trying to do is make a service with a button on the top of the screen and taking screenshot by tapping it.
I wonder if it may work, with service as I said. Also I want the button excluded from the screenshot. Am I able to do this?
Here is the code that allowed my screenshot to be stored on sd card and used later for whatever your needs are:
First, add proper permission to save file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
And this is the code (running in an Activity):
private void takeScreenshot() {
Date now = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
try {
// image naming and path to include sd card appending name you choose for file
String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
// create bitmap screen capture
View v1 = getWindow().getDecorView().getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
File imageFile = new File(mPath);
FileOutputStream outputStream = new FileOutputStream(imageFile);
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
openScreenshot(imageFile);
} catch (Throwable e) {
// Several error may come out with file handling or OOM
e.printStackTrace();
}
}
And this is how you can open the recently generated image:
private void openScreenshot(File imageFile) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(imageFile);
intent.setDataAndType(uri, "image/*");
startActivity(intent);
}
to exclude the button, you can make button hide and then take screen show after some time interval.

Saved bitmap in android is 3 bytes long when read

I have an activity to choose and save a profile picture. There is an image view and a button that starts the gallery activity for result awiting the user to choose an image. When the gallery is closed, the following code is executed:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if ((resultCode == RESULT_OK) && (requestCode == SELECT_PHOTO)) {
Uri selectedImage = data.getData();
try {
Bitmap image = this.decodeAndScaleImage(selectedImage, 285);
imgInsertPicture.setImageBitmap(image);
this.imagePresent = true;
this.saveMyProfilePicture(image);
this.popImageView();
} catch (IOException e) {
e.printStackTrace();
showToast(R.string.error_saving_picture);
}
}
}
private void saveMyProfilePicture(Bitmap picture) throws IOException {
FileOutputStream outputStream = openFileOutput(Globals.MY_PICTURE_FILE_NAME, MODE_PRIVATE);
picture.compress(Globals.MY_PICTURE_FORMAT, 90, outputStream);
outputStream.close();
ByteArrayOutputStream rawOutputStream = new ByteArrayOutputStream();
picture.compress(Globals.MY_PICTURE_FORMAT, 90, rawOutputStream);
byte[] rawPictureData = rawOutputStream.toByteArray();
rawOutputStream.close();
byte[] base64PictureData = Base64.encode(rawPictureData, Base64.DEFAULT);
rawPictureData = null;
FileOutputStream base64OutputStream = openFileOutput(Globals.MY_PICTURE_B64_FILE_NAME, MODE_PRIVATE);
base64OutputStream.write(base64PictureData);
base64OutputStream.close();
}
I debugged this code and verified that:
- no exception is thrown;
- the written files contain the exact amount of data (17kB for the jpg image, 24kB for the base64 version);
- the produced bitmap is the one that I expect and is displayed correctly in the image view.
popImageView is only used to bump the image view on top of other views that were on the front before an image was chosen; and decodeAndScale method only works on bitmap data in memory and doesn't save anything.
However, when I try to reload the current picture when the activity starts, the image displayed is blank and the jpeg file conly contains 3 bytes:
#Override
public void onStart() {
super.onStart();
if (!imagePresent && pictureExists()) {
File pictureFile = new File(getFilesDir(), Globals.MY_PICTURE_FILE_NAME);
imgInsertPicture.setImageURI(Uri.fromFile(pictureFile));
popImageView();
imagePresent = true;
}
}
Here pictureExists checks that the file name is contained in the collection returned by listFiles(). pictureFile.exists() returns true, but as I said, it conly contains 3 bytes. I also tried using BitmapFactory.decodeX, but since the file is broken, it was useless.
I cannot understand why. I checked that the file was written entirely and then it disappears...
When I was debugging on my Nexus S the code worked fine, but then I switched to a Nexus 5 and it broke.
Have you tried decoding the file to a bitmap using BitmapFactory?
http://developer.android.com/reference/android/graphics/BitmapFactory.html#decodeFile(java.lang.String)
Haven't tested the following code but can you please try:
File pictureFile = new File(getFilesDir(), Globals.MY_PICTURE_FILE_NAME);
Bitmap bitmapImage = BitmapFactory.decodeFile(Uri.fromFile(pictureFile));
imgInsertPicture.setImageBitmap(bitmapImage);
popImageView();
imagePresent = true;
Try this in your onActivityResult
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getActivity().getContentResolver().query(
selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
selectedImagePath =filePath;
then use selectedImagePath as file path.
Hope it helps.

How to send image from one activity to another in kitkat android?

In first Activity:
Intent i = new Intent(FirstActivity.this, SecondActivity.class);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] bytes = stream.toByteArray();
i.putExtra("image", bytes);
startActivity(i);
In second Activity:
byte[] byteArray = extras.getByteArray("image");
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
if (bmp != null) {
iv_1.setImageBitmap(bmp);
}
This is working for all devices and versions. But it is not working for Kitkat, why?
How to solve the issue in kitkat?
Passing such a huge file through intent is not a good practice. It would slow down the process of launching new activity.
Try to make a static reference of the image and use it in the next activity. As soon as you are done, just make it null
Make a singleton class with a Map<String, Bitmap> which will keep all images you need, and through intent send just their key names.
It is not a good for performance to pass Bitmaps from on activity to another.
Just try to save the bitmap in memory and send "Path" of bitmap to another activity and then just use BitmapFactory.decodeFile(pathName);method in another activity to get bitmap from path.
In your first activity convert imageview to bitmap
imageView.buildDrawingCache();
Bitmap bitmap = imageView.getDrawingCache();
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", bitmap);
in second activity
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
Its working on kitkat also.

How to attach Bitmap to email android

I have a bitmap that I have saved in the external storage. I already have a method that loads and returns the bitmap. My question is, how do I attach this image to an email Intent.
Note: I know how to start the email intent, I simply need to know how to attach the bitmap. Thanks.
This is how I am saving the pic:
private void savePicture(String filename, Bitmap b, Context ctx) {
try {
FileOutputStream out;
out = ctx.openFileOutput(filename, Context.MODE_WORLD_READABLE);
b.compress(Bitmap.CompressFormat.JPEG, 40, out);
if (b.compress(Bitmap.CompressFormat.JPEG, 40, out) == true)
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
try this for Attach Image with Email
Fetch Image From SdCard
String path = Environment.getExternalStorageDirectory().toString();
File file = new File(path,"YourImageName.JPEG");
Uri pngUri = Uri.fromFile(file);
Email Intent
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/html");
emailIntent.putExtra(android.content.Intent.EXTRA_STREAM, pngUri);

Categories