0

I have an onClick listener of a checkbox set up here:

@Override
                public void onClick(View v) {
                    if (addCheckbox.isChecked()) {
                        System.out.println("Checked");
                        PackageManager pm = mContext.getPackageManager();
                        Drawable icon = null;
                        try {
                            icon = pm
                            .getApplicationIcon(entry.activityInfo.packageName);
                        } catch (NameNotFoundException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        Drawable default_icon = pm.getDefaultActivityIcon();
                        if (icon instanceof BitmapDrawable
                                && default_icon instanceof BitmapDrawable) {
                            BitmapDrawable icon_bd = (BitmapDrawable) icon;
                            Bitmap icon_b = icon_bd.getBitmap();
                            BitmapDrawable default_bd = (BitmapDrawable) pm
                                    .getDefaultActivityIcon();
                            Bitmap default_b = default_bd.getBitmap();
                            if (icon_b == default_b) {
                                // It's the default icon
                                scaleDownBitmap(default_b, 100, v.getContext());
                                Log.d("AppInfoAdapter", "Scale Bitmap Chosen");

                                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                                default_b.compress(Bitmap.CompressFormat.PNG, 100, stream);
                                byte[] byteArray = stream.toByteArray();
                                Log.d("AppInfoAdapter", "Scale Bitmap to Array");

                                Intent intent = new Intent(v.getContext(), Drag_and_Drop_App.class);
                                intent.putExtra("picture", byteArray);
                                v.getContext().startActivity(intent);
                                Log.d("AppInfoAdapter", "Intent started to send Bitmap");
                            }
                        }
                    } else {
                        System.out.println("Un-Checked");
                    }

                }
            });

and am trying to get the Intent sent here (that contains the bitmap) to my gridView here (this is the gridView adapter):

   // Keep all Images in array list
public ArrayList<Integer> drawables = new ArrayList<Integer>();

// Constructor
public GridViewAdapter(Context c){
    mContextGV = c;
    Log.d("GridViewAdapter", "Constructor is set");

    drawables.add(R.drawable.pattern1);
    Log.d("GridViewAdapter", "pattern1 added");

    drawables.add(R.drawable.pattern2);
    Log.d("GridViewAdapter", "pattern2 added");

    drawables.add(R.drawable.trashcan);
    Log.d("GridViewAdapter", "trashcan added");

    drawables.add(R.drawable.ic_launcher);
    Log.d("GridViewAdapter", "ic_launcher added");
}

But since I don't have anything to get in my adapter, I would have to get the bitmap here: (where my gridView is actually set up):

// set layout for the main screen
    setContentView(R.layout.drag_and_drop_app);

    // GridView
    Log.d("D&D", "onCreate called");

    Bundle extras = getIntent().getExtras();
    byte[] byteArray = extras.getByteArray("picture");
    Bitmap default_b = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);

    android.widget.GridView gridView = (android.widget.GridView) findViewById(R.id.GRIDVIEW1);

    // Instance of Adapter Class
    gridView.setAdapter(new GridViewAdapter(this));

But then I am unable to add that bitmap default_b to my gridView.

How can I do this?

UPDATED CODING:

                    @Override
                public void onClick(View v) {
                    if (addCheckbox.isChecked()) {
                        System.out.println("Checked");
                        PackageManager pm = mContext.getPackageManager();
                        Drawable icon = null;
                        try {
                            icon = pm
                            .getApplicationIcon(entry.activityInfo.packageName);
                        } catch (NameNotFoundException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        Drawable default_icon = pm.getDefaultActivityIcon();
                        if (icon instanceof BitmapDrawable
                                && default_icon instanceof BitmapDrawable) {
                            BitmapDrawable icon_bd = (BitmapDrawable) icon;
                            Bitmap icon_b = icon_bd.getBitmap();
                            BitmapDrawable default_bd = (BitmapDrawable) pm
                                    .getDefaultActivityIcon();
                            Bitmap default_b = default_bd.getBitmap();
                            if (icon_b == default_b) {
                                // It's the default icon
                                scaleDownBitmap(default_b, 100, v.getContext());
                                Log.d("AppInfoAdapter", "Scale Bitmap Chosen");

                                SaveImage(default_b);

                                Intent intent = new Intent(v.getContext(),Drag_and_Drop_App.class);
                                intent.putExtra("picture", fname);
                                v.getContext().startActivity(intent);
                                Log.d("AppInfoAdapter", "Intent started to send Bitmap");

                            }
                        }
                    } else {
                        System.out.println("Un-Checked");
                    }

                }
            });

    // return view
    return v;
}

