你需要知道的Android拍照適配方案

轉(zhuǎn)載自http://blog.coderclock.com/2016/05/22/android/你需要知道的Android拍照適配問(wèn)題

說(shuō)起調(diào)用系統(tǒng)相機(jī)來(lái)拍照的功能石蔗,大家肯定不陌生厅翔,現(xiàn)在所有應(yīng)用都具備這個(gè)功能槐秧。例如最基本的,用戶拍照上傳頭像。Android開(kāi)發(fā)的孩紙都知道,碎片化給拍照這個(gè)功能的實(shí)現(xiàn)帶來(lái)挺多頭疼的問(wèn)題。所以顺囊,我決定寫(xiě)寫(xiě)一些網(wǎng)上不多見(jiàn)但又經(jīng)常聽(tīng)到童鞋們吐槽的問(wèn)題


拍照功能實(shí)現(xiàn)

Android 程序上實(shí)現(xiàn)拍照功能的方式分為兩種:第一種是利用相機(jī)的 API 來(lái)自定義相機(jī)蕉拢,第二種是利用 Intent 調(diào)用系統(tǒng)指定的相機(jī)拍照特碳。下面講的內(nèi)容都是針對(duì)第二種實(shí)現(xiàn)方式的適配。

通常情況下晕换,我們調(diào)用拍照的業(yè)務(wù)場(chǎng)景是如下面這樣的:

1.A 界面午乓,點(diǎn)擊按鈕調(diào)用相機(jī)拍照;
2.A 界面得到拍完照片届巩,跳轉(zhuǎn)到 B 界面進(jìn)行預(yù)覽硅瞧;
3.B 界面有個(gè)按鈕,點(diǎn)擊后觸發(fā)某個(gè)業(yè)務(wù)流程來(lái)處理這張照片恕汇;

實(shí)現(xiàn)的大體流程代碼如下:

  //1腕唧、調(diào)用相機(jī)
  File mPhotoFile = new File(folder,filename);
  Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  Uri fileUri = Uri.fromFile(mPhotoFile);
  captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
  mActivity.startActivityForResult(captureIntent, CAPTURE_PHOTO_REQUEST_CODE);
  //2、拿到照片
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      if (requestCode == CapturePhotoHelper.CAPTURE_PHOTO_REQUEST_CODE && resultCode == RESULT_OK) {
          File photoFile = mCapturePhotoHelper.getPhoto();//獲取拍完的照片
          if (photoFile != null) {
              PhotoPreviewActivity.preview(this, photoFile);//跳轉(zhuǎn)到預(yù)覽界面
          }
          finish();
      } else {
          super.onActivityResult(requestCode, resultCode, data);
      }
  }
  //3瘾英、各種各樣處理這張圖片的業(yè)務(wù)代碼

到這里基本科普完了如何調(diào)用系統(tǒng)相機(jī)拍照枣接,相信這些網(wǎng)上一搜一大把的代碼,很多童鞋都能看懂缺谴。


有沒(méi)有相機(jī)可用但惶?

前面講到我們是調(diào)用系統(tǒng)指定的相機(jī)app來(lái)拍照,那么系統(tǒng)是否存在可以被我們調(diào)用的app呢?這個(gè)我們不敢確定膀曾,畢竟 Android 奇葩問(wèn)題多县爬,還真有遇到過(guò)這種極端的情況導(dǎo)致閃退的添谊。雖然很極端,但作為客戶端人員還是要進(jìn)行處理耳高,方式有二:

1.調(diào)用相機(jī)時(shí),簡(jiǎn)單粗暴的 try-catch
2.調(diào)用相機(jī)前所踊,檢測(cè)系統(tǒng)有沒(méi)有相機(jī) app 可用

try-catch 這種粗暴的方式大家肯定很熟悉了,那么要如何檢測(cè)系統(tǒng)有沒(méi)有相機(jī) app 可用呢秕岛?系統(tǒng)在 PackageManager 里為我們提供這樣一個(gè) API

通過(guò)這樣一個(gè) API ,可以知道系統(tǒng)是否存在 actionMediaStore.ACTION_IMAGE_CAPTUREintent 可以喚起的拍照界面瓣蛀,具體實(shí)現(xiàn)代碼如下:

  /**
   * 判斷系統(tǒng)中是否存在可以啟動(dòng)的相機(jī)應(yīng)用
   *
   * @return 存在返回true陆蟆,不存在返回false
   */
  public boolean hasCamera() {
      PackageManager packageManager = mActivity.getPackageManager();
      Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
      List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
      return list.size() > 0;
  }

