2017-07-15 94 views
0

我正在開發Android應用程序,其中部分功能是用戶可以從其設備中選擇圖像,將其與列表中的特定項目相關聯,以及在應用程序中使用它。我的意圖是將圖像本身存儲在內部存儲器中,以及SQLite數據庫中圖像的路徑以及該項目的其餘存儲信息。
我已經能夠讓用戶選擇並且上傳圖片,但是圖片有時會根據圖片的拍攝情況進行旋轉。我試過看Exif數據,但方向始終爲零。我試過用光標作爲MediaStore.Images.Media.DATA的信息,但也無濟於事。相關的代碼的當前狀態如下:Android用戶上傳的圖像在ImageView中以假Exif數據旋轉

@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(); 
} 

下面是相關佈局文件:

<?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> 

這允許用戶選擇一個圖像,將其上傳到圖像視圖(有時旋轉),存儲圖像,並在關閉應用程序後檢索圖像。輪換是唯一的主要問題,我所嘗試的修復並未體現在這裏。我在這裏引用了太多的答案,但它們分爲三大類:檢查Exif標籤並用矩陣旋轉位圖,使用光標獲取圖像信息並旋轉,然後使用Glide。三人都失敗了,我不知道下一步該做什麼。有什麼建議麼?

完整的代碼可以在here找到。

UPDATE
按照要求,我已經added將Exif檢查代碼無濟於事。如前所述,方向始終爲零,因此我會根據鏈接中的代碼獲取空位圖。

+0

「有什麼建議嗎?」 - 問一個問題,你在哪裏顯示你的「修復[你]已經嘗試過」並尋求幫助,提供什麼不起作用的具體細節。我們無法幫助您處理我們無法看到的代碼。你在這裏的代碼肯定不起作用,因爲它不會旋轉圖像。 FWIW,[這個示例應用程序](https://github.com/commonsguy/cw-omnibus/tree/v8.6/Camera/EXIFRotater)演示了「檢查Exif標籤並旋轉位圖矩陣」解決方案,以及旋轉'ImageView'。 – CommonsWare

+0

請參閱[鏈接](https://stackoverflow.com/questions/14066038/why-does-an-image-captured-using-camera-intent-gets-rotated-on-some-devices-on-a) – santalu

+0

@ CommonsWare我已經添加了我之前嘗試過的代碼,並根據santalu的鏈接進行了一些小改動。我已經用結果更新了我的問題。 – BFrisch

回答

0

我不知道saveImage()做什麼。鑑於它需要在Bitmap並返回一個「路徑」,我假定它將Bitmap保存到一個文件。如果是這樣,那肯定不行,因爲Bitmap沒有EXIF數據。

使用the support library's edition of ExifInterface的原始內容中讀取EXIF標記。使用getContentResolver().openInputStream(imageUri)可獲得InputStream,將其傳遞給ExifInterface構造函數。

+0

這適用於我的設備SDK 24+,因爲這是添加了'InputStream'的'ExifInterface'構造函數的地方。 'saveImage()'確實是一個自定義函數,它只是將圖像寫入內部存儲並返回數據庫的路徑。然後,我的主要問題似乎是訪問低於24的設備的'ExifInterface'的原始內容。我可以用不同的API和URI來做到這一點,或者我需要採取不同的方法嗎?最低級別的構造函數將一個文件名作爲'String',但我想我對這與URI有何不同有點困惑。 – BFrisch

+0

@BFrisch:「這適用於我的設備SDK 24+,因爲那是添加了InputStream的ExifInterface構造函數的地方。」 - 它也在支持庫中,這是我鏈接到的。 – CommonsWare

+0

我現在明白了。我沒有意識到我必須鏈接到我的Gradle文件中的支持庫。一旦我明白支持庫是獨立的,[https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html?m=1)博客文章是有幫助的。謝謝。 – BFrisch