day 10-11 面試題:Android6.0-Android 7.0適配

面試題:

1. Android 6.0適配     
2. Android 7.0適配

1. Android 6.0適配

1.1 HttpClient不支持問題

在Android 6.0以上,HttpClient被google從系統庫中移除,有兩種方式可以處理

  1. module下的gradle文件中的添加聲明

    useLibrary ‘org.apache.http.legacy’

  2. 添加HttpClient依賴

    1. 百度搜索 maven,找一個maven庫
    2. 搜索HttpClient,找到apache的HttpClient庫
    3. 下載jar或者引入依賴即可

1.2 動態權限申請

targetSdkVersion 改爲23及以上之後,所有需要手動授予的權限如果不申請,會閃退。

  1. 目前國內安卓綠色聯盟要求必須把targetSdkVersion提高到26,否則不予上架,所以,把targetSdkVersion限制在23以下的方案已廢棄。

  2. 適配動態權限

    自己對該功能進行封裝一下,方便調用。

    1. 判斷是否是Android 6.0以上

       Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
      
    2. 判斷是否具有對應的權限

       context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED
      
    3. 如果沒有權限,調用權限申請方法去申請

       activity.requestPermissions(permissions, requestCode)
      
    4. 在Activity的onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)方法中對操作結果進行判斷,如果通過則繼續執行原有邏輯,如果沒有則彈框提示明確信息讓用戶去設置界面手動授予。

2. Android 7.0適配

2.1 使用FileProvider進行應用間共享文件

不做FileProvider適配的話,在拍照、apk安裝等場景下,因爲調用了file://格式的Uri讀取文件,會拋出FileUriExposedException.

適配步驟:

  1. 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>
    
  2. 編寫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>
    
  3. 添加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;
     }
    
  4. 調用處修改爲封裝的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));
}

解決方案:

  1. 修改js方案爲jsbridge方式,複用window.prompt(有心的話可以百度搜索一下,使用還是很方便的)
  2. 將原來需要在客戶端注入的js邏輯抽出來,讓h5頁面提前加載
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章