and here is the class:

    public void SaveImage(Bitmap default_b) {

    String root = Environment.getExternalStorageDirectory().toString();
    File myDir = new File(root + "/saved_images");
    myDir.mkdirs();
    Random generator = new Random();
    int n = 100000;
    n = generator.nextInt(n);
    String fname = "Image-" + n +".jpg";
    File file = new File (myDir, fname);
    if (file.exists()) file.delete();
    try {
        FileOutputStream out = new FileOutputStream(file);
        default_b.compress(Bitmap.CompressFormat.JPEG, 90, out);
        out.flush();
        out.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
user2909006
  • 253
  • 6
  • 22

1 Answers1

0

You shouldn't be passing a byte array into an intent. Intent bundles have a maximum size when being sent between activities, and furthermore may bog down your application as they are serialized and deserialized.

See also this issue describing your exact problem, and note that the issue was closed with "working as intended". In the words of Romain Guy:

It is very costly to pass large amount of data via Intents. You should NOT be using Intents as a transport mechanism for bitmaps. Instead, pass around URIs or any other location mechanism (file path, etc.)

I would urge you to write the image to the cache directory and read it asynchronously from the other activity.

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
  • How do I write the image to the cache directory? – user2909006 Nov 24 '13 at 18:02
  • Also, how would I thren read from the cache directory in my gridView adapter so that I can use it in the gridView? After looking around on the cache directory, it appears as though that's only for images from the internet with a URL? If I am wrong or mistaken please let me know as I am new to this. – user2909006 Nov 24 '13 at 18:03
  • If you already have a mechanism in place for reading images from a URI, you can simply use the local URI (`file://` followed by the absolute path to your cached image) to load it. As for writing the image, you could for instance [take a look at this answer](http://stackoverflow.com/a/673014/154306). – Paul Lammertsma Nov 24 '13 at 18:56
  • Ok...so basically I would change my coding to use a FileOutput stream and not a byteArray one? And then also I don't have anything for reading images from a URI so how exactly would I get the image from the FileOutput stream so that I can use it in a gridView? – user2909006 Nov 24 '13 at 19:09
  • Please note that I am using the bitmap that I make in my onClick method above – user2909006 Nov 24 '13 at 19:10
  • Yes, you should write the file using an output stream. Provide the filename into the intent, and obtain it again from the target activity. Finally, load the image into your GridView from the file using [BitmapFactory.decodeFile(String)](http://developer.android.com/reference/android/graphics/BitmapFactory.html#decodeFile(java.lang.String)), or use a library of your choosing such as Retrofit. – Paul Lammertsma Nov 24 '13 at 19:15
  • Ok so I went off on my own a bit and went to [here](http://stackoverflow.com/questions/7887078/android-saving-file-to-external-storage) and I'll post my updated coding above. So I had an error on my intent on "file", so I just made it a global variable by using `File file;` is that ok? If that is all good, I'll start on obtaining it and using it in my gridView. – user2909006 Nov 24 '13 at 19:27
  • Then in my Drag_and_Drop_App, I would get it by using `Bundle extras = getIntent().getExtras(); String fname = extras.getString("picture"); Bitmap default_b = BitmapFactory.decodeFile(fname);` right? But then how would I make that usable in my gridViewAdapter so that I can put it in my gridView? – user2909006 Nov 24 '13 at 19:54
  • OR in my gridViewAdapter would I just use `Bitmap default_b = BitmapFactory.decodeFile("picture");`? – user2909006 Nov 24 '13 at 20:04
  • This well exceeds the scope of the question, and furthermore I don't know what your objective is or how the application should fit together. I'd suggest you take a step back and rethink your approach. Yes, you should can read strings from an intent in that fashion, and there are various ways to provide it into your GridView. Depending on what your objective is, you could store the result in an associated object, provide it into the GridView's adapter, or simply statically reference it from the adapter itself. Feel free to post a new question now that you've overcome your initial problem. – Paul Lammertsma Nov 24 '13 at 22:13