拍出來(lái)的照片“歪了”M镌觥8啮辍!

經(jīng)常會(huì)遇到一種情況像棘,拍照時(shí)看到照片是正的,但是當(dāng)我們的 app 獲取到這張照片時(shí)截歉,卻發(fā)現(xiàn)旋轉(zhuǎn)了 90 度(也有可能是180烟零、270,不過(guò)90度比較多見(jiàn)锨阿,貌似都是由于手機(jī)傳感器導(dǎo)致的)。很多童鞋對(duì)此感到很困擾壳嚎,因?yàn)椴皇撬惺謾C(jī)都會(huì)出現(xiàn)這種情況,就算會(huì)是出現(xiàn)這種情況的手機(jī)上烟馅,也并非每次必現(xiàn)。要怎么解決這個(gè)問(wèn)題呢口渔?從解決的思路上看穿撮,只要獲取到照片旋轉(zhuǎn)的角度,利用 Matrix 來(lái)進(jìn)行角度糾正即可攻礼。那么問(wèn)題來(lái)了,要怎么知道照片旋轉(zhuǎn)的角度呢礁扮?細(xì)心的童鞋可能會(huì)發(fā)現(xiàn)瞬沦,拍完一張照片去到相冊(cè)點(diǎn)擊屬性查看,能看到下面這樣一堆關(guān)于照片的屬性數(shù)據(jù)


沒(méi)錯(cuò)僚焦,這里面就有一個(gè)旋轉(zhuǎn)角度曙痘,倘若拍照后保存的成像照片文件發(fā)生了角度旋轉(zhuǎn)芳悲,這個(gè)圖片的屬性參數(shù)就能告訴我們到底旋轉(zhuǎn)了多少度边坤。只要獲取到這個(gè)角度值茧痒,我們就能進(jìn)行糾正的工作了。 Android 系統(tǒng)提供了 ExifInterface 類來(lái)滿足獲取圖片各個(gè)屬性的操作

通過(guò) ExifInterface 類拿到 TAG_ORIENTATION 屬性對(duì)應(yīng)的值旺订,即為我們想要得到旋轉(zhuǎn)角度。再根據(jù)利用 Matrix 進(jìn)行旋轉(zhuǎn)糾正即可耸峭。實(shí)現(xiàn)代碼大致如下:
/**
* 獲取圖片的旋轉(zhuǎn)角度
*
* @param path 圖片絕對(duì)路徑
* @return 圖片的旋轉(zhuǎn)角度
/
public static int getBitmapDegree(String path) {
int degree = 0;
try {
// 從指定路徑下讀取圖片桩蓉,并獲取其EXIF信息
ExifInterface exifInterface = new ExifInterface(path);
// 獲取圖片的旋轉(zhuǎn)信息
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
/
*
* 將圖片按照指定的角度進(jìn)行旋轉(zhuǎn)
*
* @param bitmap 需要旋轉(zhuǎn)的圖片
* @param degree 指定的旋轉(zhuǎn)角度
* @return 旋轉(zhuǎn)后的圖片
*/
public static Bitmap rotateBitmapByDegree(Bitmap bitmap, int degree) {
// 根據(jù)旋轉(zhuǎn)角度,生成旋轉(zhuǎn)矩陣
Matrix matrix = new Matrix();
matrix.postRotate(degree);
// 將原始圖片按照旋轉(zhuǎn)矩陣進(jìn)行旋轉(zhuǎn)劳闹,并得到新的圖片
Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
}
return newBitmap;
}

ExifInterface 能拿到的信息遠(yuǎn)遠(yuǎn)不止旋轉(zhuǎn)角度,其他的參數(shù)感興趣的童鞋可以看看 API 文檔业汰。


拍完照怎么閃退了样漆?

曾在小米和魅族的某些機(jī)型上遇到過(guò)這樣的問(wèn)題,調(diào)用系統(tǒng)相機(jī)拍照放祟,拍完點(diǎn)擊確定回到自己的app里面卻莫名奇妙的閃退了跪妥。這種閃退有兩個(gè)特點(diǎn):

