SolinariWu
4/3/2017 - 4:05 AM

DownloadManager

DownloadManager

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.solinari.automaticallyopenapk.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true" >
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
</provider>
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path path="." name="external_storage" />
</paths>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ffffffff">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/update"
        android:textColor="@color/black"
        android:textStyle="normal|bold"
        android:layout_marginTop="15dp"
        android:layout_marginLeft="15dp"/>
    <TextView
        android:id="@+id/textView2"
        android:layout_below="@id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:layout_marginLeft="15dp"
        android:text="@string/wait" />
    <ProgressBar
        android:id="@+id/download_progressBar"
        android:layout_below="@id/textView2"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:indeterminate="false"
        android:layout_marginTop="15dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:max="100" />
    <TextView
        android:id="@+id/txtProgress"
        android:layout_below="@id/download_progressBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_marginBottom="15dp"
        android:textStyle="normal|bold"/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
        <include
            layout="@layout/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|enterAlways|snap" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/version"
        android:textColor="@color/black"
        android:textSize="18sp"
        android:textStyle="bold"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"/>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/tvVersion"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="18sp"
        android:layout_marginLeft="5dp" />
    <Button
        android:id="@+id/btnUpload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/update" />
    </LinearLayout>
    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/author"
        android:textColor="@color/black"
        android:textSize="18sp"
        android:textStyle="bold"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"/>
    <TextView
        android:id="@+id/tvAuthor"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/author_name"
        android:textColor="@color/black"
        android:textSize="18sp"
        android:layout_marginLeft="5dp"/>
    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/email"
        android:textColor="@color/black"
        android:textSize="18sp"
        android:textStyle="bold"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"/>
    <TextView
        android:id="@+id/tvEmail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/author_email"
        android:textColor="@color/black"
        android:textSize="18sp"
        android:layout_marginLeft="5dp"/>
</LinearLayout>
package com.example.solinari.automaticallyopenapk;

import android.content.Context;
import android.content.SharedPreferences;

/**
 * Created by Solinari on 2017/3/2.
 */

public class SharedPreferencesHelper {
    final String SP_Name = "AutomaticallyOpenApk_SP";
    public final String DownloadID = "LoginID";
    public SharedPreferences settings;
    public SharedPreferences.Editor PE;
    public SharedPreferencesHelper(Context context) {
        settings = context.getSharedPreferences(SP_Name, 0);
        PE = settings.edit();
    }
    public void setDownloadID(long id) {//儲存DownloadID
        PE.putLong(DownloadID,id);
        PE.commit();
    }
    public long getDownloadID() {
        return settings.getLong(DownloadID, -1);
    }//取得DownloadID
}
class DownloadObserver extends ContentObserver
    {
        public DownloadObserver(Handler handler) {
            super(handler);
        }
        @Override
        public void onChange(boolean selfChange) {
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(LatestDownloadID);
            DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
            final Cursor cursor = dm.query(query);
            if (cursor != null && cursor.moveToFirst()) {
                final int totalColumn = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
                final int currentColumn = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
                int totalSize = cursor.getInt(totalColumn);
                int currentSize = cursor.getInt(currentColumn);
                float percent = (float) currentSize / (float) totalSize;
                final int progress = Math.round(percent * 100);
                runOnUiThread(new Runnable() {//確保在UI Thread執行
                    @Override
                    public void run() {
                        newFragment.setProgress(progress);
                    }
                });
            }
        }
    }
private void DownloadManagerEnqueue(){
        //創建目錄
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ;
        //設定APK儲存位置
        request.setDestinationInExternalPublicDir(  Environment.DIRECTORY_DOWNLOADS  , "Solinari.apk" ) ;
        DownloadCompleteReceiver receiver = new DownloadCompleteReceiver(getApplicationContext());
        registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));//註冊DOWNLOAD_COMPLETE-BroadcastReceiver
        downloadObserver = new DownloadObserver(null);
        getContentResolver().registerContentObserver(CONTENT_URI, true, downloadObserver);//註冊ContentObserver
        LatestDownloadID= DM.enqueue(request);
        SharedPreferencesHelper sp = new SharedPreferencesHelper(getApplicationContext());
        sp.setDownloadID(LatestDownloadID);//儲存DownloadID
    }
private void DownloadManagerEnqueue(){
        //創建目錄
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ;
        //設定APK儲存位置
        request.setDestinationInExternalPublicDir(  Environment.DIRECTORY_DOWNLOADS  , "Solinari.apk" ) ;
        downloadObserver = new DownloadObserver(null);
        getContentResolver().registerContentObserver(CONTENT_URI, true, downloadObserver);//註冊ContentObserver
        LatestDownloadID= DM.enqueue(request);
    }
package com.example.solinari.automaticallyopenapk;

import android.annotation.SuppressLint;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import java.io.File;

/**
 * Created by Solinari on 2017/3/2.
 */

