System with Download Manager

Keywords: Android Database Java xml

Preface:

Are you still writing Download Utils on your own? With Download Manger, all you need to do is draw the UI and leave the rest to him.

Introduction:

Download Manager is a system download method after Android 2.3. It is a system service that handles long-running HTTP downloads. The URI that the client can request is downloaded to a specific target file. The client will interact with HTTP in the background to download, or the download will fail, or the connection will be changed and the system will be restarted. You can also access the download management interface of the system to view progress. Download Manger has two subclasses, Request and Query. The Request class can set some properties for download. Query class can query the current download progress, download address, file storage directory and other data.

DownloadManager

1. Required permissions

<uses-permission android:name="android.permission.INTERNET" />;

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>;

2. Get the object and start downloading

DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));
long id = downloadManager.enqueue(request);
//Each downloaded file corresponds to an id through which data can be queried.

3. Cancel Download

downloadManager.remove(REFERENCE_1, REFERENCE_2, REFERENCE_3);  

This method returns the number of successful cancelled downloads. If a download is cancelled, all associated files, partially downloaded files and fully downloaded files will be deleted.

Class Request

1. Specify download location and file name

        /**
         * Method 1: 
         * Directory: Android - > Data - > com. app - > files - > Download - > dxtj. apk
         * This file is dedicated to your application. After the software is uninstalled, all downloaded files will be deleted along with the uninstallation.
         */
request.setDestinationInExternalFilesDir( this , Environment.DIRECTORY_DOWNLOADS ,  "dxtj.apk" );  

        /**
         * Method 2:
         * download file storage address SD Card download folder, dxtj.apk
         * After the software is uninstalled, the downloaded files will be retained
         */
        //Create a folder on the SD card
        request.setDestinationInExternalPublicDir(  "/epmyg/"  , "dxtj.apk" ) ;  


        /**
         * Method 3:
         * If the downloaded file wants to be shared by other applications
         * Especially those files you download that you want to be scanned by Media Scanner (such as music files)
         */
        request.setDestinationInExternalPublicDir( Environment.DIRECTORY_MUSIC,  "Confession balloon.mp3" );  

        /**
         * Method 4
         * The file will be stored in the actual download file stored externally. If there is no folder, create it and, if there is, return false below.
         * The system has a download folder, such as Millet Mobile System Download folder SD card - > Download folder
         */
        //Create directory
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ; 

        //Setting File Storage Path
        request.setDestinationInExternalPublicDir(  Environment.DIRECTORY_DOWNLOADS  , "dxtj.apk" ) ;
    }

2. Specify the type of network downloaded

//Specifies that the download operation is performed in the WIFI state.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
//Specifies that the download operation is performed in MOBILE state
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE);
//Is roaming allowed to perform download operations
request.setAllowedOverRoaming(boolean);
//Is "metered network connection" allowed to perform download operations
request.setAllowedOverMetered(boolean); //Default is allowed.

3. Customize Notification Style

//Setting the title and description of Notification
request.setTitle("Title");  
request.setDescription("describe"); 
//Set Notification's display and hide.
request.setNotificationVisibility(visibility);

VISIBILTY_HIDDEN: Notification: It will not be displayed. If this property is set, permissions must be added.
android.permission.DOWNLOAD_WITHOUT_NOTIFICATION.
VISIBILITY_VISIBLE: Notification displays, but only during the execution of the download task, the completion of the download automatically disappears. (Default value)
VISIBILITY_VISIBLE_NOTIFY_COMPLETED: Notification displays both when downloading and after completion.
VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION: Notification will only be displayed when the task is completed.
There are relatively few methods for setting Notification.

4. Set download file type:

request.setMimeType("application/vnd.android.package-archive");

This is the type of Android. apk file. Some models have to set up this method in order to open the installation interface correctly after downloading and clicking on the Notification Bar. Otherwise a Toast (can not open file). Other file types of MimeType, Baidu bar.

5. Add http headers for network links that request download, such as User-Agent, gzip compression, etc.

request.addRequestHeader(String header, String value);

Class Query

Our requirement may not only be to show progress in Notification, but also to get real-time download progress in app. So Query classes are some of the ways to provide queries.
But there are only two ways in the API. Originally, he saved the data in the database. We need to get a Cursor result set to get the data we want.

 DownloadManager.Query query = new DownloadManager.Query();
 Cursor cursor = downloadManager.query(query.setFilterById(id));
                if (cursor != null && cursor.moveToFirst()) {
                    //Download files to local directories
                    String address = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                    //Number of bytes downloaded
                    int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                    //Total number of bytes to download
                    int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                    //Notification title
                    String title =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
                    //describe
                    String description =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION));
                    //Download the corresponding id
                    long id =cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
                    //Download file name
                    String filename =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
                    //URL links to download files
                    String url =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI));
}

This can only be retrieved once, the information in the database. We can use the Timer class to query the database at regular intervals. ContentProvider can also be used to access.

Deficiencies:

