本文基于OKGO3.0.4版本编写
首先导入依赖
implementation 'com.lzy.net:okgo:3.0.4'
一.okgo跳过https验证
1.导入自定义SSLSocketClient类
public class SSLSocketClient {
//获取这个SSLSocketFactory
public static SSLSocketFactory getSSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, getTrustManager(), new SecureRandom());
return sslContext.getSocketFactory();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//获取TrustManager
private static TrustManager[] getTrustManager() {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
return trustAllCerts;
}
//获取HostnameVerifier
public static HostnameVerifier getHostnameVerifier() {
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
};
return hostnameVerifier;
}
}
2.在Application里配置
OkHttpClient build = new OkHttpClient.Builder()
.sslSocketFactory(SSLSocketClient.getSSLSocketFactory())
.hostnameVerifier(SSLSocketClient.getHostnameVerifier())
.build();
//初始化okgo并配置给httpclient
OkGo.getInstance().init(this).setOkHttpClient(build);
至此https配置完毕了就
接下来就去请求文件吧
二:OKGO下载文件(本文下载的是一个apk文件)
final String destfiledir = Environment.getExternalStorageDirectory().getPath() + "/OAdownload";//下载路径
final String destfilename = "OA.apk";//文件名
OkGo
.tag("Download tips")//添加标记 用于取消单个请求 取消: OkGo.getInstance().cancelTag("Download tips");
.<File>get("http://immobile.r93535.com:8086/LN/GetExtApp/extapp/ExtApp/A/1111/LatestVersion")
.execute(new FileCallback(destfiledir, destfilename) {
@Override
public void onStart(Request<File, ? extends Request> request) {
super.onStart(request);
Log.e("gogogo", "正在加载中");
}
@Override
public void downloadProgress(Progress progress) {
super.downloadProgress(progress);
long totalSize = progress.totalSize;//总长度
long currentSize = progress.currentSize;//本次下载的大小
//进度条
progressBar.setMax((int) totalSize);
progressBar.setProgress((int) currentSize);
textView.setText(String.valueOf(progress.fraction * 100 + "%")); //下载进度
}
@Override
public void onError(Response<File> response) {
super.onError(response);
Log.e("gogogo", "下载出错");
}
@Override
public void onSuccess(Response<File> response) {
Log.e("gogogo", "下载成功");
// 安装apk
install(destfiledir + destfilename);
}
@Override
public void onFinish() {
super.onFinish();
Log.e("gogogo", "结束");
}
});
三:安装apk
开始安装apk:
File apkFile = new File(filePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
startActivity(intent);
注意:在android 7.0之前这样写没有一点瑕疵,但是随着Android 7.0的到来引入“私有目录被限制访问”,“StrictMode API 政策”,为了进一步提高私有文件的安全性,Android不再由开发者放宽私有文件的访问权限,之前我们一直使用”file:///”绝对路径来传递文件地址的方式,在接收方访问时很容易触发SecurityException的异常。
因此,为了更好的适配Android 7.0,例如相机拍照这类涉及到文件地址传递的地方就用上了FileProvider,FileProvider也更好地进入了大家的视野。
不多bb,看代码!
1.首先在manifest里面配置provider(跟activity同级)
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="你的包名.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
2.在res文件下建立xml文件夹然后建立file_paths文件
<resources>
<paths>
<external-path
name="OA.apk"
path="/OAdownload" />
</paths>
</resources>
path就是文件路径,那么是文件名字 然后external-path就相当于Environment.getExternalStorageDirectory() 。
别的路径可以参考下图:
files-path | Context.getFilesDir() |
cache-path | Context.getCacheDir() |
external-path | Environment.getExternalStorageDirectory() |
external-files-path | Context.getExternalFilesDir(null) |
external-cache-path | Context.getExternalCacheDir() |
3.开始安装
private void install(String filePath) {
Log.i("file", "开始执行安装: " + filePath);
File apkFile = new File(filePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Log.w("file", "版本大于 N ,开始使用 fileProvider 进行安装");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(
this
, "com.example.duqianlong.okdownladdemo.fileprovider"
, apkFile);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
Log.w("file", "正常进行安装");
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
}
startActivity(intent);
}
至此差不多就大功告成了,当然权限是少不了的
4.添加权限(因为不是危险权限,所以不需要动态申请,添加到manifest里面就行)
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
读写权限&网络权限 是少不了的,当然这个就需要动态申请了,这个可以参考以前的博客
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
自此全部完毕大功告成,可以测试啦!
由于动态图太大传不上来,同学们可以去Github下载下来自己测试