Android更新之路

现在App更新大部分都是在应用市场更新,但对于有些公司,App更新有可能还是采用古老的办法,把APK文件放入服务器,客户端通过版本号来判断软件是否更新,由于我们公司的老项目是这样处理的 ,所以记录一下该文章,把最新版的APK放入服务端,通过版本号判断客户端及时更新App

所用到的知识以及思路

1   我们这里的版本号是通过xml放入服务端,客户端读取xml数据中的版本号  --- 解析版本号

2   客户端手机App与xml解析出来的版本号进行比较 解析的版本号大于用户正在使用的版本号 --更新

注意:有些小bug对用户体验不是很明显但为了解决这个bug也需要更新  像这种更新我们这里叫做非强制更新,用户可以更新也可以不更新,对于严重的bug和功能模块的上架就需要进行强制更新,强制和非强制也是通过xml进行解析获取到  ---强制更新和非强制更新

3  用户进行更新App需要下载APK文件包这里通过I/O流的方法进行获取APK文件

我的App是在启动页的时候进行判断更新的,也有些App是在应用程序Application中其实都差不多。

现在我们就来完成首先获取到客户端App版本号 int versionCode = context.getPackageManager().getPackageInfo(包名,0).versionCode;

创建ParseXmlService对象  ParseXmlService parseXmlService = new ParseXmlService(); 保存xml数据信息HashMap mHashMap = new HashMap();

使用I/O流读取xml数据

链接网络

URL url = null

  try{

    url = new URL(获取服务端xml数据的API)

}catch(MalformedURLException e1){

    e1.printStackTrace();

}

HttpURLConnection conn = null;

try{

    conn = (HttpURLConnection).url.openConnection();

}catch(IOException e1){

    e1.printStackTrace;

}

conn.setConnectTimeOut(5000);

conn.setReadTimeOut(5000);

try{

    conn.connect();

}catch(IOException e2){

}

输入流获取XML文件数据

InputStream is = null;

try{

    is = conn.getInputStream();

}catch(IOException e1){

    e1.printStackTrace();

}

try{

    mHashMap = service.parsexml(is);

}catch(Exception e){

    e.printStackTrace();

}

先判断mHashMap进行非空判断 

获取版本号  serviceCode = Integer.valueOf(mHashMap.get("version"))

if(serviceCode >versionCode){

    进行更新操作

}

    进入到登陆页或者主页面

}

下面进入到第二步进行更新操作 获取xml数据中的强制更新判断的数据

String force = mHashMap.get("forceupdata")  0:强制  1:非强制

文件更新这里使用的是输入流和文件输出流

1  首先判断手机是否存在SD卡 并且是否具有读写权限

2  获得存储卡的路径  设置全局成员变量   mSavepath   后面还需要用到

3  一般情况下下载文件的API是通过XML文件解读获取到的

if(Environment.getExternalStorageState().equals(Environment,MEDIA_MOUNTED)){

    String sdpath = Environment.getExternalStorageDirectory()+"/";

    mSavePath = sdpath+"download";

    URL url = new URL(服务器域名+XML解析出来的URL)

    HttpURLConnection conn = (HttpURLConnection)url.openConnection();

    conn.setRequestProperty("Accept-Encoding","identity");

    conn.connect();

    //获取文件大小

    int length = conn.getContentLength();

    InputStream is = conn.getInputStream();

    File file = new File(mSavePath);

    //判断文件是否存在

    if(file.exists()){

        file.mkdir();

}

    File apkFile = new File(mSavePath,mHashMap.get("appname"));

    FileOutputStream fos = new FileOutputStream(apkFile);

    int count = 0;

    //缓存

    byte buf[] = new byte[1024]

    do{

        int numread = is.read(buf);

        count+=numread;

        //计算进度条位置

        progress = (int) count/length *100

        //更新进度mHandler.sendEmptyMessage(DownLoad)

        if(numread<=0){

            //下载完成

    }

    }

}

然后关闭各种流操作

最后就是安装APK文件

