apk包自动检测更新,下载安装;

package com.ecjia.update;


import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.ecjia.hamster.model.UPDATE_BEAN;
import com.ecjia.mydialog.CustomDialog;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by Jongey on 2018/3/27  0027.
 * CheckVersionInfoTask.java
 * 从服务器取得版本信息,与本地apk对比版本号,判断是否有更新,然后用Dialog让用户选择是否更新
 * 若用户选择更新,则调用服务去完成apk文件的下载
 */
public class CheckVersionInfoTask extends AsyncTask<Void, Void, String>  {

    private static final String TAG = "CheckVersionInfoTask";
    private ProgressDialog dialog;
    private  Context mContext;
    private boolean mShowProgressDialog;
    private CustomDialog.Builder builder;
    private CustomDialog mDialog;
    private UPDATE_BEAN update_bean;
    private String apkUrl ;
    private String updateMessage ;
    private int apkCode ;

    //服务器端地址
    private static final String VERSION_INFO_URL = "xxxxxx";

    public CheckVersionInfoTask(Context context, boolean showProgressDialog) {
        this.mContext = context;
        this.mShowProgressDialog = showProgressDialog;

    }

    //初始化显示Dialog
    protected void onPreExecute() {
        if (mShowProgressDialog) {
            dialog = new ProgressDialog(mContext);
            dialog.setMessage("正在检测新版本");
            dialog.show();
        }
    }

    //在后台任务(子线程)中检查服务器的版本信息
    @Override
    protected String doInBackground(Void... params) {
        return getVersionInfo(VERSION_INFO_URL);
    }


    //后台任务执行完毕后,解除Dialog并且解析return返回的结果
    @Override
    protected void onPostExecute(String result) {

        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }

