当前位置:   article > 正文

android 实现版本更新和下载安装_android apk版本下载更新插件

android apk版本下载更新插件

在开发android APP时候 经常用到的一个技术 就是检查目前手机端APP的版本,如果手机端版本较低 ,就会实现下载新版本和安装。

实现的过程的大体思路是这样的:

首先得到本地的版本,其次向服务器发送请求,参数为当前的版本号,服务器会比较服务端的版本号,返回客户端一个对象,对象中包含是否需要更新(),比较两个版本,如果不一致,则客户端从服务器下载新的版本并且安装,这里下载和安装使用了第三方插件afinal_0.5.1_bin.jar 该插件能够实现下载和安装。

由于我是刚进入android的开发,并且第一次写博文,不足之处,请大家原谅和多多指点。

首先第一步不必多说,导入afinal_0.5.1_bin.jar包

第二步,因为为了提高效果,会使用Notification提示栏,这里先准备好他的布局。notification_layout_big.xml 代码如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" 
    >


    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_launcher" />


    <RelativeLayout
        
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/imageView1"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="20dp"
         >

        <TextView
            android:id="@+id/tv_versionUpdate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="涂吧版本更新,点击下载"
            android:textColor="@color/white"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/tv_versionAbstract"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_versionUpdate"
            android:text="2222"
            android:textSize="16sp" />
    </RelativeLayout>
</RelativeLayout>

然后就是其他类的代码了,首先是Update类,功能是获得当前版本

package com.example.update;


import java.util.ArrayList;
import java.util.List;


import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;


import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.widget.Toast;


import com.example.update.UpdateAsyncTask.UpdateListener;