1.沒(méi)有什么錯(cuò)誤日志(有些機(jī)子啥日志都沒(méi)有,有些機(jī)子會(huì)出來(lái)個(gè)空異常錯(cuò)誤日志)侦香;
2.同個(gè)機(jī)子上非必現(xiàn)(有時(shí)候怎么拍都不閃退纽疟,有時(shí)候一拍就閃退);

對(duì)待非必現(xiàn)問(wèn)題往往比較頭疼散吵,當(dāng)初遇到這樣的問(wèn)題也是非常不解膘壶。上網(wǎng)搜羅了一圈也沒(méi)方案,后來(lái)留意到一個(gè)比較有意思信息:有些系統(tǒng)廠商的 ROM 會(huì)給自帶相機(jī)應(yīng)用做優(yōu)化,當(dāng)某個(gè) app 通過(guò) intent 進(jìn)入相機(jī)拍照界面時(shí)柬赐,系統(tǒng)會(huì)把這個(gè) app 當(dāng)前最上層的 Activity 銷毀回收肛宋。(注意:我遇到的情況是有時(shí)候很快就回收掉,有時(shí)候怎么等也不回收床玻,沒(méi)有什么必現(xiàn)規(guī)律)為了驗(yàn)證一下沉帮,便在啟動(dòng)相機(jī)的 Activity 中對(duì) onDestory 方法進(jìn)行加 log 贫堰。果不其然待牵,終于發(fā)現(xiàn)進(jìn)入拍照界面的時(shí)候 onDestory 方法被執(zhí)行了。所以偎行,前面提到的閃退基本可以推測(cè)是 Activity 被回收導(dǎo)致某些非UI控件的成員變量為空導(dǎo)致的贰拿。(有些機(jī)子會(huì)報(bào)出空異常錯(cuò)誤日志膨更,但是有些機(jī)子閃退了什么都不報(bào),是不是覺(jué)得很奇葩Q弧)

既然涉及到 Activity 被回收的問(wèn)題健蕊,自然要想起 onSaveInstanceStateonRestoreInstanceState 這對(duì)方法。去到 onSaveInstanceState 把數(shù)據(jù)保存晴及,并在 onRestoreInstanceState 方法中進(jìn)行恢復(fù)即可嫡锌。大體代碼思路如下:

  @Override
  protected void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
      mRestorePhotoFile = mCapturePhotoHelper.getPhoto();
      if (mRestorePhotoFile != null) {
          outState.putSerializable(EXTRA_RESTORE_PHOTO, mRestorePhotoFile);
      }
  }
  @Override
  protected void onRestoreInstanceState(Bundle savedInstanceState) {
      super.onRestoreInstanceState(savedInstanceState);
      mRestorePhotoFile = (File) savedInstanceState.getSerializable(EXTRA_RESTORE_PHOTO);
      mCapturePhotoHelper.setPhoto(mRestorePhotoFile);
  }

對(duì)于 onSaveInstanceStateonRestoreInstanceState 方法的作用還不熟悉的童鞋,網(wǎng)上資料很多蛛倦,可以自行搜索啦桌。

到這里甫男,可能有童鞋要問(wèn),這種閃退并不能保證復(fù)現(xiàn)板驳,我要怎么知道問(wèn)題所在和是否修復(fù)了呢若治?我們可以去到開(kāi)發(fā)者選項(xiàng)里開(kāi)啟不保留活動(dòng)這一項(xiàng)進(jìn)行調(diào)試驗(yàn)證


它作用是保留當(dāng)前和用戶接觸的 Activity 感混,并將目前無(wú)法和用戶交互 Activity 進(jìn)行銷毀回收菌仁。打開(kāi)這個(gè)調(diào)試選項(xiàng)就可以滿足驗(yàn)證的需求济丘,當(dāng)你的 app 的某個(gè) Activity 跳轉(zhuǎn)到拍照的 Activity 后谱秽,這個(gè) Activity 立馬就會(huì)被系統(tǒng)銷毀回收疟赊,這樣就可以很好的完全復(fù)現(xiàn)閃退的場(chǎng)景峡碉,幫助開(kāi)發(fā)者確認(rèn)問(wèn)題有沒(méi)有修復(fù)了。

涉及到 Activity 被銷毀吉执,還想提一下代碼實(shí)現(xiàn)上的問(wèn)題地来。假設(shè)當(dāng)前有兩個(gè) ActivityMainActivity 中有個(gè) Button 咕宿,點(diǎn)擊可以調(diào)用系統(tǒng)相機(jī)拍照并顯示到 PreviewActivity 進(jìn)行預(yù)覽蜡秽。有下面兩種實(shí)現(xiàn)方案:

