先看效果:
实现步骤:
1、 传入apk链接,下载apk文件
2、 画个View展示交互效果
3、 主动提示安装
1:根据链接,去下载apk文件:
首先引库PRDownloader
implementation 'com.mindorks.android:prdownloader:0.5.0'
下载部分代码
String url="http://artist2020.oss-cn-beijing.aliyuncs.com/........../ygApp.apk";//网络地址
String name= VolleyUtils.getRandomString(5)+ "ygApp.apk";//本地存此APK要定义一个名字
final String dirPath = getFilesDir().getPath() + "/" + "volley";
File file = new File(dirPath);
if (!file.exists()) {
file.mkdirs();
}
PRDownloader.download(url, dirPath, name)
.build()
.setOnProgressListener(new OnProgressListener() {
@Override
public void onProgress(Progress progress) {
float a=(float) progress.currentBytes/(float) progress.totalBytes;
//正在下载中,显示进度 a%
}
})
.start(new OnDownloadListener() {
@Override
public void onDownloadComplete() {
//下载成功,开始安装APK文件
//最下面有installApp方法
ProUtils.installApp(Welcome.this,dirPath+"/"+name);
}
@Override
public void onError(Error error) {
//下载失败后的操作
}
});
2:展示进度的View:
可以把这个view放在dialog里,暴露出方法
这样直接就可以通过dialog去控制进度显示
进度View代码
最下面3个方法,去控制view的UI显示
public class CircleProgressView extends View {
private boolean isAysning=false;
private float progress=0f;
private Paint paintCircle=null;
private Paint paintBack=null;
private Paint paintText=null;
private int width=0;
private int textSize=0;
private RectF rectF=null;
private LinearGradient linearGradient;
public CircleProgressView(Context context) {
this(context, null);
}
public CircleProgressView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
width=BaseObserver.getInstance().getPXformDP(7);
paintCircle=new Paint();
paintCircle.setStrokeWidth(width);
paintCircle.setColor(0xff313131);
paintCircle.setAntiAlias(true);
paintCircle.setStrokeCap(Paint.Cap.ROUND);
paintCircle.setStyle(Paint.Style.STROKE);
paintBack=new Paint();
paintBack.setStrokeWidth(width);
paintBack.setColor(0xfff2cd30);
paintBack.setAntiAlias(true);
paintBack.setStrokeCap(Paint.Cap.ROUND);
paintBack.setStyle(Paint.Style.FILL);
paintBack.setShadowLayer(10,0, 0, Color.BLACK);
paintText=new Paint();
paintText.setColor(0xff313131);
paintCircle.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(rectF==null){
rectF=new RectF(0+width,0+width,getWidth()-width,getHeight()-width);
}
canvas.drawArc(rectF,-90,360,false,paintBack);
float f=progress*360f;
canvas.drawArc(rectF,-90,(int)f,false,paintCircle);
String pro;
if(isAysning){
pro=(int)(100f*(progress))+"%";
}else {
pro="更新";
}
if(textSize==0){
textSize=getHeight()/4;
paintText.setTextSize(textSize);
}
float textWidth = paintText.measureText(pro);
Paint.FontMetrics fontMetrics = paintText.getFontMetrics();
float y = getHeight()/2 + (Math.abs(fontMetrics.ascent) - fontMetrics.descent)/2;
canvas.drawText(pro, (getWidth()-textWidth)/2,y,paintText);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMySize(500, widthMeasureSpec);
int height = getMySize(500, heightMeasureSpec);
//设置成正方形
if (width < height) {
height = width;
} else {
width = height;
}
setMeasuredDimension(width, height);
}
private int getMySize(int defaultSize, int measureSpec) {
int mySize = defaultSize;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
switch (mode) {
case MeasureSpec.EXACTLY: {
mySize = size;
break;
}
case MeasureSpec.UNSPECIFIED: {
mySize = defaultSize;
break;
}
case MeasureSpec.AT_MOST: {
mySize = size;
break;
}
}
return mySize;
}
public void begin(){
if(!isAysning){
isAysning=true;
}
invalidate();
}
public void progress(float f){
isAysning=true;
this.progress=f;
invalidate();
}
public void clear(){
isAysning=false;
progress=0f;
invalidate();
}
}
3:主动去安装APK文件:
这个就不说了,网上有很多类似的代码,我整理了下
目前没有遇见安卓版本的bug
可大胆的用
String appFilePro="com.androeda.xx.xxx";//你的包名
public static void installApp(Context context,String path){
if(context==null){
return;
}
File file = new File(path);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if(Build.VERSION.SDK_INT>=24) { //Android 7.0及以上
// 参数2 清单文件中provider节点里面的authorities ; 参数3 共享的文件,即apk包的file类
Uri apkUri = FileProvider.getUriForFile(context, appFilePro, file);
//对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
}else{
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
}
context.startActivity(intent);
}
在manifest的application节点中添加
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="......上面的appFilePro 要一致"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
在res中新建file_path文件
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="root" path="" />
<files-path name="files" path="." />
<cache-path name="cache" path="." />
<external-path name="external" path="." />
<external-files-path name="name" path="." />
<external-cache-path name="name" path="." />
</paths>
写在最后:
同是天涯打工人,相逢何必论高下。
红颜何处真知己,人生无聊才编程。