I have wrote an app with 2 activities. One activity took a picture and the second one use it with some filters.
Activity 1:
Intent FilterSelectionIntent = new Intent(getActivity(), PulsFiltersActivity.class);
FilterSelectionIntent.putExtra("PicTaken", currentBitmap);
startActivity(FilterSelectionIntent);
Acitivity 2:
Bundle bd = intent.getExtras();
mBitmap = bd.getParcelable("PicTaken");
I have put some breakpoints in the Activity 2 and it never stop at. As soon as I comment the "putExtra" in comment, I can reach the breakpoints. In my case, the activity is not started, I think the intent is wrong.
I know that one solution is to use Bitmap.compress and forward the result in the Output stream. but in my case, it take too much time. My android device is a very basic one and it takes 2s to save the bmp. this why I try to use the intent to pass argument but it seems not working.
I'm also open to save the bmp as tmp file but I can lose 2 sec.
Any idea .
Bitmap implements Parcelable, so you could always pass it in the intent:
Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("BitmapImg", bitmap);
and retrieve it on the other end:
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImg");
Check it here : How can I pass a Bitmap object from one activity to another
I think you have confused a couple of concepts of sending objects. In your Activity 1, you put the extra directly to the intent. In Activity 2, you try to get it back from a Bundle, which you did not put the Bitmap to. So try this in your activity 2:
mBitmap = (Bitmap) intent.getParcelableExtra("PicTaken");
Edit: I found some reports of Bitmaps being too big to send and activites not starting when sending Bitmaps. Converting them to ByteArray may help.
You also can store the bitmap into internal storage like this:
final static String IMG_PATH= "bmp2Store"
FileOutputStream streamOut;
Bitmap image = currentBitmap;
try {
// Store bitmap into internal storage
streamOut = mContext.openFileOutput(IMG_PATH, Context.MODE_PRIVATE);
image.compress(Bitmap.CompressFormat.PNG, 100, streamOut);
streamOut.close();
// Call ActivityB
Intent intent= new Intent(this, ConsumirOfertaActivity.class);
startActivity(intent);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
And in the activityB:
final static String IMG_PATH= "bmp2Store"
Bitmap bitmap;
FileInputStream streamIn;
try {
streamIn = openFileInput(IMG_PATH);
bitmap = BitmapFactory.decodeStream(streamIn);
streamIn.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You should not pass bitmap inside bundle:
Size of the data you are allowed to pass through Bundle or Intent is very less (~1MB). Considering a object like Bitmap, there are high chances that memory allocated to it greater than 1MB. This can happen for any kind of object including byte array, String etc.
Solution:
Store your bitmap into File, FileProvider, Singleton (as WeakReference of course) class, etc before starting Activity B, and pass just URI as parameter in Bundle.
Also check out this posts:
Intent.putExtras size limit? and
Maximum length of Intent putExtra method? (Force close)
Related
Im trying to save a pdf file on a user-picked location but Im having problems passing data through the intent.
I tried using a bundle to pass the info but it is always null.
It only works if I add a local variable and assign it in the #save method. But I want to pass it through the intent.
The thing is im not going into another activity, just to choose a directory and im coming back.
`protected void save(byte[] bytes, String fileName, String mimeType) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.setType(mimeType);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_TITLE, fileName);
intent.putExtra("bytes", bytes);
activityResultLaunch.launch(intent);
}`
`ActivityResultLauncher<Intent> activityResultLaunch = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
Intent data = result.getData();
try {
Uri uri = data.getData();
OutputStream outputStream = getContext().getContentResolver().openOutputStream(uri);
// here it is always null
//byte[] bytes = data.getByteArrayExtra("bytes");
outputStream.write(bytes);
outputStream.close();
Toast.makeText(getContext(), "Successfully saved document to device!", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(getContext(), "Failed to save document to device.", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
});`
Any suggestions? I dont see what im missing here, ive been banging my head on this for a couple of hours and couldnt get it to work. Any help is greatly appreciated!
intent.putExtra("bytes", bytes);
Here, you are passing an Intent extra to the activity that you are starting. That activity is a device-supplied activity that responds to ACTION_CREATE_DOCUMENT.
More importantly, it is not your activity. It is certainly not the activity that is calling launch() for that Intent.
So, that bytes extra will be available to the ACTION_OPEN_DOCUMENT activity. That activity will ignore that extra. It will not include that extra in the completely different Intent that is delivered to your onActivityResult() method.
But I want to pass it through the intent.
That is not an option in Android, sorry.
Activity 1:I have an imageview in which the images taken from camera and gallery are set and it works fine. In this Activity there is a right click button which will redirect you to second activity.
Activity 2: In this Activity I have four options
Save
Share
Share Via Instagram
Share Via Facebook
Activity 3: From the above four options the third activity works accordingly.
Now I don't know how to pass the image taken in first activity to the third activity.
My Effort: In first Activity image taken from camera:
Intent i=new Intent(Camera.this,SaveVia.class);
i.putExtra("image", thumbnail );
startActivity(i);
In Second Activity SaveVia:
Intent intent2 = new Intent(SaveVia.this, Save.class);
Bitmap receiptimage = (Bitmap)getIntent().getExtras().getParcelable("image")
startActivity(intent2);
In third Activity called Save:
Bitmap receiptimage = (Bitmap) getIntent().getExtras().getParcelable("imagepass");
// receipt.setImageBitmap(receiptimage);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
receiptimage.compress(Bitmap.CompressFormat.PNG, 90, bytes);
File storagePath = new File(Environment.getExternalStorageDirectory() + "/PhotoAR/");
storagePath.mkdirs();
File destination = new File(storagePath, Long.toString(System.currentTimeMillis()) + ".jpg");
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
Toast.makeText(Save.this,"No Error",Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(Save.this,"Error Arrived",Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(Save.this,"Error Arrived again",Toast.LENGTH_LONG).show();
#AND
You don't need to pass bitmap as Parcelable from one activity.Pass file path in intent from one activity to another.
When you capture image get path in onActivityresult and save that path.
And redirect that two second activity.And from that path show your bitmap.Just Share Uri from path in share on facebook and Instagram.
I recommend using File I/O to save the bitmap to disk. Put the path of the file into your intent bundle using putExtra and recreate the bitmap in your other screens. Putting large bitmaps into a bundle with an intent can cause TransactionTooLarge exceptions.
Take a look at Getting path of captured image in android using camera intent
I'm creating an image filter app in Android studio. first, the user selects an image from gallery and it will be displayed in imageview. Then the user clicks edit button and that image is displayed in imageview of next activity where we can add filters... It works fine with low resolution images but when I select any high resolution image it is shown in first imageview but when I click edit button either the app crashes or the last image I had selected is displayed.I searched for the solution but couldn't find it. If anyone knows how to solve this problem please help me
There is a limit to the size of data that can be passed through an intent. The limit is roughly 500Kb - your high resolution photographs will be larger than this.
Consider saving your image to a file location on the device, passing the URI to the receiving activity and loading it within there.
first paste crash logs.
then instead of passing image itself just pass image path.
or simply add the edit tools and mainView in one activity and make edit tools invisible! however you can use fragment too.
use with putExtra to send the Uri Path:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent .setClass(ThisActivity.this, NewActivity.class);
intent .putExtra("KEY", Uri);
startActivity(intent );
You just need to add path of image.
It's better to save the image in storage and pass the Uri of location instead of passing the image.
Save image in storage:-
public static Uri saveImageOnExternalStorage(Bitmap capturedBitmap, String imageId) {
if (null != capturedBitmap ) {
OutputStream fOutputStream;
String path = Environment.getExternalStorageDirectory().toString();
File file = new File(path + "temp", mediaId + ".png");
file.delete();
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try {
if (file.createNewFile()) {
fOutputStream = new FileOutputStream(file);
capturedBitmap.compress(COMPRESS_FORMAT, 100, fOutputStream);
fOutputStream.flush();
fOutputStream.close();
return Uri.fromFile(file); // return saved image path on external storage
}
} catch (FileNotFoundException e) {
Log.e(TAG,e.getMessage());
return null;
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG,e.getMessage());
}
}
return null;
}
Now the same Uri you can pass in the intent of next activity:-
Intent intent = new Intent(CurrentActivity.this, LaunchActivity.class);
intent .putExtra("image_key", Uri);
startActivity(intent );
I'm trying to share from my app to Hyves using share intent. If I have hyves app installed and share from gallery it switch to hyves app, and upload image correctly to hyves, so it should work.
Problem is, I can't find it documented how should proper intent for hyves work, but I assume that gallery uploads images only, so I have this:
Bitmap image = BitmapFactory.decodeFile(MyGlobals.INSTANCE.activeSetting.f_image_path);
It's line of code where I pull my "active" or "selected" image within my app. At this point image is saved to SD Card, so I might read uri instead of decoding file, but I want it this way to have same approach for both hyves and facebook.
Then I call:
Intent hyvesIntent = new Intent(Intent.ACTION_SEND);
hyvesIntent.setPackage("com.hyves.android.application");
hyvesIntent.setType("image/jpeg");
hyvesIntent.putExtra("image", image);
startActivityForResult(hyvesIntent, 666);
First of all, I'm not sure if setPackage is OK to be used here, but I'm checking if this package exist to enable / disable share, and this is package name that is visible.
I need Activity result to then notify that Image is shared or not.
What happens here it starts the Hyves app, but I get full white screen, and then the Hyves app times out.
So, Can I use Bitmap in intent, and is it OK to setPackage or should I setClass?
Tnx
Maybe you can not put the bitmap directly in the intent.
First convert the bitmap into a byte array than send another side and convert into bitmap
//convert bitmap to bytearray
public static byte[] getBitmapAsByteArray(Bitmap bitmap, boolean type) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if (type) {
bitmap.compress(CompressFormat.PNG, 0, outputStream);
} else {
bitmap.compress(CompressFormat.JPEG, 0, outputStream);
}
return outputStream.toByteArray();
}
//convert bitmap to bytearray
public static Bitmap getBitmap(byte[] imgByte){
Bitmap bm = BitmapFactory.decodeByteArray(imgByte, 0, imgByte.length);
return bm;
}
//than intent
Intent hyvesIntent = new Intent(Intent.ACTION_SEND);
hyvesIntent.setPackage("com.hyves.android.application");
hyvesIntent.setType("image/jpeg");
hyvesIntent.putExtra("image", getBitmapAsByteArray(image,true));
startActivityForResult(hyvesIntent, 666);
I hope that is right way to put image
How can I pass an image, drawable type between activities?
I try this:
private Drawable imagen;
Bundle bundle = new Bundle();
bundle.putSerializable("imagen", (Serializable) unaReceta.getImagen());
Intent myIntent = new Intent(v.getContext(), Receta.class);
myIntent.putExtras(bundle);
startActivityForResult(myIntent, 0);
But it reports me an execption:
java.lang.ClassCastException: android.graphics.drawable.BitmapDrawable
1) Passing in intent as extras
In the Activity A you decode your image and send it via intent:
Using this method (extras) image is passed in 162 milliseconds time interval
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
Intent intent = new Intent(this, ActivityB.class);
intent.putExtra("picture", b);
startActivity(intent);
In Activity B you receive intent with byte array (decoded picture) and apply it as source to ImageView:
Bundle extras = getIntent().getExtras();
byte[] b = extras.getByteArray("picture");
Bitmap bmp = BitmapFactory.decodeByteArray(b, 0, b.length);
ImageView image = (ImageView) findViewById(R.id.imageView1);
image.setImageBitmap(bmp);
2) Saving image file and passing its reference to another activity
WHY to do so? - taken from http://groups.google.com/group/android-developers/browse_frm/thread/9309931b3f060284#
"The size limit is: keep it as small as possible. Definitely don't put
a bitmap in there unless it is no larger than an icon (32x32 or
whatever).
In *Activity A* save the file (Internal Storage)
String fileName = "SomeName.png";
try {
FileOutputStream fileOutStream = openFileOutput(fileName, MODE_PRIVATE);
fileOutStream.write(b); //b is byte array
//(used if you have your picture downloaded
// from the *Web* or got it from the *devices camera*)
//otherwise this technique is useless
fileOutStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
Pass location as String to Activity B
Intent intent = new Intent(this, ActivityB.class);
intent.putExtra("picname", fileName);
In *Activity B* retrieve the file
Bundle extras = getIntent().getExtras();
String fileName = extras.getString("picname");
Make *drawable* out of the picture
File filePath = getFileStreamPath(fileName);
Drawable d = Drawable.createFromPath(filePath.toString());
Apply it to the ImageView resource
someImageView.setBackgroundDrawable(d);
You can tag each image (in the xml, or programmaticlly) with the image resource name (like "img1.png"),
then retrieve the image name using the getTag();
Then use getResources().getIdentifier(image name,"drawable", .getPackageName()) to get the drawable resource id.
And just pass the resource id through the intent -
intent.putExtra("img 1",resource id);
Lastly the result Activity can create the image from the resource using:
getResources().getDrawable(intent.getIntExtra("img 1",-1));
Drawable objects are not inherently serializable, so they cannot be passed directly in Intent extras. You must find another way to serialize or persist the image data and retrieve it in the new Activity.
For example, if you are working with BitmapDrawable instances, the underlying Bitmap could be written out to a file and read back, or serialized into a byte array (if its small enough) and the byte array could be passed via extras of an Intent.
HTH
Much much much better not to pass (or serialize) Drawables around among Activities. Very likely your are getting the drawable out of a resource. Hence there's a resource ID. Pass that around instead, that's just an int. And re-hydrate the Drawable in the other Activity.
If the Drawable is not coming from a resource, but it's built at runtime in memory ... well let's speak about it. #Devunwired has a nice suggestion in that case.
You can simply use a native buildDrawingCache method:
ImageView imageView = imageLayout.findViewById (R.id.img_thumb);
imageView.buildDrawingCache ();
Bundle extras = new Bundle ();
extras.putParcelable ("image", imageView.getDrawingCache ());
Intent intent = new Intent (this, ImageActivity.class);
intent.putExtras (extras);
startActivity (intent);
then get it at your ImageActivity:
Bundle bundle = getIntent ().getExtras ();
if (bundle != null) {
ImageView imageView = findViewById (R.id.img_full);
Bitmap image = bundle.getParcelable ("image");
imageView.setImageBitmap (image);
}
In case you pull those images from web and load them again and again, caching them would be really good option since you'll decrease network traffic and increase loading speed. I suggest using WebImageView from Droid-Fu. Really good solution, used it on some projects and I'm very satisfied with it.
I don't know if this is the case, but if the reason why you are trying to pass a drawable is because you are using an Imageview, just put the resource id in the imageview's tag, pass the tag as an Integer instead of the drawable in the intent's extra and use the following line in the receiving activity:
imageView.setImageDrawable(getResources().getDrawable(getIntent().getIntExtra("image_id",0)));
Hope it will help someone.