● 方案一:MainActivity 中點(diǎn)擊 Button 后芽突,啟動(dòng)系統(tǒng)相機(jī)拍照,并在 MainActivityonActivityResult 方法中獲取拍下來(lái)的照片寞蚌,并啟動(dòng)跳轉(zhuǎn)到 PreviewActivity 界面進(jìn)行效果預(yù)覽睬澡;

● 方案二:MainActivity 中點(diǎn)擊 Button 后眠蚂,啟動(dòng) PreviewActivity 界面,在 PreviewActivityonCreate(或者onStart昔脯、onResume)方法中啟動(dòng)系統(tǒng)相機(jī)拍照,然后在 PreviewActivityonActivityResult 方法中獲取拍下來(lái)的照片進(jìn)行預(yù)覽隧饼;

上面兩種方案得到的實(shí)現(xiàn)效果是一模一樣的静陈,但是第二種方案卻存在很大的問(wèn)題。因?yàn)閱?dòng)相機(jī)的代碼放在 onCreate(或者onStart拐格、onResume)中刑赶,當(dāng)進(jìn)入拍照界面后撞叨,PreviewActivity 隨即被銷毀,拍完照確認(rèn)后回到 PreviewActivity 時(shí)牵敷,被銷毀的 PreviewActivity 需要重建劣领,又要走一遍 onCreateonStart奕锌、onResume村生,又調(diào)用了啟動(dòng)相機(jī)拍照的代碼,周而復(fù)始的進(jìn)入了死循環(huán)狀態(tài)辽话。為了避免讓你的用戶抓狂卫病,果斷明智的選擇方案一。

以上這種情況提到調(diào)用系統(tǒng)拍照時(shí)益咬,Activity就回收的情況帜平,在小米4S小米4 LTE機(jī)子上(MIUI的版本是7.3,Android系統(tǒng)版本是6.0)出現(xiàn)的概率很高冗锁。 所以,建議看到此文的童鞋也可以去驗(yàn)證適配一下箍邮。


圖片無(wú)法顯示

圖片無(wú)法顯示這個(gè)問(wèn)題也是略坑芋绸,如何坑法摔敛?往下看,同樣是在小米4S小米4 LTE機(jī)子上(MIUI的版本是7.3桃犬,Android系統(tǒng)版本是6.0)出現(xiàn)概率很高的場(chǎng)景(當(dāng)然行楞,不保證其他機(jī)子沒(méi)出現(xiàn)過(guò))。按照我們前面提到的業(yè)務(wù)場(chǎng)景形用,調(diào)用相機(jī)拍照完成后证杭,我們的 app 會(huì)有一個(gè)預(yù)覽圖片的界面。但是在用了小米的機(jī)子進(jìn)行拍照后镇饺,自己 app 的預(yù)覽界面卻怎么也無(wú)法顯示出照片來(lái)送讲,同樣是相當(dāng)郁悶哼鬓,郁悶完后還是要一步一步去排查解決問(wèn)題的!為此秸侣,需要一步一步猜測(cè)驗(yàn)證問(wèn)題所在。

● 猜測(cè)一:沒(méi)有拿到照片路徑味榛,所以無(wú)法顯示搏色?
直接斷點(diǎn)打 log 跟蹤券册,猜測(cè)一很快被推翻,路徑是有的航邢。

● 猜測(cè)二:Bitmap太大了骄蝇,無(wú)法顯示九火?
直接在 AS 的 log 控制臺(tái)仔細(xì)的觀察了一下系統(tǒng) log ,發(fā)現(xiàn)了一些蛛絲馬跡

  OpenGLRenderer: Bitmap too large to be uploaded into a texture

