面試題:
1. Android 6.0適配
2. Android 7.0適配
1. Android 6.0適配
1.1 HttpClient不支持問題
在Android 6.0以上,HttpClient被google從系統庫中移除,有兩種方式可以處理
-
module下的gradle文件中的添加聲明
useLibrary ‘org.apache.http.legacy’
-
添加HttpClient依賴
- 百度搜索
maven
,找一個maven庫 - 搜索HttpClient,找到apache的HttpClient庫
- 下載jar或者引入依賴即可
- 百度搜索
1.2 動態權限申請
targetSdkVersion 改爲23及以上之後,所有需要手動授予的權限如果不申請,會閃退。
-
目前國內安卓綠色聯盟要求必須把targetSdkVersion提高到26,否則不予上架,所以,把targetSdkVersion限制在23以下的方案已廢棄。
-
適配動態權限
自己對該功能進行封裝一下,方便調用。
-
判斷是否是Android 6.0以上
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
-
判斷是否具有對應的權限
context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED
-
如果沒有權限,調用權限申請方法去申請
activity.requestPermissions(permissions, requestCode)
-
在Activity的
onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
方法中對操作結果進行判斷,如果通過則繼續執行原有邏輯,如果沒有則彈框提示明確信息讓用戶去設置界面手動授予。
-
2. Android 7.0適配
2.1 使用FileProvider進行應用間共享文件
不做FileProvider適配的話,在拍照、apk安裝等場景下,因爲調用了file://格式的Uri讀取文件,會拋出FileUriExposedException.
適配步驟:
-
在
AndroidManifest.xml
文件中聲明provider<!--FileProvider的支持--> <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.android7.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
-
編寫file_paths.xml文件,例子中放在xml文件夾下
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- <root-path/> 代表設備的根目錄new File("/"); <files-path/> 代表context.getFilesDir() <cache-path/> 代表context.getCacheDir() <external-path/> 代表Environment.getExternalStorageDirectory() <external-files-path>代表context.getExternalFilesDirs() <external-cache-path>代表getExternalCacheDirs() --> <root-path name="root" path=""/> <files-path name="files" path="file" /> <cache-path name="cache" path="cache" /> <external-path name="external" path="SD" /> <external-files-path name="name" path="SD_file" /> <external-cache-path name="name" path="SD_cache" /> </paths>
-
添加Utils方法,適配Uri的獲取
public static Uri getUriForFile(Context context, File file) { Uri fileUri = null; if (Build.VERSION.SDK_INT >= 24) { fileUri = getUriForFile24(context, file); } else { fileUri = Uri.fromFile(file); } return fileUri; } public static Uri getUriForFile24(Context context, File file) { Uri fileUri = android.support.v4.content.FileProvider.getUriForFile(context, context.getPackageName() + ".android7.fileprovider", file); return fileUri; }
-
調用處修改爲封裝的Utils方法
getUriForFile(context, file)
2.2 APK signature schema v2
無網環境下寫的文檔,所以不附圖了
在打Release包時:工具欄 Build -> Generate Signed APK ->輸入密碼 ->Signature Versions。
此處選項V!和V2都要選上
只勾選V2,7.0以下會顯示未安裝,7.0以上會使用V2的安全驗證方式。
2.3 拒絕webview注入
我的項目以前的js注入是,註冊了js後又注入了一段js腳本,在targetSdkVersion升級到25以後,完全失效。
原代碼:
private void initGPS() {
mJsGPS = new JsGPS(mWebView);
mWebView.addJavascriptInterface(mJsGPS, "EMPGeolocation");
registerGPS();
}
private void registerGPS() {
// 嵌套一層方法,防止傳來的回調函數不是字符串
String gpsJStr = "function Geolocation(){};".concat("Geolocation.prototype.getCurrentLocation = function(callback, accuracy)").concat("{")
.concat(" EMPGeolocation.getCurrentLocation(getFuncName(callback), accuracy);").concat("};").concat("var geolocation = new Geolocation();");
mWebView.loadUrl("javascript:".concat(gpsJStr));
}
解決方案:
- 修改js方案爲jsbridge方式,複用window.prompt(有心的話可以百度搜索一下,使用還是很方便的)
- 將原來需要在客戶端注入的js邏輯抽出來,讓h5頁面提前加載