android – How to use onActivityResult method from other than Activity class-ThrowExceptions

Exception or error:

I am creating an app where i need to find current location of user .

So here I would like to do a task like when user returns from that System intent, my task should be done after that.(Displaying users current location)

So i am planning to use OnActivityResult().

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

}

But the problem is that I don’t know how can I use that method in a class which is not extending Activity.

Please some one give me idea how can i achieve this?

How to solve:

You need an Activity on order to receive the result.

If its just for organisation of code then call other class from Activty class.

public class Result {
    public static void activityResult(int requestCode, int resultCode, Intent data){
          ...
   }
}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       Result.activityResult(requestCode,resultCode,data);
        ...
    }

###

Create an inner class in the non Activity class and define your activity results handler therein:

class singletonActivity extends Activity{
  protected void onActivityResult(...){
    // do whatever ..
  }
}

intantiate it to call startActivityForResult

Activity actv = new singletonActivity(..)
actv.startActivityForResult(intent ..)

your handler will be called.
🙂

ps: you may have to include some overrides. just leave them empty.

pps: this is old school java mouseListenerAdapter style
~Oo>

###

You can’t call this method out of his scope.

protected void onActivityResult (int requestCode, int resultCode, Intent data)

If the method is protected like this case, you can see the table of Access Levels to know how to proceed.

|-----------------------------------------------------------|
|                     ACCESS LEVELS                         |
|------------------|---------|---------|----------|---------|
|      Modifier    |  Class  | Package | Subclass |  World  |
|------------------|---------|---------|----------|---------|
|      public      |    Y    |    Y    |    Y     |    Y    |
|------------------|---------|---------|----------|---------|
|      protected   |    Y    |    Y    |    Y     |    N    |
|------------------|---------|---------|----------|---------|
|      no modifier |    Y    |    Y    |    N     |    N    |
|------------------|---------|---------|----------|---------|
|      private     |    Y    |    N    |    N     |    N    |
|------------------|---------|---------|----------|---------|

As you can see, this method only can be called from android.app.* package, Activity and their subclasses.


SOLUTION:

You need to do something like this:

We have a class ImagePicker for selecting a image from Gallery or Camera or Delete it. This class need to call onActivityResult if user wants to delete image (We don’t need to start an Activity for a result that we already know).

public class ImagePicker {
    private ImagePickerDelegate delegate;

    public ImagePicker (ImagePickerDelegate delegate) {
        this.delegate = delegate;
    }

    //Will explain this two methods later
    public void show() {
        //Some code to show AlertDialog
    }

    public void handleResponse(Intent data) {
        //Some code to handle onActivityResult
    }

    //Our interface to delegate some behavior 
    public interface ImagePickerDelegate {
        void onImageHandled(Bitmap image);
        void onImageError();
        void onImageDeleted();
    }
}

For using this class in our Activity, we need to implement the delegate methods and pass our activity as the delegate of ImagePicker:

public class MyActivity extends Activity implements ImagePicker.ImagePickerDelegate {
    ImagePicker imagePicker;    

    @OnClick(R.id.image_edit)
    public void selectImage () {
        imagePicker = new ImagePicker(this);
        imagePicker.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == ImagePicker.REQUEST_IMAGE_PICKER && resultCode == RESULT_OK) {
            imagePicker.handleResponse(data);
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onImageHandled(Bitmap image) {
        //handle image resized
        imageView.setImageBitmap(image);
    }

    @Override
    public void onImageError() {
        //handle image error
        Toast.makeText(this, "Whoops - unexpected error!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onImageDeleted() {
        //handle image deleted
        groupImageView.setImageBitmap(null);
        groupImageView.setImageResource(R.drawable.ic_pick_picture);
    }
}

Finally, we need to make thous delegate methods to be called, and that happen in show() and handleResponse(Intent data):

//The show method create and dialog with 3 options,
//the important thing here, is when an option is selected
public void show() {
    //Inflating some views and creating dialog...

    NavigationView navView = (NavigationView)viewInflated.findViewById(R.id.navigation_menu);
    navView.setNavigationItemSelectedListener( new NavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem) {
            switch (menuItem.getItemId()) {
                case R.id.action_select_image:
                    Intent pickPhoto = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    activity.startActivityForResult(pickPhoto , REQUEST_IMAGE_PICKER);
                    break;
                case R.id.action_take_picture:
                    Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    activity.startActivityForResult(takePicture, REQUEST_IMAGE_PICKER);
                    break;
                case R.id.action_delete_image:
                    delegate.onImageDeleted(); //send response to activity
                    break;
            }
            alertDialog.dismiss();
            return true;
        }
    });