每次拍完照片勒极,都會(huì)出現(xiàn)上面這樣的 log 虑鼎,果然炫彩,因?yàn)閳D片太大而導(dǎo)致在 ImageView 上無(wú)法顯示。到這里有童鞋要吐槽了乐尊,沒(méi)對(duì)圖片的采樣率 inSampleSize 做處理划址?天地良心啊,絕對(duì)做處理了痢缎,直接看代碼:

  /**
   * 壓縮Bitmap的大小
   *
   * @param imagePath     圖片文件路徑
   * @param requestWidth  壓縮到想要的寬度
   * @param requestHeight 壓縮到想要的高度
   * @return
   */
  public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) {
      if (!TextUtils.isEmpty(imagePath)) {
          if (requestWidth <= 0 || requestHeight <= 0) {
              Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
              return bitmap;
          }
          BitmapFactory.Options options = new BitmapFactory.Options();
          options.inJustDecodeBounds = true;//不加載圖片到內(nèi)存世澜,僅獲得圖片寬高
          BitmapFactory.decodeFile(imagePath, options);
          options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //計(jì)算獲取新的采樣率
          options.inJustDecodeBounds = false;
          return BitmapFactory.decodeFile(imagePath, options);
      } else {
          return null;
      }
  }
  public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
      final int height = options.outHeight;
      final int width = options.outWidth;
      int inSampleSize = 1;
      Log.i(TAG, "height: " + height);
      Log.i(TAG, "width: " + width);
      if (height > reqHeight || width > reqWidth) {
          final int halfHeight = height / 2;
          final int halfWidth = width / 2;
          while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
              inSampleSize *= 2;
          }
          long totalPixels = width * height / inSampleSize;
          final long totalReqPixelsCap = reqWidth * reqHeight * 2;
          while (totalPixels > totalReqPixelsCap) {
              inSampleSize *= 2;
              totalPixels /= 2;
          }
      }
      return inSampleSize;
  }

瞄了代碼后,是不是覺(jué)得沒(méi)有問(wèn)題了案疲?沒(méi)錯(cuò)麻养,inSampleSize 確確實(shí)實(shí)經(jīng)過(guò)處理鳖昌,那為什么圖片還是太大而顯示不出來(lái)呢? requestWidth许昨、int requestHeight 設(shè)置得太大導(dǎo)致 inSampleSize 太小了糕档?不可能啊,我都試著把長(zhǎng)寬都設(shè)置成 100 了還是沒(méi)法顯示类垫!干脆琅坡,直接打印 inSampleSize 值,一打印售躁,inSampleSize 值居然為 1 茴晋。 我去诺擅,徹底打臉了,明明說(shuō)好的處理過(guò)了烁涌,居然還是 1 4橹础!r阉痢!為了一探究竟症概,干脆加 log 厉颤。

  public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) {
      if (!TextUtils.isEmpty(imagePath)) {
          Log.i(TAG, "requestWidth: " + requestWidth);
          Log.i(TAG, "requestHeight: " + requestHeight);
          if (requestWidth <= 0 || requestHeight <= 0) {
              Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
              return bitmap;
          }
          BitmapFactory.Options options = new BitmapFactory.Options();
          options.inJustDecodeBounds = true;//不加載圖片到內(nèi)存逼友,僅獲得圖片寬高
          BitmapFactory.decodeFile(imagePath, options);
          Log.i(TAG, "original height: " + options.outHeight);
          Log.i(TAG, "original width: " + options.outWidth);
          options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //計(jì)算獲取新的采樣率
          Log.i(TAG, "inSampleSize: " + options.inSampleSize);
          options.inJustDecodeBounds = false;
          return BitmapFactory.decodeFile(imagePath, options);
      } else {
          return null;
      }
  }

運(yùn)行打印出來(lái)的日志如下:


圖片原來(lái)的寬高居然都是 -1 秤涩,真是奇葩了筐眷!難怪,inSampleSize 經(jīng)過(guò)處理之后結(jié)果還是 1 照棋。狠狠的吐槽了之后武翎,總是要回來(lái)解決問(wèn)題的。那么符隙,圖片的寬高信息都丟失了垫毙,我去哪里找啊丽蝎? 像下面這樣膀藐?

  public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) {
         ...
         BitmapFactory.Options options = new BitmapFactory.Options();
         options.inJustDecodeBounds = true;//不加載圖片到內(nèi)存消请,僅獲得圖片寬高
         Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
         bitmap.getWidth();
         bitmap.getHeight();
         ...
      } else {
          return null;
     }
 }

no,此方案行不通蛉加,inJustDecodeBounds = true 時(shí),BitmapFactory 獲得 Bitmap 對(duì)象是 null厂抽;那要怎樣才能獲圖片的寬高呢丁眼?前面提到的 ExifInterface 再次幫了我們大忙,通過(guò)它的下面兩個(gè)屬性即可拿到圖片真正的寬高


