mainActivity :
package com.example.he.toby.otademo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private TextView textView;
private Button SerxmlOta;
private Button downLoadJar;
Update manager;
private static final int DOWNLOAD = 1;
private static final int DOWNLOAD_FINISH = 2;
private String tag = getClass().getSimpleName();
private static final String MJAR_TEST = "http://192.168.11.39:8080/Uiauto-Jar/first.txt";
Update update ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.textView = (TextView) findViewById(R.id.textView);
update = new Update(MainActivity.this);
// TODO: 2016/5/20
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
UpdateManger mUpdatemanger = new UpdateManger(MainActivity.this);
mUpdatemanger.checkUpdateInfo();
Toast.makeText(getApplicationContext(), "调用updatemanger类", Toast.LENGTH_SHORT).show();
}
});
// TODO: 2016/5/20 版本
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String versionName = getVersionName();
int versionCode = getVersionCode();
Toast.makeText(getApplicationContext(), "VersionName-->" + versionName + "\n" +
"VersionCode-->" + versionCode, Toast.LENGTH_SHORT).show();
textView.setText("APP版本:" + "\nVersionName-->" + versionName + "\n" + "VersionCode-->" + versionCode);
Log.e("MainActivity", "VersionName-->" + versionName+","+"VersionCode-->" + versionCode);
}
});
// TODO: 2016/5/20 serxml解析
this.SerxmlOta = (Button) findViewById(R.id.button3);
SerxmlOta.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "serxml 解析更新xml文件", Toast.LENGTH_SHORT).show();
update.checkUpdate();
}
});
// TODO: 2016/5/20 download JAR
findViewById(R.id._dlj).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(tag, "down load jar ");
update.resultJson();
}
});
}
private String getVersionName() {
String versionname;
try {
PackageManager packageManager = getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(this.getPackageName(), 0);
versionname = packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
versionname = null;
}
return versionname;
}
private int getVersionCode() {
Log.e(tag, "当前的版本调用");
int versionCode;
try {
PackageManager packageManager = getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(this.getPackageName(), 0);
versionCode = packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
versionCode = -1;
}
return versionCode;
}
}
UpdateManger类
package com.example.he.toby.otademo;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
/**
* Created by toby.he on 2016/3/17.
*/
public class UpdateManger {
// 应用程序Context
private Context mContext;
// 提示消息
private String updateMsg = "有最新的软件包,请下载!";
// 下载安装包的网络路径
private String apkUrl = "http://192.168.11.39:8080/Tracer/GigasetTracers1.0.apk";
private Dialog noticeDialog;// 提示有软件更新的对话框
private Dialog downloadDialog;// 下载对话框
private static final String savePath = Environment.getExternalStorageDirectory().toString()+File.separator; // 保存apk的文件夹
private static final String saveFileName = savePath + "UpdateDemoRelease.apk";
// 进度条与通知UI刷新的handler和msg常量
private ProgressBar mProgress;
private static final int DOWN_UPDATE = 1;
private static final int DOWN_OVER = 2;
private int progress;// 当前进度
private Thread downLoadThread; // 下载线程
private boolean interceptFlag = false;// 用户取消下载
private String TAG = getClass().getSimpleName();
HashMap<String, String> mHashMap;
// 通知处理刷新界面的handler
private Handler mHandler = new Handler() {
@SuppressLint("HandlerLeak")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DOWN_UPDATE:
mProgress.setProgress(progress);
break;
case DOWN_OVER:
installApk();
break;
}
super.handleMessage(msg);
}
};
public UpdateManger(Context context) {
this.mContext = context;
}
// 显示更新程序对话框,供主程序调用
public void checkUpdateInfo() {
// if (isUpdate()) {
showNoticeDialog();
// }
// else {
// Toast.makeText(mContext, "不更新", Toast.LENGTH_LONG).show();
// }
}
private int getVersionCode(Context context) {
int versionCode = 0;
try {
versionCode = context.getPackageManager().getPackageInfo("com.example.he.toby.otademo", 0).versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return versionCode;
}
private boolean isUpdate() {
{
int versionCode = getVersionCode(mContext);
//本地的XML更新
// InputStream inStream = ParseXmlService.class
//
// .getResourceAsStream("version.xml");
// InputStream inStream = ParseXmlService.class
// .getClassLoader()
// .getResourceAsStream(
// "version1.xml");
//解析网络xml进行更新软件
URL url = null;
try {
url = new URL("http://192.168.11.39:8080/Tracer/ServerVersion.xml");
Log.e(TAG, "down load ");
} 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);
InputStream is = null;
try {
is = conn.getInputStream();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
ParseXmlService service = new ParseXmlService();
try {
mHashMap = service
.parseXml(is);
} catch (Exception e) {
e.printStackTrace();
}
if (null != mHashMap) {
int serviceCode = Integer.valueOf(mHashMap.get("version"));
if (serviceCode > versionCode) {
Log.e(TAG,"当前版本是version-->"+versionCode+"\n服务server版本是-->"+serviceCode);
return true;
}
}
return false;
}
}
private void showNoticeDialog() {
android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(
mContext);// Builder,可以通过此builder设置改变AleartDialog的默认的主题样式及属性相关信息
builder.setTitle("软件版本更新");
builder.setMessage(updateMsg);
builder.setPositiveButton("下载", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();// 当取消对话框后进行操作一定的代码?取消对话框
showDownloadDialog();
}
});
Log.e("shownoticeD","show noticedialog");
builder.setNegativeButton("以后再说", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
noticeDialog = builder.create();
noticeDialog.show();
}
protected void showDownloadDialog() {
android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(mContext);
builder.setTitle("软件版本更新");
final LayoutInflater inflater = LayoutInflater.from(mContext);
View v = inflater.inflate(R.layout.progress, null);
mProgress = (ProgressBar) v.findViewById(R.id.progress);
builder.setView(v);// 设置对话框的内容为一个View
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
interceptFlag = true;
}
});
downloadDialog = builder.create();
downloadDialog.show();
downloadApk();
}
private void downloadApk() {
downLoadThread = new Thread(mdownApkRunnable);
downLoadThread.start();
}
protected void installApk() {
File apkfile = new File(saveFileName);
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()),
"application/vnd.android.package-archive");// File.toString()会返回路径信息
mContext.startActivity(i);
}
private Runnable mdownApkRunnable = new Runnable() {
@Override
public void run() {
URL url;
try {
url = new URL(apkUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.connect();
int length = conn.getContentLength();
conn.setConnectTimeout(5000);
InputStream ins = conn.getInputStream();
File file = new File(savePath);
if (!file.exists()) {
file.mkdir();
}
String apkFile = saveFileName;
File ApkFile = new File(apkFile);
FileOutputStream outStream = new FileOutputStream(ApkFile);
int count = 0;
byte buf[] = new byte[1024];
do {
int numread = ins.read(buf);
count += numread;
progress = (int) (((float) count / length) * 100);
// 下载进度
mHandler.sendEmptyMessage(DOWN_UPDATE);
if (numread <= 0) {
// 下载完成通知安装
mHandler.sendEmptyMessage(DOWN_OVER);
break;
}
outStream.write(buf, 0, numread);
} while (!interceptFlag);// 点击取消停止下载
outStream.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
Update 类
package com.example.he.toby.otademo;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Created by toby.he on 2016/3/22.
*/
public class Update {
private static final int DOWNLOAD_ING = 1;
private static final int DOWNLOAD_FINISH = 2;
private String TAG = getClass().getSimpleName().toString();
HashMap<String, String> mHashMap;
private String mSavePath;
private int progress;
private boolean cancelUpdate = false;
private Context mContext;
private ProgressBar mProgress;
private Dialog mDownloadDialog;
private static final String PATH = "http://192.168.11.39:8080/Tracer/ServerVersion.html";
private String mVersion_code;
private String mVersion_name;
private String mVersion_desc;
private String mVersion_path;
// TODO: 2016/4/12 jar文件地址
private String mJar_name;
private String mJar_url;
public static final String MJAR_PATH = "http://192.168.11.39:8080/Uiauto-Jar/test.html";
String[] nameList=null ;
// 通知处理刷新界面的handler
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case DOWNLOAD_ING:
mProgress.setProgress(progress);
break;
case DOWNLOAD_FINISH:
// 隐藏当前下载对话框
mDownloadDialog.dismiss();
//安装APK
installApk();
break;
default:
break;
}
}
};
// TODO: 2016/4/12 获取版本
private Handler mGetVersion = new Handler() {
public void handleMessage(Message msg) {
JSONObject jsonObject = (JSONObject) msg.obj;
System.out.println(jsonObject.toString());
try {
mVersion_code = jsonObject.getString("version_code");
mVersion_name = jsonObject.getString("version_name");
mVersion_desc = jsonObject.getString("version_desc");
mVersion_path = jsonObject.getString("version_path");
if (isUpdate()) {
Toast.makeText(mContext, "需要更新", Toast.LENGTH_SHORT).show();
// 显示提示更新对话框
showNoticeDialog();
} else {
Toast.makeText(mContext, "已是最新版本", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
public Update(Context context) {
this.mContext = context;
Log.e(TAG, "update");
}
//检查更新
public void checkUpdate() {
RequestQueue requestQueue = Volley.newRequestQueue(mContext);
JsonObjectRequest request = new JsonObjectRequest(PATH, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject jsonObject) {
Message msg = Message.obtain();
msg.obj = jsonObject;
mGetVersion.sendMessage(msg);
Log.e(TAG, jsonObject.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Log.e(TAG, volleyError.toString());
}
});
requestQueue.add(request);
}
public static int getLineNumber(Exception e){
StackTraceElement[] trace =e.getStackTrace();
if(trace==null||trace.length==0) return -1; //
return trace[0].getLineNumber();
}
// TODO: 2016/4/12 检测jar文件
public void checkJar()
{
try {
String result = readParse(mJar_url);
Toast.makeText(mContext,"result-->"+result,Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
Handler mGetJarHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
JSONArray jsonArray = null;
ArrayList<HashMap<String, String>> list = new ArrayList<>();
try {
jsonArray = new JSONArray(msg.obj);
} catch (JSONException e) {
e.printStackTrace();
}
// JSONObject jsonObject = (JSONObject) msg.obj;
// System.out.println(jsonObject.toString());
for (int i = 0 ; i <jsonArray.length();i++)
{
try {
JSONObject jsonObject = jsonArray.getJSONObject(i);
} catch (JSONException e) {
e.printStackTrace();
}
HashMap<String,String> map = new HashMap<String,String>();
map.put("NAME",mJar_name);
map.put("URL", mJar_url);
list.add(map);
}
Iterator<HashMap<String, String>> it = list.iterator();
StringBuffer strbf = new StringBuffer();
while (it.hasNext()) {
HashMap<String, String> ma = it.next();
// strbf.append(ma.)
}
}
};
// TODO: 2016/4/12 多选对话框
private void MultiChoiceDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setIcon(R.mipmap.ic_launcher);
builder.setTitle("所有的JAR包");
// final String[] hobbies = {"篮球", "足球", "网球", "斯诺克"};
// 设置一个单项选择下拉框
/**
* 第一个参数指定我们要显示的一组下拉多选框的数据集合
* 第二个参数代表哪几个选项被选择,如果是null,则表示一个都不选择,如果希望指定哪一个多选选项框被选择,
* 需要传递一个boolean[]数组进去,其长度要和第一个参数的长度相同,例如 {true, false, false, true};
* 第三个参数给每一个多选项绑定一个监听器
*/
builder.setMultiChoiceItems(nameList, null, new DialogInterface.OnMultiChoiceClickListener()
{
StringBuffer sb = new StringBuffer(100);
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked)
{
if(isChecked)
{
sb.append(nameList[which] + ", ");
}
// Toast.makeText(mContext, "爱好为:" + sb.toString(), Toast.LENGTH_SHORT).show();
}
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
Log.e(TAG, "sure");
// Toast.makeText(mContext,"这里添加要下载执行",Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
}
});
builder.show();
}
/*
* 与本地版本比较判断是否需要更新
*/
public boolean isUpdate() {
int serverVersion = Integer.parseInt(mVersion_code);
int localVersion = 1;
localVersion = getVersionCode(mContext);
if (serverVersion > localVersion) {
Log.e(TAG, "当前版本是version-->" + localVersion + "\n服务server版本是-->" + serverVersion);
return true;
}
return false;
}
private int getVersionCode(Context context) {
int versionCode = 0;
try {
versionCode = context.getPackageManager().getPackageInfo("com.example.he.toby.otademo", 0).versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return versionCode;
}
private void showNoticeDialog() {
Log.e(TAG, "showNoticeDialog()");
AlertDialog.Builder builder = new Builder(mContext);
builder.setTitle("提示");
String msg = "有软件更新,要下载更新么 ?\n" + mVersion_desc;
builder.setMessage(msg);
builder.setPositiveButton("UPDATE", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//隐藏对话框
dialog.dismiss();
//显示下载对话框
showDownloadDialog();
}
});
builder.setNegativeButton("Cancle", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
private void installApk() {
File apkfile = new File(mSavePath, mVersion_name);
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
mContext.startActivity(i);
}
private void showDownloadDialog() {
Builder builder = new Builder(
mContext);
builder.setTitle("更新中");
final LayoutInflater inflater = LayoutInflater.from(mContext);
View v = inflater.inflate(R.layout.progress, null);
mProgress = (ProgressBar) v.findViewById(R.id.progress);
builder.setView(v);
builder.setNegativeButton(R.string.soft_update_cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
cancelUpdate = true;
}
});
mDownloadDialog = builder.create();
mDownloadDialog.show();
// TODO: 2016/3/22 下载
downloadApk();
}
private void downloadApk() {
new downloadApkThread().start();
}
private class downloadApkThread extends Thread {
@Override
public void run() {
Log.e(TAG, " Will Downloadapk");
try {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String sdpath = Environment.getExternalStorageDirectory() + "/";
mSavePath = sdpath + "download";
File file = new File(mSavePath);
if (!file.exists()) {
file.mkdir();
}
// TODO: 2016/4/1 下载
HttpURLConnection conn = (HttpURLConnection) new URL(mVersion_path).openConnection();
conn.connect();
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
File apkFile = new File(mSavePath, mVersion_name);
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_ING);
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();
}
}
/**
* 从指定的URL中获取数组
* @param urlPath
* @return
* @throws Exception
*/
public String readParse(String urlPath) throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int len = 0;
URL url = new URL(urlPath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStream inStream = conn.getInputStream();
while ((len = inStream.read(data)) != -1) {
outStream.write(data, 0, len);
}
inStream.close();
return new String((outStream.toByteArray()));//通过out.Stream.toByteArray获取到写的数据
}
/**
* 解析
*
* @throws JSONException
*/
private ArrayList<HashMap<String, Object>> Analysis(String jsonStr)
throws JSONException {
/******************* 解析 ***********************/
JSONArray jsonArray = null;
Log.d(TAG, "后:" + jsonStr);
// 初始化list数组对象
ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
//转化成 JSONObject类
JSONObject js = new JSONObject(jsonStr);
if (js.has("TestJar"))
{
jsonArray = js.getJSONArray("TestJar");
if (jsonArray.length()>0)
{
for (int i = 0; i<jsonArray.length();i++)
{
JSONObject jsonOj = jsonArray.getJSONObject(i);
String NAME = "";
String URL = "";
if(jsonOj.has("NAME")){
NAME = jsonOj.getString("NAME");
}
if(jsonOj.has("URL")){
URL = jsonOj.getString("URL");
}
// 初始化map数组对象
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("NAME", NAME);
map.put("URL", URL);
list.add(map);
Log.d(TAG, "SearchResultJson>>>" + " NAME=" + NAME + " URL=" + URL);
System.out.println("name:" + NAME);
}
}
}
// nameList = new String[jsonArray.length()];
return list;
}
/**
* readParse(String)从服务器端获取数据
* Analysis(String)解析json数据
*/
ArrayList<HashMap<String, Object>> allData ;
String jsonObject = null;
public void resultJson() {
new Thread(new Runnable() {
@Override
public void run() {
try {
jsonObject = readParse(MJAR_PATH);
Log.e(TAG, "从服务器中读取到的数据:\n"+jsonObject);
allData = Analysis(jsonObject);
Iterator<HashMap<String, Object>> it = allData.iterator();
while (it.hasNext()) {
Map<String, Object> ma = it.next();
Log.e("name&&url","NAME: "+ma.get("NAME")+",URL:"+ma.get("URL")+"\n");
}
// MultiChoiceDialog();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// try {
// allData = Analysis(readParse(MJAR_PATH));
}
}
xml文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="UpdateManger_OTA"
android:id="@+id/button"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="版本code"
android:id="@+id/button2"
android:layout_below="@+id/button"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignRight="@+id/button"
android:layout_alignEnd="@+id/button" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView"
android:layout_below="@+id/button2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Server-xml解析-OTA"
android:id="@+id/button3"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DownLoadJar从服务器上下载"
android:id="@+id/_dlj"
android:layout_below="@+id/button3"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignRight="@+id/button3"
android:layout_alignEnd="@+id/button3" />
</RelativeLayout>