android downloads apk and installs

Posted by georgen on Fri, 25 Oct 2019 17:20:46 +0200

1. First, we set the Dialog layout file, 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="Version update"/>
 
    <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,

The progress bar shows the download progress, and TextView shows the download percentage.

Then customize an AlertDialog, set the layout file in, 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);
        //Set dialog box style
        setStyle();
        //Initialize control
        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() {
        //Settings dialog cannot be cancelled
        this.setCancelable(false);
        //Set the touch dialog outside cannot be cancelled
        this.setCanceledOnTouchOutside(false);
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindow().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        //Get application window size
        WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes();
        //Set dialog Center
        layoutParams.gravity = Gravity.CENTER;
        //Set the dialog width to 3 / 5 of the screen
        layoutParams.width = (displaymetrics.widthPixels/5)*3;
    }
 
    //Set progress bar
    public void setProgress(int progress){
        mTextView.setText(progress+"%");
        mProgressBar.setProgress(progress);
    }
}

3. Create a display dialog box and cancel the dialog box, MainActivity:

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

4. Create a download method to download the application:

private void download() {
        showDialog();
        //It's better to use single thread pool or intentService
        new Thread(new DownLoadRunnable(this,url, handler)).start();
    }

5. Specific handling methods in 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() {
     //Set the thread priority as the background, so that when multiple threads are concurrent, the CPU time allocated by many irrelevant threads will be reduced, which is conducive to the processing of the main thread.   
     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
     //Specific download method
        startDownload();
    }
 
    private long startDownload() {
        //Get DownloadManager object
        DownloadManager downloadManager=(DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
        //Obtain the download id, which is the unique id when the download task is generated. You can obtain the download information through this id
        long requestId= downloadManager.enqueue(CreateRequest(url));
        //Query download information method
        queryDownloadProgress(requestId,downloadManager);
        return  requestId;
    }
 
    private void queryDownloadProgress(long requestId, DownloadManager downloadManager) {
 
 
        DownloadManager.Query query=new DownloadManager.Query();
        //Query download task information according to task id
        query.setFilterById(requestId);
        try {
            boolean isGoging=true;
            while (isGoging) {
                Cursor cursor = downloadManager.query(query);
                if (cursor != null && cursor.moveToFirst()) {
 
                    //Get download status
                    int state = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                    switch (state) {
                        case DownloadManager.STATUS_SUCCESSFUL://Download successful
                            isGoging=false;
                            handler.obtainMessage(downloadManager.STATUS_SUCCESSFUL).sendToTarget();//Send to main thread, update ui
                            break;
                        case DownloadManager.STATUS_FAILED://Download failed
                            isGoging=false;
                            handler.obtainMessage(downloadManager.STATUS_FAILED).sendToTarget();//Send to main thread, update ui
                            break;
 
                        case DownloadManager.STATUS_RUNNING://Download
                            /**
                             * Calculate download rate;
                             */
                            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();//Send to main thread, update ui
                            break;
 
                        case DownloadManager.STATUS_PAUSED://Download stop
                            handler.obtainMessage(DownloadManager.STATUS_PAUSED).sendToTarget();
                            break;
 
                        case DownloadManager.STATUS_PENDING://Ready to download
                            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);// Hide notification
 
        request.setAllowedNetworkTypes(request.NETWORK_WIFI);//Set the download network environment to wifi
 
        request.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS,"MyApp.app");//Specify the apk cache path, which is the Download folder in SD card by default
 
        return  request;
    }
}

6. In the main thread, get Message through Handler, call handleMessage method to process information, update 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, "Download task completed!", 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. After the download is completed, install (register the broadcast receiver statically to realize the installation function) 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. Accept the broadcast and install the application by yourself, 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);
		// To start an activity in Boradcast, you need to add 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"; / / the storage location is Android/data / package name / file/Download folder
		installintent.setDataAndType(
				Uri.fromFile(new File(context.getExternalFilesDir(
						Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()
						+ "/vc.apk")),
				"application/vnd.android.package-archive");
		context.startActivity(installintent);
	}
}

9. Authority:

<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" />

Reference resources:

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

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

Topics: Android Java xml network