        if (!TextUtils.isEmpty(result)) {
            parseJson(result);
        }
    }


    /**
     * 从服务器取得版本信息
     * {
       "url":"http://crazyfzw.github.io/demo/auto-update-version/new-version-v2.0.apk",
        "versionName":2,
       "updateMessage":"[1]新增视频弹幕功能<br/>[2]优化离线缓存功能<br/>[3]增强了稳定性"
       }
     * @return
     */
    public String getVersionInfo(String urlStr){
        HttpURLConnection uRLConnection = null;
        InputStream is = null;
        BufferedReader buffer = null;
        String result = null;
        try {
            URL url = new URL(urlStr);
            uRLConnection = (HttpURLConnection) url.openConnection();
            uRLConnection.setRequestMethod("GET");
            is = uRLConnection.getInputStream();
            buffer = new BufferedReader(new InputStreamReader(is));
            StringBuilder strBuilder = new StringBuilder();
            String line;
            while ((line = buffer.readLine()) != null) {
                strBuilder.append(line);
            }
            result = strBuilder.toString();
        } catch (Exception e) {
            Log.e(TAG, "http post error");
        } finally {
            if (buffer != null) {
                try {
                    buffer.close();
                } catch (IOException ignored) {
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ignored) {

                }
            }
            if (uRLConnection != null) {
                uRLConnection.disconnect();
            }
        }
        return result;
    }


    /**
     *
     * @param result
     */
    private void parseJson(String result) {


            Gson gson = new Gson();
            java.lang.reflect.Type type = new TypeToken<UPDATE_BEAN>() {}.getType();

            update_bean = gson.fromJson(result, type);

            apkUrl=update_bean.getData().getApk_url();//APK下载路径
            updateMessage=update_bean.getData().getApp_new_text();//版本更新说明
            apkCode = update_bean.getData().getApp_version_num(); //新版APK对于的版本号

            //JSONObject obj = new JSONObject(result);
            //String apkUrl = obj.getString("apk_url");
            //String updateMessage = obj.getString("app_new_text");
            //String apkCode = obj.getString("app_version_num");

            //取得已经安装在手机的APP的版本号 versionCode
            final int versionCode = getCurrentVersionCode();

            //对比版本号判断是否需要更新
            if (apkCode > versionCode) {

                    //showDialog(updateMessage, apkUrl);

                    showTwoButtonDialog(updateMessage,"版本更新提示","立即更新","取消",new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            goToDownloadApk(apkUrl);
                            mDialog.dismiss();
                        }
                    }, new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            mDialog.dismiss();
                            //这里写自定义处理XXX
                        }
                    });

            } else if (mShowProgressDialog) {
                Toast.makeText(mContext, "当前已经是最新版本了哦", Toast.LENGTH_SHORT).show();

            }

    }

    /**
     * 取得当前版本号
     * @return
     */
    public int getCurrentVersionCode() {

        try {
            return mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), PackageManager.GET_CONFIGURATIONS).versionCode;
        } catch (PackageManager.NameNotFoundException ignored) {

        }
        return 0;
    }

    /**
     * 显示对话框提示用户有新版本,并且让用户选择是否更新版本
     * @param alertText  提示信息
     * @param confirmText  升级
     * @param cancelText  忽略
     * @param conFirmListener  升级按钮监听
     * @param cancelListener   忽略按钮监听
     */
    private void showTwoButtonDialog(String alertText,String title,String confirmText, String cancelText, View.OnClickListener conFirmListener, View.OnClickListener cancelListener) {

        builder = new CustomDialog.Builder(mContext);
        mDialog = builder.setTitle(title)
                .setMessage(Html.fromHtml(alertText))
                .setPositiveButton(confirmText, conFirmListener)
                .setNegativeButton(cancelText, cancelListener)
                .createTwoButtonDialog();
        mDialog.show();
    }


    /**
     * 显示对话框提示用户有新版本,并且让用户选择是否更新版本
     * @param content 提示信息
     * @param downloadUrl apk下载地址
     */
    public void showDialog(String content, final String downloadUrl) {

            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            builder.setTitle("发现了新版本");
            builder.setMessage(Html.fromHtml(content))
                    .setPositiveButton("升级", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            //下载apk文件
                            goToDownloadApk(downloadUrl);
                        }
                    })
                    .setNegativeButton("忽略", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                        }
                    });

            AlertDialog dialog = builder.create();
            //点击对话框外面,对话框不消失
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();
    }


    /**
     * intent启用DownloadService服务去下载AKP文件
     * @param downloadUrl
     */
    private void goToDownloadApk(String downloadUrl) {
        Intent intent = new Intent(mContext, DownloadApkService.class);
        intent.putExtra("apkUrl", downloadUrl);
        mContext.startService(intent);
    }


}

/**
 *后台下载apk服务
 */

package com.ecjia.update;

import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by Jongey on 2018/3/27  0027.
 * 创建服务完成apk文件的下载,下载完成后调用系统的安装程序完成安装
 */
public class DownloadApkService extends IntentService{

    private static final int BUFFER_SIZE = 10 * 1024; //缓存大小
    private static final String TAG = "DownloadService";

    private static final int NOTIFICATION_ID = 0;
    private NotificationManager mNotifyManager;
    private NotificationCompat.Builder mBuilder;

    public DownloadApkService() {
        super("DownloadApkService");
    }

