以前工作開發的app因為歷史原因,targetSdkVersion一直停留在21,即android 5.0。而compileSdkVersion則偶有升級,目前停留在23.0.1。最近有機會從0開始搭建一個嶄新的app,根據android的建議,complieSdkVersion和targetSdkVersion采用了最新的版本25。開發中較多代碼從上個app移植,但出現了一些新的問題。
6.0動態權限問題
app中包含從圖庫選取圖片視頻及拍照的工作,6.0以上手機測試時出現了crash。根據日志信息,提示缺少READ_EXTERNAL_STORAGE權限。
//Manifest中明確申請了該權限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
該問題出現的原因是6.0 (API 23) 之前,應用的權限在安裝時全部授予,運行時不再詢問用戶;在6.0 或更高版本對權限進行了分類,對某些涉及到用戶隱私的權限可在運行時根據用戶的需要動態授予。
android系統將權限分為幾個等級,如正常權限和危險權限。其中危險權限如下,需要在運行時動態申請。
解決方法是訪問圖庫、拍照前,動態申請權限。代碼如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
|| this.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
|| this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions( new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},100);
} else {
//加載media
}
} else {
//加載media
}
7.0拍照問題
測試中發現,7.0手機點擊拍照crash。出錯的拍照代碼如下:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String fCapturePicture = new File(getExternalCacheDir(), PICTURE_NAME + System.currentTimeMillis() + ".jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(fCapturePicture));
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, REQUEST_CODE_CAPTURE_PICTURE);
根據出錯日志,拍照時出現FileUriExposedException異常。
問題原因:安卓為了提高私有文件的安全性,在targetSdk版本為N或者以后版本的app中,其私有目錄將會限制訪問。
第一種解決方法,使用ContentProvider方式傳遞uri:
ContentValues contentValues = new ContentValues(1);
contentValues.put(MediaStore.Images.Media.DATA, fCapturePicture.getAbsolutePath());
Uri uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
第二種解決方法,使用FileProvider解決:
具體可參考http://www.lxweimin.com/p/68a4e8132fcd
總結
同樣的代碼,不同的targetSdkVersion會導致不同的行為結果。采用高版本的最新的targetSdk,才可以體驗到安卓系統最新的設計和行為。建議complileSdkVersion、targetSdkVersion都保持為最新版本