Search code examples
androidandroid-intentandroid-arrayadapterandroid-gallery

startActivityForResult passing data through to "toActivityResult" using ArrayAdapter


I have created a custom list interface. I'm using an array adapter to manage my list view cell's button clicks. One of my buttons opens a dialog that shows the device's gallery and allows them to choose an image.

In my Adapters getView method, I have the on click listeners for the buttons. When I choose the image. The onActivityResult method in my Activity gets called as it should. But I'm having trouble reading the intent.putExtras("id", id) as it is read as null in the Activity. Here is my method where the startActivityForResult is called in my MainActivityListAdapter:

public void showExtraPicture(String imgStr, final String qid, String qname) {
    ImageButton gallery = (ImageButton) dialog.findViewById(R.id.gallerybtn);
    gallery.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            System.out.println("BIT: Qid: " + qid);
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            Bundle mBundle = new Bundle();
            mBundle.putSerializable("qid", qid);
            intent.putExtras(mBundle);
            ((Activity) QuestionListAdapter.this.context).startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
            dialog.dismiss();
        } // end method onClick
    }); // end setOnClickListener

}

I have tried using Bundle putSerializable but that isn't working for me. I'm guessing my problem has to do with me calling the data from the ArrayAdapter.

Here is my onActivityResult in my MainActivity:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Bundle mBun = data.getExtras();
    String qid = "";
    if (mBun != null) {
        qid = (String) mBun.getSerializable("qid");
    }
    if (requestCode == 1) {
        if (resultCode == RESULT_OK) {
            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 filePath = cursor.getString(columnIndex);
            cursor.close();


            Bitmap yourSelectedImage = BitmapFactory.decodeFile(filePath);
            try {
                Bitmap image = getBitmapFromUri(selectedImage);
                String stringRepresention = BitMapToString(image);

                //Save string to DB
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

Solution

  • The Intent supplied to onActivityResult() is not the same as the one you used for startActivityForResult(); the activity started for the result will use setResult(int resultCode, Intent data) to set the Intent supplied to your onActivityResult() function.

    Therefore, any extras you supply on your original intent are only useful when the target activity (an image chooser, in your case) is doing its job -- you will not see those extras in your result (unless the target activity goes out of its way to copy them into the result intent, of course).

    What do you need to propagate qid for? You didn't include the usage on the receiving side... so I will assume that you need it to know where to put the chosen image in some way.

    In that case, you should use the requestCode functionality. Let your app keep track of pending requests with a requestCode->qid mapping. Make sure to use a unique requestCode for every startActivityForResult() call. You will get that requestCode back as an argument to onActivityResult() -- look it up in your map, and you'll have the related qid. Don't forget to clean up your map when the requests come back.

    Possible caveat: you may need to store the mapping persistently on disk, in case your process is killed while the image selector is on top. That situation will likely be rare, but you should make sure to test it and handle it if needed.