public class Update {

/*
* 服务器需求,定义两个借口
* 接口一:
* 本地上传当前版本号以后,返回是否需要更新
* 如果需要更新,则返回更新的地址,及新版本的描述
*      接口参数
* oldVersion  
* 返回结果
* address
* abstract

* 接口二:新版本apk的下载地址
*   loadUrl

*/

/**
* 检测当前版本和服务器版本是否相同
*/
String versionUrl;   //检查版本名的url,即接口一
String curVersion;   //当前版本名

private void checkVersion(final Context context){
int versioncode ;
try {
PackageManager manager = context.getPackageManager();
PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
curVersion = info.versionName;
versioncode = info.versionCode;
UpdateNotificationReceiver.VersionName = curVersion;
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

List<NameValuePair> params = new  ArrayList<NameValuePair>(); 
params.add(new BasicNameValuePair("oldVersion",curVersion));
UpdateAsyncTask task = new UpdateAsyncTask(context, versionUrl, new UpdateListener() {

@Override
public VersionBean parseData(String data) {
//自定义解析
VersionBean bean = new VersionBean();
try {
JSONObject updateObj = new JSONObject(data);
bean.setVersion_address(updateObj.getString("address"));
bean.setVersion_abstract(updateObj.getString("abstract"));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bean;
}

@Override
public void onLoadDataSuccess(VersionBean object) {
//重新存储
VersionBean bean = (VersionBean) object;

//这里是需要更新时候需要需要发送广播在广播中启动服务
Intent intent = new Intent(context,UpdateNotificationReceiver.class);
intent.putExtra("address", bean.getVersion_address());
intent.putExtra("abstract", bean.getVersion_abstract());
context.sendBroadcast(intent);
}

@Override
public void onLoadDataFailed(String tag) {
Toast.makeText(context, "当前已是最新版本", Toast.LENGTH_SHORT).show();

}
}, params);
task.execute(VersionBean.class);

}
}

这个类使用时需要将checkVersion()方法改为公有,这样方便在事件处理中调用,这里大家根据需要改吧,下面就是UpdateAsyncTask 类:

package com.example.update;


import java.io.UnsupportedEncodingException;
import java.util.List;


import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import android.content.Context;
import android.os.AsyncTask;
import android.text.TextUtils;


public class UpdateAsyncTask extends AsyncTask<Class, Integer, VersionBean>{


private Context mContext;
private String mUrl;
private UpdateListener mListener;
private List<NameValuePair> mList;




public UpdateAsyncTask(Context context,String url,UpdateListener listener,List<NameValuePair> list){
this.mContext = context;
this.mUrl = url;
this.mListener = listener;
this.mList = list;
}




@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}


@Override
protected VersionBean doInBackground(Class... arg0) {
try {
BasicHttpParams bhp = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(bhp, 4*1000);
HttpConnectionParams.setSoTimeout(bhp, 4*1000);
DefaultHttpClient dhClient = new DefaultHttpClient(bhp);
HttpPost post = new HttpPost(this.mUrl);
post.setEntity(new UrlEncodedFormEntity(mList,HTTP.UTF_8));
HttpResponse response = dhClient.execute(post);
//result格式,Json数据,包含 state 和 data两项
String result = EntityUtils.toString(response.getEntity());
JSONObject jsonObj = new JSONObject(result);
String state = jsonObj.getString("state");
String data = jsonObj.getString("data");
//表示没有更新
if("0".equals(state)){
return null;
}
//有要更新的包
else{
if(TextUtils.isEmpty(data)){
return null;
}else{
VersionBean bean = mListener.parseData(data);
return bean;
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}


@Override
protected void onPostExecute(VersionBean bean) {
// TODO Auto-generated method stub
super.onPostExecute(bean);
if(bean == null){
mListener.onLoadDataFailed("没有要更新的包");
}else{
mListener.onLoadDataSuccess(bean);
}
}

public interface UpdateListener{
public void onLoadDataSuccess(VersionBean object);
public void onLoadDataFailed(String tag);
public VersionBean parseData(String data);
}

}
接下来是接收广播类,在该类会启动服务并且创建提示栏

package com.example.update;


import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.RemoteViews;


import com.example.graphics.R;


public class UpdateNotificationReceiver extends BroadcastReceiver{


public static int notId = 11;   //与更新服务里的notId要不同,下载
public static String LoadAddress = "http://baidu.com"; //默认的apk下载网址
public static String VersionName = "1.2.0"; //新版本的版本名


@Override
public void onReceive(Context context, Intent intent) {
LoadAddress = intent.getStringExtra("address");
String abst= intent.getStringExtra("abstract");
Intent loadIntent = new Intent(context,UpdateNotificationService.class);
PendingIntent pi = PendingIntent.getService(context, 0,loadIntent, 0);


Notification foregroundNote;
Bitmap bigIcon = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
RemoteViews bigView = new RemoteViews(context.getApplicationContext().getPackageName(),
R.layout.notification_layout_big);
bigView.setTextViewText(R.id.tv_versionAbstract, absts);
Notification.Builder mNotifyBuilder = new Notification.Builder(context);
foregroundNote = mNotifyBuilder.setContentTitle("某某版本更新,点击下载")
.setContentText("某某版本更新")
.setSmallIcon(R.drawable.ic_launcher)
.setTicker("某某版本更新")
.setLargeIcon(bigIcon)
.build();
foregroundNote.bigContentView = bigView;
foregroundNote.setLatestEventInfo(context, "某某版本更新,点击下载", abst, pi);
NotificationManager mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotifyManager.notify(notId, foregroundNote);
}


}


下载要在服务中进行,服务类的代码如下

package com.example.update;


import java.io.File;


import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;


import com.example.graphics.R;


public class UpdateNotificationService extends Service{


private String DownloadUrl ; //下载地址
private String loadApkPath ; //apk文件路径
private String Path ;    //APK保存路径
private String apkName;   //应用名称
private  NotificationManager notManager ;
private  Notification notification ;
private  int notId = 12;  //与更新广播里的notId要不同


@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}




@Override
public int onStartCommand(Intent intent, int flags, int startId) {
DownloadUrl = UpdateNotificationReceiver.LoadAddress;
apkName = "taobao"+UpdateNotificationReceiver.VersionName+".apk";
Path = Environment.getExternalStorageDirectory()+"/data/data/Apk";
File file2 = new File(Path);
if(!file2.exists())  
file2.mkdirs();
loadApkPath = Path + apkName;
File file = new File(loadApkPath);
if(file.exists()){
file.delete();
}
notManager = (NotificationManager) UpdateNotificationService.this.getSystemService(Context.NOTIFICATION_SERVICE);
notManager.cancel(UpdateNotificationReceiver.notId);   //取消广播里,点击下载的通知
notification = new Notification();
notification.icon = R.drawable.ic_launcher;
notification.setLatestEventInfo(this, "某某版本更新,下载中", "0%", null);
notManager.notify(notId,notification);
downLoadApk();   //开始下载apk
return super.onStartCommand(intent, flags, startId);
}


/**
* 下载apk,使用afinal框架,注意导入jar包

*/
protected void downLoadApk() {
FinalHttp fh = new FinalHttp();
fh.download(DownloadUrl, loadApkPath,
new AjaxCallBack<File>() {


/** 
* 下载完成
* @param  t  apk文件
*/
@Override
public void onSuccess(File t) {
notManager.cancel(notId);
if(t.exists() && t.length() > 0){
//启动安装
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.fromFile(t),
"application/vnd.android.package-archive");
startActivity(intent);
}
super.onSuccess(t);
}


/**
* 下载中
* @param count  文件总长度
* @param current  当前下载长度
*/
@Override
public void onLoading(long count, long current) {
//更新下载进度
notification.setLatestEventInfo(NotificationService.this, "某某版本更新", "下载进度 "+(int)(((double)current/count)*100)+"%", null);
notManager.notify(notId,notification);
super.onLoading(count, current);
}
});
}


}
现在代码基本已经全了,但是不要忘了,方法中我们经常会用到一个对象,我们的对象还没有创建,接下来是对象类

package com.example.update;


import java.io.Serializable;


public class VersionBean implements Serializable{

private String version_address;

private String version_abstract;

public VersionBean(){}

public VersionBean(String vAddress,String vAbstract){
this.version_address = vAddress;
this.version_abstract = vAbstract;
}

public String getVersion_address() {
return version_address;
}
public void setVersion_address(String version_address) {
this.version_address = version_address;
}
public String getVersion_abstract() {
return version_abstract;
}
public void setVersion_abstract(String version_abstract) {
this.version_abstract = version_abstract;
}


}

写到这里,主要类已经写完了,但是是不是觉得还缺点什么?如果你代码只是这样写,在实际操作中,会无法实现现在,因为我们的服务和广播还没有注册,否则android不会启动服务和广播,这里注册的代码就不写了,大家自己写吧。

由于第一次写博文,水平有限,这些代码也是别人教我的,感谢团队中不断教我的同事们,也希望我这篇简答的代码对大家有用,最后是源码的下载路径:

http://pan.baidu.com/s/1hq2BSG0。希望大家多动提出宝贵意见

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/861162
推荐阅读
相关标签
  

闽ICP备14008679号