public class DownloadCompleteReceiver extends BroadcastReceiver {
    static SharedPreferencesHelper sp ;
    Context con;
    public DownloadCompleteReceiver(Context context){
        con = context;
        sp = new SharedPreferencesHelper(context);
    }
    @SuppressLint("NewApi")
    public void onReceive(Context context, Intent intent) {
        long downLoadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        long cacheDownLoadId = sp.getDownloadID();
        if (cacheDownLoadId == downLoadId) {
            Intent install = new Intent(Intent.ACTION_VIEW);
            File apkFile = queryDownloadedApk(context);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//Android 7.0 需要透過FileProvider來取得APK檔的Uri
                install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                Uri contentUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", apkFile);
                install.setDataAndType(contentUri, "application/vnd.android.package-archive");
            } else {
                install.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
                install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
            context.startActivity(install);//開啟安裝畫面
        }
    }

    //透過downLoadId尋找下載的apk檔,解决6.0以上版本安裝問題
    public static File queryDownloadedApk(Context context) {
        File targetApkFile = null;
        DownloadManager downloader = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);

        long downloadId =sp.getDownloadID();
        if (downloadId != -1) {
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(downloadId);
            query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
            Cursor cur = downloader.query(query);
            if (cur != null) {
                if (cur.moveToFirst()) {
                    String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                    if (!TextUtils.isEmpty(uriString)) {
                        targetApkFile = new File(Uri.parse(uriString).getPath());
                    }
                }
                cur.close();
            }
        }
        return targetApkFile;
    }
}

package com.example.solinari.automaticallyopenapk;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * Created by Solinari on 2016/12/4.
 */

public class DialogFragmentHelper extends DialogFragment{
    private ProgressBar progressBar;//下載新版APP時ProgressBar
    private TextView txtProgress;//下載新版APP時顯示文字百分比
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);//取消Dialog title列
        getDialog().setCanceledOnTouchOutside(false);//不能點擊Dialog以外區域
        View v = inflater.inflate(R.layout.download_apk_dialog, container, false);
        progressBar = (ProgressBar) v.findViewById(R.id.download_progressBar);
        txtProgress = (TextView) v.findViewById(R.id.txtProgress);
        txtProgress.setText("0%");
        return v;
    }
    protected void setProgress(int progress){//更新進度條
        progressBar.setProgress(progress);
        txtProgress.setText(Integer.toString(progress) + "%");
    }


}
package com.example.solinari.automaticallyopenapk;

import android.Manifest;
import android.app.DownloadManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import org.w3c.dom.Text;

/**
 * Created by Solinari on 2017/02/15.
 */

public class About extends Navigation_BaseActivity {
    DownloadManager DM ;
    DownloadManager.Request request;
    private long LatestDownloadID;
    String URL;
    DialogFragmentHelper newFragment;
    static final Uri CONTENT_URI = Uri.parse("content://downloads/my_downloads");
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         setContentView(R.layout.about);
        Button btnUpload = (Button) findViewById(R.id.btnUpload);
        toolbar.setTitle(R.string.about);//設置ToolBar Title
        setUpToolBar();//使用父類別的setUpToolBar(),設置ToolBar
        CurrentMenuItem = 1;//目前Navigation項目位置
        NV.getMenu().getItem(CurrentMenuItem).setChecked(true);//設置Navigation目前項目被選取狀態
        TextView tvVersion = (TextView) findViewById(R.id.tvVersion);
        try {//取得APP目前的versionName
            PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
            tvVersion.setText( packageInfo.versionName);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        btnUpload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                DownloadNewVersion();
            }
        });
    }
    private void DownloadNewVersion(){
        newFragment = new DialogFragmentHelper();
        newFragment.show(getSupportFragmentManager(),"download apk");
        DM = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        URL = "https://github.com/SolinariWu/AutomaticallyOpenApk/raw/master/Solinari.apk";
        Uri uri = Uri.parse(URL);
        request = new DownloadManager.Request(uri);
        request.setMimeType("application/vnd.android.package-archive");//設置MIME為Android APK檔
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//Android 6.0以上需要判斷使用者是否願意開啟儲存(WRITE_EXTERNAL_STORAGE)的權限
            CheckStoragePermission();
        }
        else{
            DownloadManagerEnqueue();
        }
    }
    private void DownloadManagerEnqueue(){
        //創建目錄
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ;
        //設定APK儲存位置
        request.setDestinationInExternalPublicDir(  Environment.DIRECTORY_DOWNLOADS  , "DG_App.apk" ) ;
        LatestDownloadID= DM.enqueue(request);
    }
    private void CheckStoragePermission() {//Android 6.0檢查是否開啟儲存(WRITE_EXTERNAL_STORAGE)的權限,若否,出現詢問視窗
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {//Can add more as per requirement
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE},
                    20);
        } else {
            DownloadManagerEnqueue();
        }
    }
    @Override//Android 6.0以上 接收使用者是否允許使用儲存權限
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 20: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    DownloadManagerEnqueue();
                } else {
                    CheckStoragePermission();
                }
                return;
            }
        }
    }

}