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;
}
}
}
}