1、本次服务端采用的是HTTP Servlet方式返回json数据
首先建立一个javaweb工程 创建一个Servlet类,代码在doGet中实现
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// response.getWriter().append("Served at:
// ").append(request.getContextPath());
HttpSession session = request.getSession();
String str = request.getParameter("function");
if (str == null) {
str = "main";
}
// 判断session是不是新创建的 减少读取xml频次
if (session.isNew()) {
//System.out.println("session创建成功,session的id是:" + session.getId());
} else {
//System.out.println("服务器已经存在该session了,session的id是:" + session.getId());
String function = session.getAttribute("function").toString();
//判断功能是否一致
if (function.equals(str)) {
String data = session.getAttribute("data").toString();
response.setCharacterEncoding("utf-8");
response.getWriter().append(data);
return;
}
}
session.setAttribute("function", str.toString());
if (str != null && str.equals("你的APP别名")) {//function代表你的APP,支持多个APP版本更新,放在不同的xml里面
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String path = this.getServletContext().getRealPath("version2.xml");
File file = new File(path);
InputStream is = new FileInputStream(file);
org.w3c.dom.Document doc = null;
try {
doc = db.parse(is);
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Element elem = ((org.w3c.dom.Document) doc).getDocumentElement();
JSONObject jsonObjectRoot = new JSONObject();
NodeList appversion = elem.getChildNodes();
if (appversion != null) {
JSONObject jsonObjectUpdate = new JSONObject();
int n = 0;// 更新条目
for (int i = 0; i < appversion.getLength(); i++) {
Node app = appversion.item(i);
for (Node node = app.getFirstChild(); node != null; node = node.getNextSibling()) {
if (app.getNodeName().equals("version")) {
String ver = app.getFirstChild().getNodeValue();
jsonObjectRoot.put("version", ver);
}
if (app.getNodeName().equals("date")) {
String da = app.getFirstChild().getNodeValue();
jsonObjectRoot.put("date", da);
}
if (app.getNodeName().equals("update")) {
n++;
String ud = app.getFirstChild().getNodeValue();
jsonObjectUpdate.put(n + "", ud);
}
if (app.getNodeName().equals("address")) {
String addr = app.getFirstChild().getNodeValue();
jsonObjectRoot.put("address", addr);
}
}
}
jsonObjectRoot.put("update", jsonObjectUpdate);
}
response.setCharacterEncoding("utf-8");
response.getWriter().append(jsonObjectRoot.toString());
session.setAttribute("data", jsonObjectRoot.toString());
} else {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String path = this.getServletContext().getRealPath("version.xml");
File file = new File(path);
InputStream is = new FileInputStream(file);
org.w3c.dom.Document doc = null;
try {
doc = db.parse(is);
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Element elem = ((org.w3c.dom.Document) doc).getDocumentElement();
JSONObject jsonObjectRoot = new JSONObject();
NodeList appversion = elem.getChildNodes();
if (appversion != null) {
JSONObject jsonObjectUpdate = new JSONObject();
int n = 0;// 更新条目
for (int i = 0; i < appversion.getLength(); i++) {
Node app = appversion.item(i);
for (Node node = app.getFirstChild(); node != null; node = node.getNextSibling()) {
if (app.getNodeName().equals("version")) {
String ver = app.getFirstChild().getNodeValue();
jsonObjectRoot.put("version", ver);
}
if (app.getNodeName().equals("date")) {
String da = app.getFirstChild().getNodeValue();
jsonObjectRoot.put("date", da);
}
if (app.getNodeName().equals("update")) {
n++;
String ud = app.getFirstChild().getNodeValue();
jsonObjectUpdate.put(n + "", ud);
}
if (app.getNodeName().equals("address")) {
String addr = app.getFirstChild().getNodeValue();
jsonObjectRoot.put("address", addr);
}
}
}
jsonObjectRoot.put("update", jsonObjectUpdate);
}
response.setCharacterEncoding("utf-8");
response.getWriter().append(jsonObjectRoot.toString());
session.setAttribute("data", jsonObjectRoot.toString());
}
}
将XML文件放在WebContent目录下,结构自己定义,例如我的version.xml如下:
XX系统
1.1.0
2018.02.04
1:XXX优化
2:XXX修改
3:XXX增加
4:XXX其他
http://1.1.1.1:8888/download/YourApp.apk
APP下载地址你可以放到tamcat服务器的一个虚拟下载目录下,搜索tomcat搭建文件下载服务器,很简单的配置。
这样访问地址 http://1.1.1.1:8888/YourWebName/YourServletName?function=你的APP别名 就能得到一个json字符串,例如我的如下:
{"version":"1.1.0","date":"2018.02.04","address":"http://1.1.1.1:8888/download/YourApp.apk","update":{"1":"1:XXX优化","2":"2:XXX修改","3":"3:XXX增加","4":"4:XXX其他"}}
现在web服务器端已经完成,下面进行android端编写
public class AppVersion extends AsyncTask {
private Handler handle;
public String getVersion() {
return version;
}
private String version = "";
public String getUpdate() {
return update;
}
private String update = "";
private String updateURL = "";
static private String updateAPKname = "";
static public String getAPKname() {
return updateAPKname;
}
private boolean bAuto = true;
public AppVersion(Handler handle, boolean bAuto/*自动检查更新、手动检查更新*/) {
this.handle = handle;
this.bAuto = bAuto;
}
@Override
protected StringBuffer doInBackground(String... params) {
String html = "";
try {
//HTTP GET请求
URL url = null;
url = new URL(params[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(2000);
conn.setReadTimeout(1000);
InputStream inStream = conn.getInputStream();
byte[] data = readInputStream(inStream);
html = new String(data, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return new StringBuffer(html);
}
public static byte[] readInputStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
inStream.close();
return outStream.toByteArray();
}
@Override
protected void onPostExecute(StringBuffer result) {
String Html = new String(result);
if (!Html.equals("")) {
try {
JSONObject jsonObjectRoot = new JSONObject(Html);
version = jsonObjectRoot.getString("version");
JSONObject jsonObjectUpdate = jsonObjectRoot.getJSONObject("update");
Iterator keys = jsonObjectUpdate.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
update = update + jsonObjectUpdate.getString(key) + "\r\n\r\n";
}
updateURL = jsonObjectRoot.getString("address");
updateAPKname = updateURL.substring(updateURL.lastIndexOf("/") + 1);
} catch (JSONException e) {
e.printStackTrace();
}
handle.sendEmptyMessage(4);
} else {
if (!bAuto)
Toast.makeText(SearchApplication.getInstance(), "无法获取更新,请检查网络是否畅通", Toast.LENGTH_LONG).show();
}
super.onPostExecute(result);
}
public String getUpdateURL() {
return updateURL;
}
public boolean isbAuto() {
return bAuto;
}
public void setbAuto(boolean bAuto) {
this.bAuto = bAuto;
}
}
二、在MainActivity的onCreate方法中调用
private String path = "http://1.1.1.1:8888/YourWebName/YourServletName?function=你的APP别名";
private AppVersion appVersion
private MyHandler myHandler;
appVersion = new AppVersion(myHandler, true);
appVersion.execute(path);
public class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 4://查询更新返回
try {
if (compareVersion(appVersion.getVersion(), getVersion()) > 0) {
//获得最后版本后,如果服务器版本>当前版本,则显示更新内容 只提示1次,1次后在菜单显示
String csTipUpdate = sp.getString(Constant.csTipUpdate, "0");//获取是否提示过
//如果未提示或者是手动更新的 则显示更新弹窗
if (csTipUpdate.equals("0") || !appVersion.isbAuto()) {
showUpdateDialog(true);//显示更新的弹窗
sp.edit().putString(Constant.csTipUpdate, "1").apply();
}
bUpdate = true;//菜单标志位
btnDowloadMap.setImageResource(R.mipmap.set1);
} else {
Log.d("version:", "没有更新的版本!");
sp.edit().putString(Constant.csTipUpdate, "0").apply();
//获得最后版本后,如果和当前不一致,则显示更新内容
String csVersion = sp.getString(Constant.csVersion, "");
if (csVersion.equals("") || !csVersion.equals(appVersion.getVersion())) {
showUpdateDialog(false);//显示内容
}
sp.edit().putString(Constant.csVersion, appVersion.getVersion()).apply();
if (!appVersion.isbAuto())
Toast.makeText(MainActivity.this, "无可用更新", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
e.printStackTrace();
}
break;
case 8://下载进度
double percent = queryDownloadStatus();
if (progressBar_download != null)
progressBar_download.setProgress((int) percent);
if (percent >= 100)
progressBar_download.setVisibility(View.INVISIBLE);
break;
}
}
}
/**
* 比较版本号的大小,前者大则返回一个正数,后者大返回一个负数,相等则返回0
*
* @param version1
* @param version2
*/
public static int compareVersion(String version1, String version2) throws Exception {
if (version1 == null || version2 == null) {
throw new Exception("compareVersion error:illegal params.");
}
String[] versionArray1 = version1.split("\\.");//注意此处为正则匹配,不能用.;
String[] versionArray2 = version2.split("\\.");
int idx = 0;
int minLength = Math.min(versionArray1.length, versionArray2.length);//取最小长度值
int diff = 0;
while (idx < minLength
&& (diff = versionArray1[idx].length() - versionArray2[idx].length()) == 0//先比较长度
&& (diff = versionArray1[idx].compareTo(versionArray2[idx])) == 0) {//再比较字符
++idx;
}
//如果已经分出大小,则直接返回,如果未分出大小,则再比较位数,有子版本的为大;
diff = (diff != 0) ? diff : versionArray1.length - versionArray2.length;
return diff;
}
/**
* Author:
* CreateTime: 2017/11/15 11:09
* Comment: 获取软件版本号
* Param:
*/
public String getVersion() {
try {
PackageManager manager = this.getPackageManager();
PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
String version = info.versionName;
return version;
} catch (Exception e) {
String s = e.toString();
e.printStackTrace();
return "";
}
}
三、android端下载APK安装
private DownloadManager downloadManager;//下载管理类
private long lastDownloadId;
/**
* Author:
* CreateTime: 2018/1/3 15:39
* Comment: 更新窗口
* Param:
*/
private void showUpdateDialog(boolean b) {
if (b) {
LayoutInflater inflater = LayoutInflater.from(this);
View layout = inflater.inflate(R.layout.pop_needupdate, null);//资源文件不贴出了
final Dialog dialog = new Dialog(MainActivity.this, R.style.dialogstyle);
TextView tv = (TextView) layout.findViewById(R.id.tvupdate);//显示内容的文件控件
final TextView tvdownload = (TextView) layout.findViewById(R.id.btn_download);//下载按钮
TextView tvclose = (TextView) layout.findViewById(R.id.btn_close);//弹窗关闭按钮
tvclose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
tvdownload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Uri uri = Uri.parse(appVersion.getUpdateURL());//更新类获得的APK URL地址
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
request.setVisibleInDownloadsUi(false);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
File rootFile = new File(Environment.getExternalStorageDirectory().getPath() + "/YourAPP/download/");//创建一个下载目录
if (!rootFile.exists()) {
rootFile.mkdirs();
}
request.setDestinationInExternalPublicDir("/YourAPP/download/", getAPKname());//设置下载路径
lastDownloadId = downloadManager.enqueue(request);
app.setLastDownloadId(lastDownloadId);
progressBar_download.setVisibility(View.VISIBLE);//弹窗上的下载进度条
tvdownload.setText("正在下载");
tvdownload.setClickable(false);
final Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
double percent = queryDownloadStatus();
myHandler.sendEmptyMessage(8);
if (percent >= 100) {
timer.cancel();
}
}
};
timer.schedule(task, 100, 500);
}
});
progressBar_download = (CustomLoading) layout.findViewById(R.id.progressBar_download);
String update = appVersion.getUpdate();
tv.setText(update);
dialog.setCancelable(false);
dialog.setContentView(layout);
dialog.show();
Window window = dialog.getWindow();
WindowManager manager = window.getWindowManager();
Display d = manager.getDefaultDisplay();
WindowManager.LayoutParams params = window.getAttributes();
params.width = (int) (d.getWidth() * 0.4);
params.height = LinearLayout.LayoutParams.WRAP_CONTENT;
dialog.getWindow().setAttributes(params);
} else {
LayoutInflater inflater = LayoutInflater.from(this);
View layout = inflater.inflate(R.layout.pop_update, null);//更新后软件第一次进入显示本次更新内容弹窗
final Dialog dialog = new Dialog(MainActivity.this, R.style.dialogstyle);
TextView tv = (TextView) layout.findViewById(R.id.tvupdate);
String update = appVersion.getUpdate();
tv.setText(update);
dialog.setCancelable(true);
dialog.setContentView(layout);
dialog.show();
Window window = dialog.getWindow();
WindowManager manager = window.getWindowManager();
Display d = manager.getDefaultDisplay();
WindowManager.LayoutParams params = window.getAttributes();
params.width = (int) (d.getWidth() * 0.4);
params.height = LinearLayout.LayoutParams.WRAP_CONTENT;
dialog.getWindow().setAttributes(params);
}
}
//你的Application加入代码
public static YourApplication app;
private long lastDownloadId;
public static YourApplication getInstance() {
return app;
}
public long getLastDownloadId() {
return lastDownloadId;
}
public void setLastDownloadId(long lastDownloadId) {
this.lastDownloadId = lastDownloadId;
}
//查询下载进度
private int queryDownloadStatus() {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(lastDownloadId);
Cursor c = downloadManager.query(query);
if (c != null && c.moveToFirst()) {
int fileSizeIdx = c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
int bytesDLIdx = c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
int fileSize = c.getInt(fileSizeIdx);
int bytesDL = c.getInt(bytesDLIdx);
double percent = bytesDL * 100.0 / fileSize;
return (int) percent;
}
return 0;
}
四、加入一个广播,下载完成后安装
广播类
public class CompleteReceiver extends BroadcastReceiver {
private DownloadManager downloadManager;
private long downloadId;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
installApk(context, downloadId);
}
}
private void installApk(Context context, long downloadId) {
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
if (app.getLastDownloadId() == downloadId) {
Uri downloadFileUri = downloadManager.getUriForDownloadedFile(downloadId);
if (getAPKname() != null && !getAPKname().equals("")) {
try {
if (downloadFileUri != null) {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
}
} catch (Exception e) {
Toast.makeText(context, "安装APP出现问题", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(context, "安装APP出现问题", Toast.LENGTH_LONG).show();
}
}
}
}
好的,这里已经结束,学习安卓几个月时间,有不足写的不对的地方敬请见谅!