面试题:
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页面提前加载