android 下载apk,并安装

1、首先我们设置Dialog的 布局文件,download_dialog.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textStyle="bold"
        android:textColor="@color/colorPrimary"
        android:text="版本更新"/>
 
    <ProgressBar
        android:id="@+id/mProgressBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        android:max="100"/>
 
    <TextView
        android:id="@+id/mTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:textStyle="bold"
        android:textSize="16sp"
        android:textColor="@color/colorPrimary"
        android:text="0%"/>
 
</LinearLayout>

2、

进度条显示下载进度,TextView显示下载百分比。

然后自定义一个AlertDialog,将布局文件设置进去,DownloadDialog.java :

public class DownloadDialog extends AlertDialog {
    private Context mContext;
    private TextView mTextView;
    private ProgressBar mProgressBar;
    private View view;
    protected DownloadDialog(Context context) {
        super(context);
        this.mContext = context;
 
    }
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //设置对话框样式
        setStyle();
        //初始化控件
        initView();
    }
 
    private void initView() {
        view = View.inflate(mContext,R.layout.dwonlaod_dialog,null);
        mTextView = (TextView)view.findViewById(R.id.mTextView);
        mProgressBar = (ProgressBar)view.findViewById(R.id.mProgressBar);
        setContentView(view);
    }
 
    private void setStyle() {
        //设置对话框不可取消
        this.setCancelable(false);
        //设置触摸对话框外面不可取消
        this.setCanceledOnTouchOutside(false);
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindow().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        //获得应用窗口大小
        WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes();
        //设置对话框居中显示
        layoutParams.gravity = Gravity.CENTER;
        //设置对话框宽度为屏幕的3/5
        layoutParams.width = (displaymetrics.widthPixels/5)*3;
    }
 
    //设置进度条
    public void setProgress(int progress){
        mTextView.setText(progress+"%");
        mProgressBar.setProgress(progress);
    }
}

3、创建显示对话框,取消对话框的方法,MainActivity :

private void showDialog() {
        if(downloadDialog==null){
            downloadDialog = new DownloadDialog(this);
        }
 
        if(!downloadDialog.isShowing()){
            downloadDialog.show();
        }
    }

4、创建一个download方法用于下载应用:

private void download() {
        showDialog();
        //最好是用单线程池,或者intentService
        new Thread(new DownLoadRunnable(this,url, handler)).start();
    }

5、DownloadRunnable中的具体处理方法:

public class DownLoadRunnable implements Runnable {
    private String url;
    private Handler handler;
    private Context mContext;
 
    public DownLoadRunnable(Context context, String url, Handler handler) {
        this.mContext = context;
        this.url = url;
        this.handler = handler;
    }
 
    @Override
    public void run() {
     //设置线程优先级为后台,这样当多个线程并发后很多无关紧要的线程分配的CPU时间将会减少,有利于主线程的处理   
     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
     //具体下载方法
        startDownload();
    }
 
    private long startDownload() {
        //获得DownloadManager对象
        DownloadManager downloadManager=(DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
        //获得下载id,这是下载任务生成时的唯一id,可通过此id获得下载信息
        long requestId= downloadManager.enqueue(CreateRequest(url));
        //查询下载信息方法
        queryDownloadProgress(requestId,downloadManager);
        return  requestId;
    }
 
    private void queryDownloadProgress(long requestId, DownloadManager downloadManager) {
 
 
        DownloadManager.Query query=new DownloadManager.Query();
        //根据任务编号id查询下载任务信息
        query.setFilterById(requestId);
        try {
            boolean isGoging=true;
            while (isGoging) {
                Cursor cursor = downloadManager.query(query);
                if (cursor != null && cursor.moveToFirst()) {
 
                    //获得下载状态
                    int state = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                    switch (state) {
                        case DownloadManager.STATUS_SUCCESSFUL://下载成功
                            isGoging=false;
                            handler.obtainMessage(downloadManager.STATUS_SUCCESSFUL).sendToTarget();//发送到主线程,更新ui
                            break;
                        case DownloadManager.STATUS_FAILED://下载失败
                            isGoging=false;
                            handler.obtainMessage(downloadManager.STATUS_FAILED).sendToTarget();//发送到主线程,更新ui
                            break;
 
                        case DownloadManager.STATUS_RUNNING://下载中
                            /**
                             * 计算下载下载率;
                             */
                            int totalSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                            int currentSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                            int progress = (int) (((float) currentSize) / ((float) totalSize) * 100);
                            handler.obtainMessage(downloadManager.STATUS_RUNNING, progress).sendToTarget();//发送到主线程,更新ui
                            break;
 
                        case DownloadManager.STATUS_PAUSED://下载停止
                            handler.obtainMessage(DownloadManager.STATUS_PAUSED).sendToTarget();
                            break;
 
                        case DownloadManager.STATUS_PENDING://准备下载
                            handler.obtainMessage(DownloadManager.STATUS_PENDING).sendToTarget();
                            break;
                    }
                }
                if(cursor!=null){
                    cursor.close();
                }
            }
 
        }catch (Exception e){
            e.printStackTrace();
        }
    }
 
    private DownloadManager.Request CreateRequest(String url) {
 
        DownloadManager.Request  request=new DownloadManager.Request(Uri.parse(url));
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);// 隐藏notification
 
        request.setAllowedNetworkTypes(request.NETWORK_WIFI);//设置下载网络环境为wifi
 
        request.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS,"MyApp.app");//指定apk缓存路径,默认是在SD卡中的Download文件夹
 
        return  request;
    }
}

6、在主线程中通过Handler获取Message,并回调handleMessage方法处理信息,更新UI,MainActivity.java:

Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case DownloadManager.STATUS_SUCCESSFUL:
                    downloadDialog.setProgress(100);
                    canceledDialog();
                    Toast.makeText(MainActivity.this, "下载任务已经完成!", Toast.LENGTH_SHORT).show();
                    break;
 
                case DownloadManager.STATUS_RUNNING:
                    //int progress = (int) msg.obj;
                    downloadDialog.setProgress((int) msg.obj);
                    //canceledDialog();
                    break;
 
                case DownloadManager.STATUS_FAILED:
                    canceledDialog();
                    break;
 
                case DownloadManager.STATUS_PENDING:
                    showDialog();
                    break;
            }
        }
    };

7、下载完成后进行安装(静态注册广播接收器,实现安装功能)AndroidManifest.xml:

<receiver
            android:name=".InstallApkBroadcast">
            <intent-filter>
                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
                <action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/>
            </intent-filter>
        </receiver>

8、接受广播并自行安装应用,InstallApkBroadcast.java:

public class InstallApkBroadcast extends BroadcastReceiver {
	@Override
	public void onReceive(Context context, Intent intent) {
		install(context);
	}

	private void install(Context context) {
		Intent installintent = new Intent();
		installintent.setAction(Intent.ACTION_VIEW);
		// 在Boradcast中启动活动需要添加Intent.FLAG_ACTIVITY_NEW_TASK
		installintent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//		installintent.setDataAndType(
//				Uri.fromFile(new File(Environment.getExternalStorageDirectory()
//						+ "/vc.apk")),
//				"application/vnd.android.package-archive");// 存储位置为Android/data/包名/file/Download文件夹
		installintent.setDataAndType(
				Uri.fromFile(new File(context.getExternalFilesDir(
						Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()
						+ "/vc.apk")),
				"application/vnd.android.package-archive");
		context.startActivity(installintent);
	}
}

9、权限:

<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" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />

参考:

https://blog.csdn.net/suyimin2010/article/details/81380334

https://blog.csdn.net/LovePluto/article/details/71309443

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值