I am receiving a NullPointerException error on my getIntent() when trying to pass a bitmap from one activity to an another activity
First Activity
public void processor(View view)
{
BitmapDrawable drawable = (BitmapDrawable)imageCapt.getDrawable();
Bitmap yeet = drawable.getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
yeet.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] bytes = stream.toByteArray();
Intent intent = new Intent(camera_activity.this, ClassifierTask.class);
intent.putExtra("picture", bytes);
startActivity(intent);
}
Receiving Activity
public class ClassifierTask extends AsyncTask<Void,Void,Void> {
static Context context;
#Override
public void onPreExecute() {
super.onPreExecute();
}
#Override
public Void doInBackground(Void... param) {
Intent intent = ((Activity)context).getIntent();
byte[] bytes = intent.getByteArrayExtra("picture");
m_bitmapForNn = BitmapFactory.decodeByteArray(bytes,0, bytes.length);
The error I receive is
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Intent android.app.Activity.getIntent()' on a null object reference
Any advice or solution for this, would be appreciated
I have a very good way
You create a new one Class,and new static
public class Data {
public static byte[] bytes;
}
or setup HashMap,ArrayList....
you just put data and read In another place
Data.bytes[0]=
Related
I have a fragment that contains an image view and button when I click on the button am going to an activity that has an image as a bitmap and in the activity, I have a button (save) that should finish the activity and go back to the fragment with the bitmap data.
I tried to use intents and bundles but nothing worked.
You need to convert your Bitmap data to an byte array then put it into the Bundle
ByteArrayOutputStream mStream = new ByteArrayOutputStream();
yourBitmapImage.compress(Bitmap.CompressFormat.PNG, 100, mStream);
byte[] byteArray = mStream.toByteArray();
Bundle mBundle = new Bundle();
mBundle.putByteArray("image",byteArray);
Passing Bitmap Object via bundle intents is very dangerous and you may end up getting errors especially for bitmaps of uknown lengths since there is even a limit for the size of the Parcelable extra.its highly unrecomended .Better solution would be to save it to a file then the path to a String value and pass it to the next activity or even to shared prefrence just in case it might be needed even after the app closes or even needed elsewhere in your code without using up your memory.Bitmaps especially are a great threat to memory if mishandled.See
public class Bitmap_saver{
public static String my_bitmap_path(Context act) {
SharedPreferences prefs = act.getSharedPreferences("SHAREDpREFname", act.MODE_PRIVATE);
return prefs.getString("my_bitmap_address", null);
}
public static void set_my_bitmap_address(Context act, String path) {
SharedPreferences.Editor saver = act.getSharedPreferences("SHAREDpREFname", act.MODE_PRIVATE).edit();
saver.putString("my_bitmap_address", path);
saver.commit();
}
public static String save_to_file(Bitmap fpb)
{
String img_name="BIT_"+ System.currentTimeMillis()+".JPG";
OutputStream fOutputStream = null;
File file = new File( Environment.getExternalStorageDirectory().toString() + "/YOUR_APP_DATA/");
if (!file.exists()) {
Log.e("Creating data dir=>",""+ String.valueOf(file.mkdirs()));
}
file = new File(Environment.getExternalStorageDirectory().toString() + "/YOUR_APP_DATA/", img_name);
try {
fOutputStream = new FileOutputStream(file);
fpb.compress(Bitmap.CompressFormat.JPEG, 100, fOutputStream);
fOutputStream.flush();
fOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
return "error";
} catch (IOException e) {
e.printStackTrace();
// Toast.makeText(this, "Save Failed", Toast.LENGTH_SHORT).show();
return "error";
}
return file.getAbsolutePath();
}
}
Call it like this to save Bitmap_saver.set_my_bitmap_path(your_context,Bitmap_saver.save_to_file(your_bitmap));
from your retreiving fragment/activity/class call this Bitmap myBitmap = BitmapFactory.decodeFile(Bitmap_saver.my_bitmap_path(your_context));
I end up using this approach:
in your fragment:
Intent signatureIntent = new Intent(getActivity(), SignatureActivity.class);
startActivityForResult(signatureIntent, your_request_code);
#Override
public void onActivityResult(int requestCode, int resultCode,
#Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == your_request_code&& resultCode == Activity.RESULT_OK){
String received = data.getStringExtra("extra");
byte[] decodedString = Base64.decode(received, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0,
decodedString.length);
}
}
in your activity:
bitmap = signatureView.getSignatureBitmap();
Intent resultIntent = new Intent();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
resultIntent .putExtra("extra",encoded);
setResult(Activity.RESULT_OK, resultIntent);
finish();
I have a class(A) who need to take a picture, so I create an other class(B) with this responsibility. But the problem is, that A don't wait the result of B. How can I do that?
Here is my code :
Class which take the picture
static final int REQUEST_IMAGE_CAPTURE = 1;
Bitmap image = null;
public void takePicture(Context context, Activity activity) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
image = (Bitmap) extras.get("data");
}
}
public Bitmap getImage(){
return image;
}
The method which call the the Camera class
public void openCamera() {
Bitmap image = null;
camera.takePicture((Context) _addView, (Activity) _addView);
image = camera.getImage();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
byte[] picture = outStream.toByteArray();
_addView.SetCameraPicture(picture);
}
While taking pictures what you are doing is opening another app(startActivityForResult) which is capable of taking pictures. When the app finishes taking the picture you are sent the data through an intent which you listen using onActivityResult. The other class B must be an
Activity(startActivityForResult() can be called only from an Activity).
So with your scenario, you must first open Activity B, then take the picture,
put the result into an intent and start Activity A with that data, which just does not make any sense. If you want to follow DRY principles put your photo taking method into a utility class and dependency inject your class to wherever you need it. Hope this helps.
You can always try to make class B async and then let class A await the method of class B
When I try to get the result from the camera I keep getting a "NullPointerException: uri" at the line:
InputStream stream = getContentResolver().openInputStream(data.getData());
from the code:
if (requestCode == CAMERA_PIC_REQUEST) {
try {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
pic.setImageBitmap(thumbnail);
InputStream stream = getContentResolver().openInputStream(data.getData());
bitmapPic = BitmapFactory.decodeStream(stream);
Being pic an ImageViewer and the image is successfully placed in the ImageViewer I can't seem to find the reason as to why this is not working.
Also here's the code for the Intent that starts the image capturer.
pic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAMERA_PIC_REQUEST);
}
});
And the part of the code that I will use it on after this is working, or at least trying to:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmapPic.compress(Bitmap.CompressFormat.JPEG, 50, baos);
byte[] data = baos.toByteArray();
mStorageRef.child(animal.getPictureID()).putBytes(data);
Being the last line Firebase related.
Also bitmapPic is a Bitmap.
Edit 1: Tried a suggestion by adding global variable:
private FileProvider mImageUri;
then
public void onClick(View view) {
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(Intent.EXTRA_STREAM, mImageUri);
startActivityForResult(intent, CAMERA_PIC_REQUEST);
}
But it says that putExtra combination doesn't exist. Not sure if that's what you meant.
Edit 2: Managed to get it working. As of now it only sends the Thumbnail but at least it's something here's how I did it:
if (requestCode == CAMERA_PIC_REQUEST) {
try {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
pic.setImageBitmap(thumbnail);
encodeBitmap(thumbnail);
}
where:
ByteArrayOutputStream baos;
public void encodeBitmap(Bitmap bitmap) {
baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
}
And finally to send it to firebase I used this:
byte[] data = baos.toByteArray();
mStorageRef.child(animal.getPictureID()).putBytes(data);
I connected to the camera via API. When a function
camera.takePicture(null, null, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
returns an array of byte [] data. If I understand correctly, this is our picture. How can I pass this array of bytes by Intent and set the resulting image next Activiti?
You could try:
Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data.length());
Then assuming the data you want to pass implements Serializable(which it should), passing it through an Intent should be as simple as:
from one activity:
i.putExtra("image", bitmap);
startActivity(i);
into the next next activity:
Intent i = getIntent();
Bitmap data = (Bitmap)i.getSerializableExtra("image");
i have success whit this way
First part
public void takePicture(View view) {
camera.takePicture(null, null, new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Intent intent = new Intent(context, AcceptNotAccept.class);
intent.putExtra("picture", data);
startActivity(intent);
}
}
}
and then got this Intent
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_accept_not_accept);
Bundle extras = getIntent().getExtras();
byte[] byteArray = extras.getByteArray("picture");
bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
((ImageView)findViewById(R.id.ivForAcceptPicture)).setImageBitmap(bitmap);
}
The idea here is to save the image into your External/Internal memory (prefer: External like SD) and use the full path of the image e.g.
Intent i = new Intent(...);
i.putExtra("myimage","path://example.path/image.jpg");
startActivity(i);
The receiving activity can get the image by calling its path:
String imagePath = getIntent().getStringExtra("myimage");
I have Activity A, B and C. In Activity C, it has an image and caption. The image and caption will be return to B when ok button is clicked. In activity b, it will return both to activity A.
Activity C
ok.setOnClickListener(new View.OnClickListener() // ok button to return image and caption to B
{
public void onClick(View arg0)
{
Intent returnIntent=new Intent();
text=t.getText().toString();
b.setDrawingCacheEnabled(true);
b.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
b.layout(0, 0, b.getMeasuredWidth(), b.getMeasuredHeight());
b.buildDrawingCache(true);
returnIntent.putExtra("text", text);
if (b.getDrawingCache() != null) {
Bitmap bitmap = Bitmap.createBitmap(b.getDrawingCache());
if (bitmap == null) {
Log.e("TAG", "getDrawingCache() == null");
}
Global.img = bitmap;
}
setResult(Activity.RESULT_OK, returnIntent);
finish();
}
});
Activity B
public void onActivityResult(int requestCode,int resultCode, Intent data)
{
if(requestCode==PROJECT_REQUEST_CODE) {
if(data!=null&&data.hasExtra("text")) {
c = data.getStringExtra("text");
txt1.setText(c); // caption can show in txt1
viewImage.setImageBitmap(Global.img); // image from C can show in viewImage
}
}
else if (requestCode==CAMERA_REQUEST_CODE)
{
}
}
b.setOnClickListener(new View.OnClickListener() { // button to return image and caption to A
public void onClick(View arg0) {
Intent returnIntent = new Intent();
returnIntent.putExtra("c",c); // return caption
returnIntent.putExtra("globalImg",Global.img);
setResult(Activity.RESULT_OK, returnIntent);
finish();
}
});
Activity A
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Bitmap b = Global.img
if (requestCode==1) {
caption = data.getStringExtra("c"); // caption from A
v.setImageBitmap(Global.img) // image from C
}else if {.....}
}
Global.java
public class Global {
static Bitmap img;
}
When I click button b in Activity B, I get this
11-05 17:26:47.114 6031-6031/com.example.project.project
E/JavaBinderīš !!! FAILED BINDER TRANSACTION !!!
Provided what you are trying to do is simply to pass along the data returned from C->B on to A, why don't you just get the string again in your onClick and put it into your intent?
You could store the text in a String member, or, as the code looks now, even get it back from the TextView:
Intent returnIntent = new Intent();
returnIntent.putExtra("text", txt1.getText().toString);
setResult(Activity.RESULT_OK, returnIntent);
The image is being stored as a static in a global object, which honestly is horrible, but you could of course access that as well from your onClickListener. You should however seriously consider returning the bitmap data in some other way, the most straightforward probably being utilizing that Bitmaps implement the Parcelable interface, and Intents can hold Parcelables as extras, so in theory you can just do putExtra("img", bitmap) and on the receiving end do intent.getParcelableExtra("img").
However, if the bitmap is large this might fail, and it might be better to store the bitmap to a resource such as a file, and pass the location of the file instead. You may also get a way with something like what you did with your static member in the Global class, but 1) you must be careful to remove the object after passing it back or the static reference will waste memory and 2) make sure you don't use this reference incorrectly, e.g. from multiple places simulatenously. A more robust solution is to make sure you create a unique ID for each bitmap and store it in a cache (for example a HashMap with the Bitmaps hashCode() as the key) and identify it by id.
public class BitmapStore {
private static final HashMap<Integer, Bitmap> BITMAPS= new HashMap<>();
public static Bitmap getBitmap(int id) {
return BITMAPS.remove(id);
}
public static int putBitmap(Bitmap b) {
int id = b.hashCode();
BITMAPS.put(id, b);
return id;
}
}
Using this, you could put the ID of your bitmap in your intent:
intent.putExtra("imageId", BitmapStore.putBitmap(bitmap));
setResult(RESULT_OK, intent);
and in onActivityResult:
Bitmap b = BitmapStore.getBitmap(intent.getIntExtra("imageId", 0));
This bitmap store is not persistant but it should be pretty safe to use as an intermediate store in the transition between two activities. It's also possible to generalize to any kind of object implementing a valid hashCode/equals contract.
try comment this line:
//returnIntent.putExtra("globalImg",Global.img);
in your Activity B
You can use Global.img for all Activity and not use intent
Added:
v.setImageBitmap(Global.img); -> nullPointerExeption becouse v is not initialize
Added:
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = false;
bitmapOptions.inPreferredConfig = Config.RGB_565;
bitmapOptions.inDither = true;
For "Out of memory" error.