1. 程式人生 > >Android apk升級 相容6.0 7.0 低版本 華為手機

Android apk升級 相容6.0 7.0 低版本 華為手機

上篇部落格寫了用DownloadManager,進行下載,結果發現有些手機並不能相容,查詢原因是DownloadManager.Request 的setDestinationInExternalPublicDir()函式問題,這直接根源掛鉤,Request 有個預設路徑,導致android 7.0的不相容,具體原因不說,你們也應該知道了(API 禁止向您的應用外公開 file://URI,若要在應用間共享檔案,您應傳送一項 content://URI,並授予 URI 臨時訪問許可權。進行此授權的最簡單方式是使用 FileProvider類。 如需有關許可權和共享檔案的更多資訊。)那,您說該怎麼玩呢?那我們就用原始的HttpURLConnection 下載唄,你想呀,無非就是下載一個檔案而已。

多的不說直接上程式碼,下面是個工具類直接用就可以:

public class UpdataAPP {
public Context context;
private ProgressDialog pBar;
private DownloadApkAsyncTask mAsyncTask = null;
private int apkSzie;

public UpdataAPP(Context context) {
    this.context = context;
}

/**
 * 版本更新----起
 */
// 更新版本要用到的一些資訊
public void updateAPP(String url) {
    mAsyncTask = new DownloadApkAsyncTask();
    mAsyncTask.execute(url);
    pBar=new ProgressDialog(context);
    pBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    pBar.setTitle("正在下載");
    pBar.setMessage("請稍候...");
    pBar.setCanceledOnTouchOutside(false);
    pBar.setProgress(0);
    pBar.show();
}


class DownloadApkAsyncTask extends AsyncTask<String, Integer, Integer> {

    private static final int DOWNLOAD_OK = 0x00;
    private static final int DOWNLOAD_ERROR = 0x01;

    private File apkFile = null;
    private File updateDir = null;

    public DownloadApkAsyncTask() {
        super();
    }

    @Override
    protected Integer doInBackground(String... params) {
        try {
            URL url = new URL(params[0]);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            connection.setConnectTimeout(15000);
            InputStream in = connection.getInputStream();
            int curSize = 0;
            int progress = 0;
            int totalSize = connection.getContentLength();
            apkSzie=totalSize;
            pBar.setMax(totalSize); // 設定進度條的總長度
            if (android.os.Environment.MEDIA_MOUNTED
                    .equals(android.os.Environment
                            .getExternalStorageState())) {
                updateDir = new File(Environment
                        .getExternalStorageDirectory().getPath()
                        + "/townnet/apk/");
            } else {
                updateDir = new File("/data/data/" + context.getPackageName()
                        + "/apk/");
            }
            if (!updateDir.exists()) {
                updateDir.mkdirs();
            }
            apkFile = new File(updateDir.getPath(), "townnet.apk");
            if (apkFile.exists()) {
                apkFile.delete();
            }
            // 修改資料夾及安裝包的許可權,供第三方應用訪問
            try {
                Runtime.getRuntime().exec(
                        "chmod 705 " + updateDir.getPath());
                Runtime.getRuntime().exec("chmod 604 " + apkFile.getPath());
            } catch (Exception e) {
                e.printStackTrace();
            }

            int temp;
            byte[] bytes = new byte[1024];
            FileOutputStream out = new FileOutputStream(apkFile);
            while ((temp = in.read(bytes)) != -1) {
                out.write(bytes, 0, temp);
                curSize += temp;
                progress = curSize * 100 / totalSize;
                publishProgress(curSize);
            }
            in.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            return DOWNLOAD_ERROR;
        }
        return DOWNLOAD_OK;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Integer result) {
        super.onPostExecute(result);
        if (result == DOWNLOAD_OK) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            Uri photoURI = FileProvider.getUriForFile(context,
                    context.getPackageName() + ".provider", new File(apkFile.getPath())
            );
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            if (Build.VERSION.SDK_INT >= 24) {

                intent.setDataAndType(photoURI, "application/vnd.android.package-archive");

            } else {
                intent.setDataAndType(Uri.parse("file://" + apkFile.getPath()),
                        "application/vnd.android.package-archive");
            }
            context.startActivity(intent);
        }
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        pBar.setProgress(values[0]); // 這裡就是關鍵的實時更新進度了!
        if (pBar.getProgress()==apkSzie){
            pBar.cancel();
        }
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();
        if (pBar!=null){
            pBar.cancel();
        }

    }

}

}

那你說怎麼用呢?很簡單呀。

//開始下載
new UpdataAPP(mContext).updateAPP(apkDownLoadUrl);

下面是:AndroidManifest.xml的FileProvider:

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/filepaths" />
    </provider>

xml下的filepaths:

這裡寫圖片描述