HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Camera intents and file manipulation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
filecameraintentsmanipulationand

Problem

I am building an Android application and there are five Activity classes or if you're familiar with the MVC pattern they would usually be the Controller classes.

Specifically a User will enter one of these 5 Activity classes (by navigating throughout the app) and sometimes they might upload a photo. Now the code for uploading a photo follows a very similar pattern. Please note all this code is repeated 5 times in all 5 classes (YUCK).

Global Variables:

/*
Tracking
 */
private static final int TAKE_PHOTO_REQUEST = 1;
private static final int GET_FROM_GALLERY = 2;

private Uri mUri;
private String mCurrentPhotoPath;
private File mFile;
private TypedFile mTypedFile; // For Retrofit


User hits Photo Upload Button, and a AlertDialog pops up:

private void showFileOptions() {
    new AlertDialog.Builder(this)
            .setItems(R.array.uploadOptions, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    switch (which) {
                        case 0:
                            dispatchTakePicture();
                            break;
                        case 1:
                            dispatchUploadFromGallery();
                            break;
                    }
                }
            })
            .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            })
            .show();
}


dispatchTakePicture:

```
/*
Take picture from your camera
*/
private void dispatchTakePicture() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Make sure that there is a camera activity to handle the intent
if (intent.resolveActivity(getPackageManager()) != null) {

// Create the File where the mTypedFile wou

Solution

If it was me, I should go for the third option.

Make an abstract superclass for your Activity where you can put this code into.

If some points of the method difference, you can refactor that part to an abstract method, so you can implement this part custom in each class.

Now, up to a little comments on your code.

Overall, pretty nice code with a lot of comments.

Some of the comments are not needed, while other are sure on their place so you can understand it quickly.

Their are 2 small things what I see and I prefer to see otherwise.

  • Switch => implement always default case.



  • e.printStackTrace();, please use a logger instead.



Edit after your answer :

What I see now is that you call the super of onActivityResult and that's good.

The only thing what is bothering me now is that you repeat the case after the super.

I don't know if you can make of CameraActivity an abstract class, if so try the following :

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

    startProgress();

    switch (requestCode) {
        case TAKE_PHOTO_REQUEST:
            if (resultCode == RESULT_OK) {
                mTypedFile = new TypedFile("image/*", mFile);
                doTakePhotoRequest();
            }
            break;
        case GET_FROM_GALLERY:
            if (resultCode == RESULT_OK) {
                mUri = data.getData();
                mTypedFile = UriHelper.handleUri(mUri, this);
                doFromGallery();
            }
            break;
        default:
            stopProgress();
            Toast.makeText(this, R.string.generalError, Toast.LENGTH_LONG).show();
            break;
    }
}

protected abstract void doTakePhotoRequest(); // give params if needed
protected abstract void doFromGallery(); // give params if needed


Like this you just implement these methods and you don't even have to override onActivityResult.

If it's not possible for an abstract class => just implement those methods empty and you can override them later.

Code Snippets

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

    startProgress();

    switch (requestCode) {
        case TAKE_PHOTO_REQUEST:
            if (resultCode == RESULT_OK) {
                mTypedFile = new TypedFile("image/*", mFile);
                doTakePhotoRequest();
            }
            break;
        case GET_FROM_GALLERY:
            if (resultCode == RESULT_OK) {
                mUri = data.getData();
                mTypedFile = UriHelper.handleUri(mUri, this);
                doFromGallery();
            }
            break;
        default:
            stopProgress();
            Toast.makeText(this, R.string.generalError, Toast.LENGTH_LONG).show();
            break;
    }
}

protected abstract void doTakePhotoRequest(); // give params if needed
protected abstract void doFromGallery(); // give params if needed

Context

StackExchange Code Review Q#96840, answer score: 4

Revisions (0)

No revisions yet.