Android 程序自动更新

来源:互联网 发布:python实现二叉树 编辑:程序博客网 时间:2024/06/04 18:30
之前帮别人定制的一个android应用需要加个自动更新的功能。在 Market 里的应用是无需操心此事的,但像我这种定制的程序就需要自己实现。

原理相当简单,检查更新的时候,通过指定的URL获取服务器端版本信息。比较版本,如果更新,访问服务器端返回的apk的URL地址,下载,安装。各种 Makert 也是通过类似的机制实现的。原理搞清楚了,代码就相当简单了。

获取apk的VesionName,即AndroidManifest.xml中定义的android:versionName

public String getVesionName(Context context)
{    String versionName = null;
    try {
        versionName = context.getPackageManager().getPackageInfo("net.vpntunnel", 0).versionName;
    } catch (NameNotFoundException e) {
        Log.e(TAG, e.getMessage());
    }
 
    return versionName;
}

更新以及安装程序需要的权限,在AndroidManifest.xml中添加

<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
<uses-permission android:name="android.permission.INSTALL_PACKAGES"></uses-permission>

获取apk的versionCode,即AndroidManifest.xml中定义的android:versionCode

public int getVersionCode(Context context) {
    int versionCode = 0;
    try {
        versionCode = context.getPackageManager().getPackageInfo("net.vpntunnel", 0).versionCode;
    } catch (NameNotFoundException e) {
        Log.e(TAG, e.getMessage());
    }
 
    return versionCode;
}

服务器端version.JSON,包含apk路径以及版本信息

{
    "ApkName":"NAME",
    "ApkFullName":"NAME_1.0.5.apk",
    "VersionName":"1.0.5",
    "VersionCode":3
}

获取远程服务器的版本信息

private void getRemoteJSON(string host) throws ClientProtocolException, IOException, JSONException {
    String url = String.format("http://%s/%s", host, VER_JSON);
    StringBuilder sb = new StringBuilder();
    HttpClient client = new DefaultHttpClient();
    HttpParams httpParams = client.getParams();
    HttpConnectionParams.setConnectionTimeout(httpParams, 3000);
    HttpConnectionParams.setSoTimeout(httpParams, 5000);
    HttpResponse response = client.execute(new HttpGet(url));
    HttpEntity entity = response.getEntity();
    if (entity != null) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"), 8192);
 
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        reader.close();
    }
 
    JSONObject object = (JSONObject) new JSONTokener(sb.toString()).nextValue();
    this.apkFullName = object.getString("ApkFullName");
    this.versionName = object.getString("VersionName");
    this.versionCode = Integer.valueOf(object.getInt("VersionCode"));
}


发现更新的提醒窗口,通过AlertDialog实现

private void shoVersionUpdate(String newVersion, final String updateURL) {
    String message = String.format("%s: %s, %s", mContext.getString(R.string.found_newversion), newVersion, mContext.getString(R.string.need_update));
    AlertDialog dialog = new AlertDialog.Builder(mContext).setTitle(mContext.getString(R.string.alertdialog_title)).setMessage(message)
    // update
            .setPositiveButton(mContext.getString(R.string.alertdialog_update_button), new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    pBar = new ProgressDialog(mContext);
                    pBar.setTitle(mContext.getString(R.string.progressdialog_title));
                    pBar.setMessage(mContext.getString(R.string.progressdialog_message));
                    pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                    dialog.dismiss();
                    downFile(updateURL);
                }
                // cancel
            }).setNegativeButton(mContext.getString(R.string.alertdialog_cancel_button), new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    dialog.dismiss();
                }
            }).create();
    dialog.show();
}

下载新版的apk文件,存放地址可以放到SD卡中。通过Environment.getExternalStorageDirectory()获取SD卡中的路径

private void downFile(final String url) {
    pBar.show();
    new Thread() {
        public void run() {
            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(url);
            HttpResponse response;
            try {
                response = client.execute(get);
                HttpEntity entity = response.getEntity();
                long length = entity.getContentLength();
                InputStream is = entity.getContent();
                FileOutputStream fileOutputStream = null;
                if (is != null) {
                    File f = new File(UPDATE_DIR);
                    if (!f.exists()) {
                        f.mkdirs();
                    }
                    fileOutputStream = new FileOutputStream(new File(UPDATE_DIR, updateFileName));
 
                    byte[] buf = new byte[1024];
                    int ch = -1;
                    int count = 0;
                    while ((ch = is.read(buf)) != -1) {
                        fileOutputStream.write(buf, 0, ch);
                        count += ch;
                        Log.d(TAG, String.valueOf(count));
                        if (length > 0) {
                        }
                    }
                }
                fileOutputStream.flush();
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
 
                handler.post(new Runnable() {
                    public void run() {
                        pBar.cancel();
                        installUpdate();
                    }
                });
            } catch (Exception e) {
                pBar.cancel();
                Log.e(TAG, e.getMessage());
            }
        }
 
    }.start();
}


安装更新

private void installUpdate() {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(Uri.fromFile(new File(UPDATE_DIR, updateFileName)), "application/vnd.android.package-archive");
    mContext.startActivity(intent);
}

至此更新需要函数就完成了,根据自己的业务逻辑组合一下,更新功能就搞定了。也可以稍微封装下,写成一个通用类,下次就可以直接用了。



原创粉丝点击