1. I found that when I downloaded, there was no sound when I sent Notification. There is no way to set the sound. But it has little impact. The main function is just to be realized.
2. Because this is the class of the system, the Notification interface of each system is different. This is the definition of each rom manufacturer. Millet is very different from Meizu. So the Notification is not unified.

Implement relevant code:

DownloadActivity.Java

package com.dx.demi.activity;

import android.app.Activity;
import android.app.DownloadManager;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.dx.demi.R;

import java.io.File;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by demi on 2017/2/16.
 */

public class DownloadActivity extends Activity implements View.OnClickListener {
    private TextView down;
    private TextView progress;
    private TextView file_name;
    private ProgressBar pb_update;
    private DownloadManager downloadManager;
    private DownloadManager.Request request;
    public static String downloadUrl = "http://ucdl.25pp.com/fs08/2017/01/20/2/2_87a290b5f041a8b512f0bc51595f839a.apk";
    Timer timer;
    long id;
    TimerTask task;
    Handler handler =new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Bundle bundle = msg.getData();
           int pro = bundle.getInt("pro");
           String name  = bundle.getString("name");
            pb_update.setProgress(pro);
            progress.setText(String.valueOf(pro)+"%");
            file_name.setText(name);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_download);
        down = (TextView) findViewById(R.id.down);
        progress = (TextView) findViewById(R.id.progress);
        file_name = (TextView) findViewById(R.id.file_name);
        pb_update = (ProgressBar) findViewById(R.id.pb_update);
        down.setOnClickListener(this);
        downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        request = new DownloadManager.Request(Uri.parse(downloadUrl));

        request.setTitle("Elephant Teaching");
        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
        request.setAllowedOverRoaming(false);
        request.setMimeType("application/vnd.android.package-archive");
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        //Create directory
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ;

        //Setting File Storage Path
        request.setDestinationInExternalPublicDir(  Environment.DIRECTORY_DOWNLOADS  , "app-release.apk" ) ;
        pb_update.setMax(100);
       final  DownloadManager.Query query = new DownloadManager.Query();
        timer = new Timer();
        task = new TimerTask() {
            @Override
            public void run() {
                Cursor cursor = downloadManager.query(query.setFilterById(id));
                if (cursor != null && cursor.moveToFirst()) {
                    if (cursor.getInt(
                            cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                        pb_update.setProgress(100);
                        install(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/app-release.apk" );
                        task.cancel();
                    }
                    String title = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
                    String address = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                    int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                    int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                    int pro =  (bytes_downloaded * 100) / bytes_total;
                    Message msg =Message.obtain();
                    Bundle bundle = new Bundle();
                    bundle.putInt("pro",pro);
                    bundle.putString("name",title);
                    msg.setData(bundle);
                    handler.sendMessage(msg);
                }
                cursor.close();
            }
        };
        timer.schedule(task, 0,1000);
    }

    @Override
    public void onClick(View v) {
        id = downloadManager.enqueue(request);
        task.run();
        down.setClickable(false);
        down.setBackgroundResource(R.drawable.btn_disable_shape);

    }
    private void install(String path) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.parse("file://" + path), "application/vnd.android.package-archive");
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//Over 4.0 system pop-up installation successfully opens the interface
        startActivity(intent);
    }
}

activity_download.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:gravity="center"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/file_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:text="dxtj.apk"/>
    <ProgressBar
        android:id="@+id/pb_update"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:max="100"
        android:progress="0"
        android:progressDrawable="@drawable/progressbar_color"
        android:layout_marginBottom="20dp"
        />

    <TextView
        android:id="@+id/progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_marginBottom="20dp"
        android:text="0%"/>
    <TextView
        android:id="@+id/down"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:paddingLeft="30dp"
        android:paddingRight="30dp"
        android:background="@drawable/btn_red_selector"
        android:textColor="@color/white"
        android:text="Download now"/>
</LinearLayout>

progressbar_color.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:id="@android:id/background">

        <shape>

            <corners android:radius="10dip" />

            <gradient
                android:angle="0"
                android:centerColor="#e4e4e4"
                android:centerY="0.75"
                android:endColor="#e4e4e4"
                android:startColor="#e4e4e4" />
        </shape>
    </item>

    <item android:id="@android:id/secondaryProgress">

        <clip>

            <shape>

                <corners android:radius="10dip" />

                <gradient
                    android:angle="0"
                    android:centerColor="#e4e4e4"
                    android:centerY="0.75"
                    android:endColor="#e4e4e4"
                    android:startColor="#e4e4e4" />
            </shape>
        </clip>
    </item>

    <item android:id="@android:id/progress">

        <clip>

            <shape>

                <corners android:radius="10dip" />

                <gradient
                    android:angle="0"
                    android:endColor="@color/red"
                    android:startColor="@color/red" />
            </shape>
        </clip>
    </item>

</layer-list>

Operation results:


It's over here. If you have any questions, you can comment and feedback.

Posted by raspberryh on Mon, 01 Apr 2019 19:27:30 -0700