    //Show dialog...
}


//this method is called from onActivityResult
public void handleResponse(Intent data) {
    try {
        //Retrieve and resize image...
        delegate.onImageHandled(image); //send the image to activity
    } catch (Exception e) {
        e.printStackTrace();
        delegate.onImageError(); //send error to activity
    }
}

At the end, what we have, is a class that can call a method in your Activity instead of onActivityResult, but when you get a result in onActivityResult, you need to handle it in that class

###

You need to register an Activity to this class and then use OnActivityResult() for that activity.

###

When you start an activity with startActivityForResult method from an activity, only the caller will recive the result.

So you could handle the result and pass it to the task or update the ui of that activity:

int MY_REQUEST_ID = 1;

public void onClick(){
    //Select a contact.
    startActivityForResult(
             new Intent(Intent.ACTION_PICK,
             new Uri("content://contacts")),
             MY_REQUEST_ID);
}    

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
     if(requestCose == MY_REQUEST_ID && resultCode == SUCCESS) {
         MyAsyncTask task = new AsyncTask(requestCode, resultCode, data);
         task.execute();
         // or update the UI
         textView.setText("Hi, activity result: "+ resultCode);
     }
}

###

I am using it like this this may be helpful to others

In my fragment I have

// Upload Cover Photo On Button Click
btn.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {

        // Start The Image Cropper And Go To onActivityResult
        Intent intent = ImageManager.startImageCropper(getContext());
        startActivityForResult(intent, CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE);

    }
});

Then Calling The Result Like This In The Fragment

// On Activity Result for Start Activity For Result
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);

    // Get The Image From Image Cropper
    Uri resultUri = ImageManager.activityResult(requestCode, resultCode, data, getContext());
}

The public class / functions supporting these are

public class ImageManager {

    // Start Image Cropper
    public static Intent startImageCropper(Context context) {

        // Crop Image
        Intent intent = CropImage.activity()
                .setGuidelines(CropImageView.Guidelines.ON)
                .setActivityTitle("Title")
                .setCropMenuCropButtonTitle("Save")
                .setAutoZoomEnabled(true)
                .setAspectRatio(1, 1)
                .getIntent(context);

        return intent;

    }

    public static Uri activityResult(int requestCode, int resultCode, Intent data, Context context) {

        // Handle Cropped Image

        Uri resultUri = null;

        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
            CropImage.ActivityResult result = CropImage.getActivityResult(data);
            if (resultCode == Activity.RESULT_OK) {
                resultUri = result.getUri();

            } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
                Exception error = result.getError();
                Toast.makeText(context, (CharSequence) error, Toast.LENGTH_SHORT).show();
            }

        }
        return resultUri;
    }
}

###

Finally i got what i need and also the solution for this question.

 Activity con;
Intent intent_= new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            con.startActivityForResult(intent_, 0);

Now i can create a method here,

public void startActivityForResult(Intent i, int code)
{
    Log.e("", "insede method startActivityForResult()");
}

By using this System is not creating a sub-activity for my intent so,this method gets called only after user return from intent.

Leave a Reply

Your email address will not be published. Required fields are marked *