private void installApk(){

    File apkfile = new File(mSavePath,mHashMap.get("apName"));

    if(!apkfile.exists()){

        return

    }


Intent i = new Intent(Intent.ACTION_VIEW)

  i.addFlag(Intent.FLAG_ACTIVITY_NEW_TASK)

   i.setDataAndType(Uri.parse("file://"+apkfile.toString()),”application/vnd.android.package-archive“);

   mContext.startActivity(i);

}


最后附上完整的UpdataManager   

public class UpdateManager {

private static final StringTAG ="UpdateManager";

    /* 下载中*/

    private static final int DOWNLOAD =1;

    /* 下载结束*/

    private static final int DOWNLOAD_FINISH =2;

    private static final int TO_MAIN_ACTIVITY =3;

    /* 保存解析的XML信息*/

    HashMapmHashMap;

    /* 下载保存路径*/

    private StringmSavePath;

    /* 记录进度条数量*/

    private int progress;

    /* 是否取消更新*/

    private boolean cancelUpdate =false;

    private ThreadnewThread;

    private ContextmContext;

    /* 更新进度条*/

    private ProgressBarmProgress;

    private DialogmDownloadDialog;

    private SharePrefUtilsprefUtils;

    public static int Code;

    private FinalDbdb;

    private StringuserId;

    private Handlerhandler;

    private AbHttpUtilhttpUtil =null;

    private double latitude =0.0;

    private double longitude =0.0;

    private Activityactivity;

    private ConnectivityManagermConnectivityManager;

    private NetworkInfonetInfo;

    @SuppressLint("HandlerLeak")

private HandlermHandler =new Handler() {

public void handleMessage(Message msg) {

switch (msg.what) {

// 正在下载

                case DOWNLOAD:

// 设置进度条位置

                    mProgress.setProgress(progress);

break;

                case DOWNLOAD_FINISH:

// 安装文件

                    installApk();

break;

                case TO_MAIN_ACTIVITY:

//                    mContext.startActivity(new Intent((WelcomeActivity)mContext,MainActivity.class));

                    break;

                default:

break;

            }

}

;

    };

    public UpdateManager(Context context) {

this.mContext = context;

        activity = (Activity)mContext;

        prefUtils =new SharePrefUtils(mContext);

        httpUtil = AbHttpUtil.getInstance(mContext);

        db = FinalDb.create(mContext);

        httpUtil.setTimeout(10000);

        httpUtil.setEasySSLEnabled(true);

        IntentFilter mFilter =new IntentFilter();

        mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);

        activity.registerReceiver(myNetReceiver, mFilter);

    }

public void removeReceiver() {

if (null !=myNetReceiver) {

activity.unregisterReceiver(myNetReceiver);

        }

}

/**

    * 检测软件更新

    */

    public void checkUpdate(ToTranslateActivityListener listener) {

this.listener = listener;

        newThread =new Thread(new Runnable() {

@Override

            public void run() {

isUpdate();

            }

});

        newThread.start();

        handler =new Handler() {

@Override

            // 当有消息发送出来的时候就执行Handler的这个方法

            public void handleMessage(Message msg) {

super.handleMessage(msg);

                showNoticeDialog();

            }

};

    }

