0

I am working on an Android app where part of the functionality is that the user can select an image from their device, associate it with a specific item from a list, and use it in the app. My intention was to store the image itself in internal memory and the path to the image in a SQLite database with the rest of the stored information for the item.
I have been able to get the user to select and image and upload it, but the image is sometimes rotated depending on how the picture was taken. I've tried looking at the Exif data, but the orientation is always zero. I've tried using a cursor for the MediaStore.Images.Media.DATA information, but also to no avail. The current state of the relevant code is as follows:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_details);

    mDbHelper = new EntryDbHelper(this);

    Intent intent = getIntent();
    pId = intent.getIntExtra(PhrasesActivity.T_KEY, -1);

    mImageView = (ImageView) findViewById(R.id.details_img);
    mImageView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            //Making an intent to Pick an image, looking for an Internal URI
            Intent pickImageIntent = new Intent(Intent.ACTION_GET_CONTENT);
            //Setting the content to images
            pickImageIntent.setType("image/*");
            if(pickImageIntent.resolveActivity(getPackageManager()) != null) {
                startActivityForResult(pickImageIntent, REQUEST_IMAGE_GET);
            }

            return true;
        }
    });

    setText();
    setImage();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(requestCode == REQUEST_IMAGE_GET && resultCode == RESULT_OK) {
        Bitmap image = null;
        Uri imageUri = data.getData();

        try {
            image = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
        } catch(FileNotFoundException e) {
            e.printStackTrace();
        } catch(IOException e) {
            e.printStackTrace();
        }

        mImageView.setImageBitmap(image);

        String path = storeImage(image);

        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(PhraseEntry.COLUMN_URI, path.toString());

        String selection = PhraseEntry._ID + " = ?";
        String[] selectionArgs = {Integer.toString(pId)};

        int count = db.update(PhraseEntry.TABLE_NAME, values, selection, selectionArgs);

        if(count == 1) {
            Toast.makeText(this, "Image Updated Successfully", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "Image Updated UNSUCCESSFULLY", Toast.LENGTH_SHORT).show();
        }
    }
}

private void setImage() {
    SQLiteDatabase db = mDbHelper.getReadableDatabase();

    String[] projection = {
            PhraseEntry.COLUMN_URI
    };

    String selection = PhraseEntry._ID + " = ?";
    String[] selectionArgs = {Integer.toString(pId)};

    Cursor cursor = db.query(PhraseEntry.TABLE_NAME, projection, selection, selectionArgs,
            null, null, null);

    String imagePath = "";

    while(cursor.moveToNext()) {
        imagePath = cursor.getString(
                cursor.getColumnIndexOrThrow(PhraseEntry.COLUMN_URI)
        );
    }

    if(!imagePath.isEmpty()) {

        try {
            File f = new File(imagePath, "phrase_" + Integer.toString(pId));
            Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
            mImageView.setImageBitmap(b);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }
    else {
        mImageView.setImageResource(R.drawable.sample);
    }
    cursor.close();
}

Here is the relevant layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.bladefrisch.discoveringtalk.DetailsActivity">

    <ImageView
        android:id="@+id/details_img"
        style="@style/DetailImage"
        android:contentDescription="Sample"
        android:src="@drawable/sample" />

    <TextView
        android:id="@+id/details_text"
        style="@style/DetailText"
        tools:text="Hello, how are you?" />

</LinearLayout>

This allows the user to select an image, upload it to the image view (sometimes rotated), store the image, and retrieve the image after shutting down the app. The rotation is the only major issue, and the fixes I have tried are not reflected here. I have follow too many answers here to cite, but they fall into three major categories: checking Exif tags and rotating the Bitmap with a matrix, using a cursor to get the image information and rotating, and using Glide. All three failed, and I am at a loss for what to do next. Any suggestions?

The complete code can be found here.

UPDATE
As requested, I've added the Exif checking code to no avail. As mentioned before, the orientation is always zero, so I get a null bitmap based on the code in the link.

BFrisch
  • 13
  • 7
  • "Any suggestions?" -- ask a question where you show one of your "fixes [you] have tried" and ask for help with it, providing specific details of what is not working. We cannot help you with code that we cannot see. The code that you have here definitely does not work, as it will do nothing to rotate the image. FWIW, [this sample app](https://github.com/commonsguy/cw-omnibus/tree/v8.6/Camera/EXIFRotater) demonstrates the "checking Exif tags and rotating the Bitmap with a matrix" solution, along with rotating the `ImageView`. – CommonsWare Jul 15 '17 at 20:40
  • See [link](https://stackoverflow.com/questions/14066038/why-does-an-image-captured-using-camera-intent-gets-rotated-on-some-devices-on-a) – Fatih Santalu Jul 15 '17 at 22:03
  • @CommonsWare I've added the code I tried before, with some minor alterations based on the link from santalu. I've updated my question with the results. – BFrisch Jul 16 '17 at 01:49

1 Answers1

0

I do not know what saveImage() does. Given that it takes in a Bitmap and returns a "path", I assume that it is saving that Bitmap to a file. If so, that will certainly not work, as a Bitmap does not have EXIF data.

Use the support library's edition of ExifInterface to read in the EXIF tags from the original content. Use getContentResolver().openInputStream(imageUri) to get an InputStream, passing that to the ExifInterface constructor.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • This worked well for my devices SDK 24+, since that is where the `ExifInterface` constructor that takes the `InputStream` was added. `saveImage()` is indeed a custom function that simply writes the images to internal storage and returns the path for my database. My main issue then seems to be accessing the original content for the `ExifInterface` for devices lower than 24. Can I do that with a different API and the URI, or so I need to take a different approach? The lowest level constructor takes a file name as a `String`, but I guess I am a little confused as to how that differs from the URI. – BFrisch Jul 16 '17 at 22:18
  • @BFrisch: "This worked well for my devices SDK 24+, since that is where the ExifInterface constructor that takes the InputStream was added." -- it is also in the one from the support library, which is what I linked to. – CommonsWare Jul 16 '17 at 23:50
  • I understand now. I didn't realize that I had to link to the support library in my Gradle file. [This](https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html?m=1) blog post was helpful once I understood the support library was something separate. Thank you. – BFrisch Jul 17 '17 at 22:04