    /**
     * onHandleIntent中下载apk文件
     * @param intent
     */
    @Override
    protected void onHandleIntent(Intent intent) {

        //初始化通知,用于显示下载进度
        mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(this);
        String appName = getString(getApplicationInfo().labelRes);
        int icon = getApplicationInfo().icon;
        mBuilder.setContentTitle(appName).setSmallIcon(icon);

        String urlStr = intent.getStringExtra("apkUrl"); //intent中取得apk下载路径

        InputStream in = null;
        FileOutputStream out = null;
        try {
            //建立下载连接
            URL url = new URL(urlStr);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(false);
            urlConnection.setConnectTimeout(10 * 1000);
            urlConnection.setReadTimeout(10 * 1000);
            urlConnection.setRequestProperty("Connection", "Keep-Alive");
            urlConnection.setRequestProperty("Charset", "UTF-8");
            urlConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
            urlConnection.connect();

            //以文件流读取数据
            long bytetotal = urlConnection.getContentLength(); //取得文件长度
            long bytesum = 0;
            int byteread = 0;
            in = urlConnection.getInputStream();
            File dir = StorageUtils.getCacheDirectory(this); //取得应用缓存目录
            String apkName = urlStr.substring(urlStr.lastIndexOf("/") + 1, urlStr.length());//取得apK文件名
            File apkFile = new File(dir, apkName);
            out = new FileOutputStream(apkFile);
            byte[] buffer = new byte[BUFFER_SIZE];

            int limit = 0;
            int oldProgress = 0;
            while ((byteread = in.read(buffer)) != -1) {
                bytesum += byteread;
                out.write(buffer, 0, byteread);
                int progress = (int) (bytesum * 100L / bytetotal);
                // 如果进度与之前进度相等,则不更新,如果更新太频繁,则会造成界面卡顿
                if (progress != oldProgress) {
                    updateProgress(progress);
                }
                oldProgress = progress;
            }

            // 下载完成,调用installAPK开始安装文件
            installAPk(apkFile);
            Log.d("调试","download apk finish");
            mNotifyManager.cancel(NOTIFICATION_ID);

        } catch (Exception e) {
            Log.e(TAG, "download apk file error");
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException ignored) {

                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ignored) {

                }
            }
        }
    }

    /**
     * 实时更新下载进度条显示
     * @param progress
     */
    private void updateProgress(int progress) {
        //"正在下载:" + progress + "%"
        mBuilder.setContentText("升级").setProgress(100, progress, false);
        PendingIntent pendingintent = PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_CANCEL_CURRENT);
        mBuilder.setContentIntent(pendingintent);
        mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
    }

    /**
     * 调用系统安装程序安装下载好的apk
     * @param apkFile
     */
    private void installAPk(File apkFile) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        //如果没有设置SDCard写权限,或者没有sdcard,apk文件保存在内存中,需要授予权限才能安装
        try {
            String[] command = {"chmod", "777", apkFile.toString()}; //777代表权限 rwxrwxrwx
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.start();
        } catch (IOException ignored) {
        }
        intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
}
/**
*工具类
*/

package com.ecjia.update;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.util.Log;

import java.io.File;
import java.io.IOException;

import static android.os.Environment.MEDIA_MOUNTED;

/**
 * Provides application storage paths
 */
final class StorageUtils {

    private static final String TAG = "StorageUtils";
    private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";

    private StorageUtils() {
    }

    /**
     * Returns application cache directory. Cache directory will be created on SD card
     * <i>("/Android/data/[app_package_name]/cache")</i> if card is mounted and app has appropriate permission. Else -
     * Android defines cache directory on device's file system.
     *
     * @param context Application context
     * @return Cache {@link File directory}
     */
    public static File getCacheDirectory(Context context) {
        File appCacheDir = null;
        if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
            appCacheDir = getExternalCacheDir(context);
        }
        if (appCacheDir == null) {
            appCacheDir = context.getCacheDir();
        }
        if (appCacheDir == null) {
            Log.w(TAG, "Can't define system cache directory! The app should be re-installed.");
        }
        return appCacheDir;
    }


    private static File getExternalCacheDir(Context context) {
        File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
        File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
        if (!appCacheDir.exists()) {
            if (!appCacheDir.mkdirs()) {
                Log.w(TAG, "Unable to create external cache directory");
                return null;
            }
            try {
                new File(appCacheDir, ".nomedia").createNewFile();
            } catch (IOException e) {
                Log.i(TAG, "Can't create \".nomedia\" file in application external cache directory");
            }
        }
        return appCacheDir;
    }

    private static boolean hasExternalStoragePermission(Context context) {
        int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION);
        return perm == PackageManager.PERMISSION_GRANTED;
    }
}







 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值