/**

    * 检查软件是否有更新版本

    *

    * @return

    */

    private void isUpdate() {

// 获取当前软件版本

        int versionCode = getVersionCode(mContext);

        // 把version.xml放到网络上,然后获取文件信息

        Log.d(TAG, "加载数据前6" + getSystemCurrentTime());

        // 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析

        ParseXmlService service =new ParseXmlService();

        URL url =null;

        try {

url =new URL(Constant.HOST_URL1

                    +"/download/version.xml");

//                    + Constant.Interface.MobiCollectAction_downloadXml);

        }catch (MalformedURLException e1) {

// TODO Auto-generated catch block

            e1.printStackTrace();

        }

HttpURLConnection conn =null;

        try {

conn = (HttpURLConnection) url.openConnection();

        }catch (IOException e1) {

// TODO Auto-generated catch block

            e1.printStackTrace();

        }

conn.setConnectTimeout(5000);

        conn.setReadTimeout(5000);

        try {

conn.connect();

        }catch (IOException e2) {

// TODO Auto-generated catch block

            //Toast.makeText(mContext, "网络连接超时,请稍后重试", Toast.LENGTH_SHORT).show();

        }

InputStream is =null;

        try {

is = conn.getInputStream();

        }catch (IOException e1) {

// TODO Auto-generated catch block

            e1.printStackTrace();

        }

try {

mHashMap = service.parseXml(is);

        }catch (Exception e) {

e.printStackTrace();

        }

if (null !=mHashMap) {

prefUtils.setString(SharePrefUtils.APPOINT_CARNUM,

                    mHashMap.get("appointcarnum"));

            prefUtils.setString(SharePrefUtils.APPOINT_INFO,

                    mHashMap.get("appointinfo"));

            prefUtils.setString(SharePrefUtils.PARKING_MONTH_INFO,

                    mHashMap.get("parkingmonthinfo"));

            prefUtils.setString(SharePrefUtils.CHECK_MEMBER,

                    mHashMap.get("checkmember"));

            prefUtils

                    .setString(SharePrefUtils.HEADIMG, mHashMap.get("headImg"));

            Intent intent =new Intent();

            intent.setAction("com.android.headimg");

            mContext.sendBroadcast(intent);

            int serviceCode = Integer.valueOf(mHashMap.get("version"));

            // 版本判断

            if (serviceCode > versionCode) {

Code =1;

                handler.sendEmptyMessage(0);

            }else {

if (listener !=null) {

listener.onTranslateListener();

                }

}

//            else {

//                List users = db.findAll(MemberUser.class);

//                if (users != null && users.size() != 0) {

//                    MemberUser user = users.get(0);

//                    if (user != null) {

//                        userId = user.getMemberId();

//                    }

//                }

//                if (!TextUtils.isEmpty(userId)) {

//                    String user_phone = users.get(0).getUsername();

//                    String user_pswd = users.get(0).getPassword();

//                    login(user_phone, user_pswd);

//                } else {

//                    Intent intent2 = new Intent(mContext,

//                            LoginActivity.class);

//                    mContext.startActivity(intent2);

//                    Activity a = (Activity) mContext;

//                    a.finish();

//                }

//            }

        }else {

Intent intent2 =new Intent(mContext,

                    LoginActivity.class);

            mContext.startActivity(intent2);

            Activity a = (Activity)mContext;

            a.finish();

        }

}

/**

    * 获取软件版本号

    *

    * @param context

    * @return

    */

    private int getVersionCode(Context context) {

int versionCode =0;

        try {

// 获取软件版本号,对应AndroidManifest.xml下android:versionCode

            versionCode = context.getPackageManager().getPackageInfo(

"com.android.bluetown", 0).versionCode;

        }catch (NameNotFoundException e) {

e.printStackTrace();

        }

return versionCode;

    }