順手吐槽一下藐守,為什么高不是 TAG_IMAGE_HEIGHT 而是 TAG_IMAGE_LENGTH卢厂。改良過(guò)后的代碼實(shí)現(xiàn)如下:

  public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) {
      if (!TextUtils.isEmpty(imagePath)) {
          Log.i(TAG, "requestWidth: " + requestWidth);
          Log.i(TAG, "requestHeight: " + requestHeight);
          if (requestWidth <= 0 || requestHeight <= 0) {
              Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
              return bitmap;
          }
          BitmapFactory.Options options = new BitmapFactory.Options();
          options.inJustDecodeBounds = true;//不加載圖片到內(nèi)存惠啄,僅獲得圖片寬高
          BitmapFactory.decodeFile(imagePath, options);
          Log.i(TAG, "original height: " + options.outHeight);
          Log.i(TAG, "original width: " + options.outWidth);
          if (options.outHeight == -1 || options.outWidth == -1) {
              try {
                  ExifInterface exifInterface = new ExifInterface(imagePath);
                  int height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, ExifInterface.ORIENTATION_NORMAL);//獲取圖片的高度
                  int width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, ExifInterface.ORIENTATION_NORMAL);//獲取圖片的寬度
                  Log.i(TAG, "exif height: " + height);
                  Log.i(TAG, "exif width: " + width);
                  options.outWidth = width;
                  options.outHeight = height;
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //計(jì)算獲取新的采樣率
          Log.i(TAG, "inSampleSize: " + options.inSampleSize);
          options.inJustDecodeBounds = false;
          return BitmapFactory.decodeFile(imagePath, options);
      } else {
          return null;
      }
  }

再看一下撵渡,打印出來(lái)的log



這樣就可以解決問(wèn)題啦趋距。


總結(jié)

以上總結(jié)了這么些身邊童鞋經(jīng)常問(wèn)起,但網(wǎng)上又不多見(jiàn)的適配問(wèn)題靠欢,希望可以幫到一些開(kāi)發(fā)童鞋少走彎路铜跑。文中多次提到小米的機(jī)子锅纺,并不代表只有MIUI上有這樣的問(wèn)題存在,僅僅只是因?yàn)槲疑磉厧У膸撞繖C(jī)子大都是小米的坦弟。對(duì)待適配問(wèn)題官地,在搜索引擎都無(wú)法提供多少有效的信息時(shí),我們只能靠斷點(diǎn)赤炒、打log、觀察控制臺(tái)的日志掩缓、以及API文檔來(lái)尋找一些蛛絲馬跡作為突破口遵岩,相信辦法總比困難多。

以上的示例代碼已經(jīng)整理到:https://github.com/D-clock/AndroidStudyCode 舍哄,主要的代碼在下面紅圈部分

感興趣的童鞋可以自行查看蠢熄!如有錯(cuò)誤炉旷,歡迎大家指正叉讥!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末图仓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子惶看,更是在濱河造成了極大的恐慌六孵,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件本今,死亡現(xiàn)場(chǎng)離奇詭異冠息,居然都是意外死亡孕索,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門散怖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)杭抠,“玉大人,你說(shuō)我怎么就攤上這事丹诀∥檀梗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵枚荣,是天一觀的道長(zhǎng)橄妆。 經(jīng)常有香客問(wèn)我祈坠,道長(zhǎng),這世上最難降的妖魔是什么慌随? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任躺同,我火速辦了婚禮蹋艺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘笛园。我一直安慰自己侍芝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布棵红。 她就那樣靜靜地躺著咧栗,像睡著了一般逆甜。 火紅的嫁衣襯著肌膚如雪虱肄。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天交煞,我揣著相機(jī)與錄音咏窿,去河邊找鬼。 笑死素征,一個(gè)胖子當(dāng)著我的面吹牛集嵌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播根欧,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼端蛆!你這毒婦竟也來(lái)了凤粗?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤今豆,失蹤者是張志新(化名)和其女友劉穎嫌拣,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體呆躲,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亭罪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了歼秽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡情组,死狀恐怖燥筷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情院崇,我是刑警寧澤肆氓,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站底瓣,受9級(jí)特大地震影響谢揪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捐凭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一拨扶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茁肠,春花似錦患民、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)仅孩。三九已至,卻和暖如春印蓖,著一層夾襖步出監(jiān)牢的瞬間辽慕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工赦肃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溅蛉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓摆尝,卻偏偏與公主長(zhǎng)得像温艇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子堕汞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容