/**

    * 显示软件更新对话框

    */

    private void showNoticeDialog() {

// 构造对话框

        Builder builder =new Builder(mContext);

        builder.setTitle(R.string.soft_update_title);

        builder.setMessage(mHashMap.get("updateinfo"));

        builder.setOnKeyListener(new OnKeyListener() {

@Override

            public boolean onKey(DialogInterface dialog, int keyCode,

                                KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK

                        && event.getRepeatCount() ==0) {

if (mHashMap.get("forceupdate").equals("0")) {

System.exit(0);

                    }else {

if (listener !=null) {

listener.onTranslateListener();

                        }

}

//                    else {

//                        List users = db.findAll(MemberUser.class);

//                        if (users != null && users.size() != 0) {

//                            MemberUser user = users.get(0);

//                            if (user != null) {

//                                userId = user.getMemberId();

//                            }

//                        }

//                        if (!TextUtils.isEmpty(userId)) {

//                            String user_phone = users.get(0).getUsername();

//                            String user_pswd = users.get(0).getPassword();

//                            login(user_phone, user_pswd);

//                        } else {

//                            Intent intent = new Intent(mContext,

//                                    LoginActivity.class);

//                            mContext.startActivity(intent);

//                            Activity a = (Activity) mContext;

//                            a.finish();

//                        }

//                    }

                }

return false;

            }

});

        // 更新

        builder.setPositiveButton(R.string.soft_update_updatebtn,

                new OnClickListener() {

@Override

                    public void onClick(DialogInterface dialog, int which) {

dialog.dismiss();

                        // 显示下载对话框

                        showDownloadDialog();

                    }

});

        // 稍后更新

        if (!mHashMap.get("forceupdate").equals("0")) {

builder.setNegativeButton(R.string.soft_update_later,

                    new OnClickListener() {

@Override

                        public void onClick(DialogInterface dialog, int which) {

dialog.dismiss();

                            if (listener !=null) {

listener.onTranslateListener();

                            }

//                            List users = db.findAll(MemberUser.class);

//                            if (users != null && users.size() != 0) {

//                                MemberUser user = users.get(0);

//                                if (user != null) {

//                                    userId = user.getMemberId();

//                                }

//                            }

//                            if (!TextUtils.isEmpty(userId)) {

//                                String user_phone = users.get(0).getUsername();

//                                String user_pswd = users.get(0).getPassword();

//                                login(user_phone, user_pswd);

//                            } else {

//                                Intent intent = new Intent(mContext,

//                                        LoginActivity.class);

//                                mContext.startActivity(intent);

//                                Activity a = (Activity) mContext;

//                                a.finish();

//                            }

                        }

});

        }

Dialog noticeDialog = builder.create();

        noticeDialog.setCancelable(true);

//        noticeDialog.setCanceledOnTouchOutside(false);

        noticeDialog.show();

    }

/**

    * 显示软件下载对话框

    */

    private void showDownloadDialog() {

// 构造软件下载对话框

        Builder builder =new Builder(mContext);

        builder.setTitle(R.string.soft_updating);

        // 给下载对话框增加进度条

        final LayoutInflater inflater = LayoutInflater.from(mContext);

        View v = inflater.inflate(R.layout.softupdate_progress, null);

        mProgress = (ProgressBar) v.findViewById(R.id.update_progress);

        builder.setView(v);

        builder.setOnKeyListener(new OnKeyListener() {

@Override

            public boolean onKey(DialogInterface dialog, int keyCode,

                                KeyEvent event) {

if (keyCode == KeyEvent.KEYCODE_BACK

                        && event.getRepeatCount() ==0) {

if (mHashMap.get("forceupdate").equals("0")) {

System.exit(0);

                    }else {

dialog.dismiss();

                    }

}

return false;

            }

});

        // 取消更新

        builder.setNegativeButton(R.string.soft_update_cancel,

                new OnClickListener() {

@Override

                    public void onClick(DialogInterface dialog, int which) {

dialog.dismiss();

                        // 设置取消状态

                        if (mHashMap.get("forceupdate").equals("0")) {

cancelUpdate =true;

                            System.exit(0);

                        }else {

dialog.dismiss();

                            cancelUpdate =true;

                        }

}

});

        mDownloadDialog = builder.create();

        mDownloadDialog.show();

        mDownloadDialog.setCancelable(true);

//        mDownloadDialog.setCanceledOnTouchOutside(false);

        // 现在文件

        downloadApk();

    }

/**

    * 下载apk文件

    */

    private void downloadApk() {

// 启动新线程下载软件

        new downloadApkThread().start();

    }

/**

    * 下载文件线程

    *

    * @author coolszy

    * @date 2012-4-26

    * @blog http://blog.92coding.com

*/

    private class downloadApkThreadextends Thread {

@Override

        public void run() {

try {

// 判断SD卡是否存在,并且是否具有读写权限

                if (Environment.getExternalStorageState().equals(

Environment.MEDIA_MOUNTED)) {

// 获得存储卡的路径

                    String sdpath = Environment.getExternalStorageDirectory()

+"/";

                    mSavePath = sdpath +"download";

                    URL url =new URL(Constant.HOST_URL1 +mHashMap.get("url"));

                    // 创建连接

                    HttpURLConnection conn = (HttpURLConnection) url

.openConnection();

                    conn.setRequestProperty("Accept-Encoding", "identity");

                    conn.connect();

                    // 获取文件大小

                    int length = conn.getContentLength();

                    // 创建输入流

                    InputStream is = conn.getInputStream();

                    File file =new File(mSavePath);

                    // 判断文件目录是否存在

                    if (!file.exists()) {

file.mkdir();

                    }

File apkFile =new File(mSavePath, mHashMap.get("appName"));

                    FileOutputStream fos =new FileOutputStream(apkFile);

                    int count =0;

                    // 缓存

                    byte buf[] =new byte[1024];

                    // 写入到文件中

                    do {

int numread = is.read(buf);

                        count += numread;

                        // 计算进度条位置

                        progress = (int) (((float) count / length) *100);

                        // 更新进度

                        mHandler.sendEmptyMessage(DOWNLOAD);

                        if (numread <=0) {

// 下载完成

                            mHandler.sendEmptyMessage(DOWNLOAD_FINISH);

break;

                        }

// 写入文件

                        fos.write(buf, 0, numread);

                    }while (!cancelUpdate);// 点击取消就停止下载.

                    fos.close();

                    is.close();

                }

}catch (MalformedURLException e) {

e.printStackTrace();

            }catch (IOException e) {

e.printStackTrace();

            }

// 取消下载对话框显示

            mDownloadDialog.dismiss();

        }

}

;

    /**

    * 安装APK文件

    */

    private void installApk() {

File apkfile =new File(mSavePath, mHashMap.get("appName"));

        if (!apkfile.exists()) {

return;

        }

// 通过Intent安装APK文件

        Intent i =new Intent(Intent.ACTION_VIEW);

        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        i.setDataAndType(Uri.parse("file://" + apkfile.toString()),

                "application/vnd.android.package-archive");

        mContext.startActivity(i);

    }

private BroadcastReceivermyNetReceiver =new BroadcastReceiver() {

@Override

        public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {

mConnectivityManager = (ConnectivityManager)activity.getSystemService(Context.CONNECTIVITY_SERVICE);

                netInfo =mConnectivityManager.getActiveNetworkInfo();

                if (netInfo !=null &&netInfo.isAvailable()) {

}else {

// 网络断开

                    List users =db.findAll(MemberUser.class);

                    if (users !=null && users.size() !=0) {

MemberUser user = users.get(0);

                        if (user !=null) {

userId = user.getMemberId();

                        }

}

if ("1".equals(prefUtils.getString(

SharePrefUtils.CHECKSTATE, ""))) {

TipDialog.showDialogStartNewActivity(

activity, R.string.tip,

                                R.string.confirm, R.string.net_no,

                                MainActivity.class);

                    }else {

if ("3".equals(prefUtils.getString(

SharePrefUtils.CHECKSTATE, ""))) {

prefUtils.setBoolean(SharePrefUtils.IS_AUTHEN_TO_AUTHING,false);

                            TipDialog.showDialogStartNewActivity(

activity, R.string.tip,

                                    R.string.confirm, R.string.net_no,

                                    AuthenticationIngActivity.class);

                        }else if ("1".equals(prefUtils.getString(

SharePrefUtils.CHECKSTATE, ""))) {

}else if ("2".equals(prefUtils.getString(

SharePrefUtils.CHECKSTATE, ""))) {

TipDialog.showDialogStartNewActivity(

activity, R.string.tip,

                                    R.string.confirm, R.string.net_no,

                                    AuthenticationActivity.class);

                        }else {

TipDialog.showDialogStartNewActivity(

activity, R.string.tip,

                                    R.string.confirm, R.string.net_no,

                                    LoginActivity.class);

                        }

}

}

}

}

};

    public StringgetSystemCurrentTime() {

SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");// HH:mm:ss

        //获取当前时间

        Date date =new Date(System.currentTimeMillis());

        return simpleDateFormat.format(date);

    }

private ToTranslateActivityListenerlistener;

    public interface ToTranslateActivityListener {

void onTranslateListener();

    }

}

你可能感兴趣的:(Android更新之路)