直接上代码,代码中有详细注释:
1 public class CheckUpdateManager { 2 private static final String TAG = "CheckUpdateManager"; 3 private ProgressDialog mWaitDialog; 4 private Context mContext; 5 private boolean mIsShowDialog; 6 private RequestPermissions mCaller; 7 8 public CheckUpdateManager(Context context, Boolean showWaitingDialog) { 9 this.mContext = context; 10 this.mIsShowDialog = showWaitingDialog; 11 if (mIsShowDialog) { 12 // 创建ProgressDialog对象 13 mWaitDialog = new ProgressDialog(mContext); 14 // 设置进度条风格,风格为圆形,旋转的 15 mWaitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 16 // 设置ProgressDialog 提示信息 17 mWaitDialog.setMessage("正在检查中,请稍后……"); 18 // 设置ProgressDialog 的进度条是否不明确 19 mWaitDialog.setIndeterminate(false); 20 // 设置ProgressDialog可以按返回键取消 21 mWaitDialog.setCancelable(false); 22 } 23 } 24 25 public void setCaller(RequestPermissions caller) { 26 this.mCaller = caller; 27 } 28 29 public void checkUpdate() { 30 if (mIsShowDialog) { 31 mWaitDialog.show(); 32 } 33 // 检查接口更新 34 AsyncHttpClient client = new AsyncHttpClient(); 35 Api api = new Api(); 36 String url = api.version(); 37 client.get(url, new AsyncHttpResponseHandler() { 38 39 @Override 40 public void onSuccess(int statusCode, Header[] headers, 41 byte[] responseString) { 42 // TODO Auto-generated method stub 43 try { 44 //将byte类型转换为String 45 String resp = new String(responseString, "utf-8"); 46 //将String转成InputStream类型 47 InputStream str = new ByteArrayInputStream(resp.getBytes()); 48 //这里调用pull解析的方式 49 final ManifestBean bean = parseXmlPull(str); 50 SharedPreferences sp = mContext.getSharedPreferences( 51 "anhua", Context.MODE_APPEND); 52 int old_dianmian = sp.getInt("old_dianmian", 1);// 服务器端默认版本号为1 53 if (old_dianmian < Integer.parseInt(bean.getVersion())) { 54 // 服务器端版本大于本地版本需要更新 55 if ("0".equals(bean.getQiangzhi())) { 56 new AlertDialog.Builder(mContext) 57 .setTitle("发现新版本") 58 .setMessage("发现新版本,是否更新?") 59 .setNegativeButton( 60 "取消", 61 new DialogInterface.OnClickListener() { 62 @Override 63 public void onClick( 64 DialogInterface dialogInterface, 65 int i) { 66 dialogInterface.dismiss(); 67 } 68 }) 69 .setPositiveButton( 70 "确定", 71 new DialogInterface.OnClickListener() { 72 @Override 73 public void onClick( 74 DialogInterface dialogInterface, 75 int i) { 76 mCaller.call(bean); 77 } 78 }).show(); 79 } else if ("1".equals(bean.getQiangzhi())) { 80 mCaller.call(bean); 81 } 82 } else { 83 if (mIsShowDialog) { 84 new AlertDialog.Builder(mContext).setTitle("温馨提示") 85 .setMessage("已经是最新版本了!") 86 .setPositiveButton("确定", null).show(); 87 } 88 } 89 } catch (UnsupportedEncodingException e) { 90 // TODO Auto-generated catch block 91 e.printStackTrace(); 92 } 93 } 94 95 @Override 96 public void onFinish() { 97 // TODO Auto-generated method stub 98 super.onFinish(); 99 if (mIsShowDialog) {100 mWaitDialog.dismiss();101 }102 }103 104 @Override105 public void onFailure(int arg0, Header[] arg1, byte[] arg2,106 Throwable arg3) {107 // TODO Auto-generated method stub108 if (mIsShowDialog) {109 new AlertDialog.Builder(mContext).setTitle("温馨提示")110 .setMessage("网络异常,无法获取版本信息")111 .setPositiveButton("确定", null).show();112 }113 }114 });115 }116 117 ManifestBean parseXmlPull(InputStream parseStr) {118 {119 ManifestBean bean = null;120 try {121 // 获取XMLPull的解析对象122 XmlPullParserFactory factory = XmlPullParserFactory123 .newInstance();124 XmlPullParser xmlPullParser = factory.newPullParser();125 // 将字节流传送到解析器中126 xmlPullParser.setInput(parseStr, "utf-8");127 128 // xmlPullParser.setInput(new StringReader(parseStr.toString()));129 // 记录下当前的读取事件130 int eventType = xmlPullParser.getEventType();131 // 用来临时记录id和name132 String version = "1";133 String qiangzhi = "0";134 String files = "";135 // 循环读取文档136 while (eventType != XmlPullParser.END_DOCUMENT) {137 // nodeName记录下当前读取的节点的名称138 String nodeName = xmlPullParser.getName();139 switch (eventType) {140 // 根据读取事件来判断执行的操作141 case XmlPullParser.START_DOCUMENT:// 开始文档事件142 // 初始化栈,用来存放读取到的节点的名称,因为该文件中的名称跟id的节点名称是重复的143 // 所以笔者想到了这种办法来控制判断目前读取的是哪一个类型的id和name,当然也有其他方法,读者可以自行试试144 break;145 case XmlPullParser.START_TAG:// 开始元素事件,凡是读取到的是开始节点,该节点名称就入栈146 if ("manifest".equals(xmlPullParser.getName())) { // 取得节点名称并判断147 bean = new ManifestBean();148 } else if ("files".equals(xmlPullParser.getName())) {149 eventType = xmlPullParser.next();150 files = xmlPullParser.getText();151 bean.setFiles(files);152 } else if ("version".equals(xmlPullParser.getName())) {153 eventType = xmlPullParser.next();154 version = xmlPullParser.getText();155 bean.setVersion(version);156 } else if ("qiangzhi".equals(xmlPullParser.getName())) {157 eventType = xmlPullParser.next();158 qiangzhi = xmlPullParser.getText();159 bean.setQiangzhi(qiangzhi);160 } else if ("dianmian".equals(xmlPullParser.getName())) {161 eventType = xmlPullParser.next();162 bean.setDianmian(Integer.parseInt(xmlPullParser163 .getText()));164 }165 break;166 case XmlPullParser.END_TAG:// 结束元素事件,凡是读取到结束节点则对应的开始元素节点出栈167 if (xmlPullParser.getName().equals("manifest")) {168 return bean;169 }170 break;171 default:172 break;173 174 }175 eventType = xmlPullParser.next();// 进入下一个元素并触发相应事件??176 }177 } catch (XmlPullParserException e) {178 e.printStackTrace();179 } catch (IOException e) {180 e.printStackTrace();181 }182 return bean;183 }184 }185 186 public interface RequestPermissions {187 void call(ManifestBean version);188 }189 190 }
下面我来说说我在使用pull解析来自服务器的xml文件时所遇到的问题:
看一下存在问题的版本:
1 public class CheckUpdateManager { 2 private static final String TAG = "CheckUpdateManager"; 3 private ProgressDialog mWaitDialog; 4 private Context mContext; 5 private boolean mIsShowDialog; 6 private RequestPermissions mCaller; 7 8 public CheckUpdateManager(Context context, Boolean showWaitingDialog) { 9 this.mContext = context; 10 this.mIsShowDialog = showWaitingDialog; 11 if (mIsShowDialog) { 12 // 创建ProgressDialog对象 13 mWaitDialog = new ProgressDialog(mContext); 14 // 设置进度条风格,风格为圆形,旋转的 15 mWaitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 16 // 设置ProgressDialog 提示信息 17 mWaitDialog.setMessage("正在检查中,请稍后……"); 18 // 设置ProgressDialog 的进度条是否不明确 19 mWaitDialog.setIndeterminate(false); 20 // 设置ProgressDialog可以按返回键取消 21 mWaitDialog.setCancelable(false); 22 } 23 } 24 25 public void setCaller(RequestPermissions caller) { 26 this.mCaller = caller; 27 } 28 29 public void checkUpdate() { 30 if (mIsShowDialog) { 31 mWaitDialog.show(); 32 } 33 // 检查接口更新 34 AsyncHttpClient client = new AsyncHttpClient(); 35 Api api = new Api(); 36 String url = api.version(); 37 client.get(url, new AsyncHttpResponseHandler() { 38 39 @Override 40 public void onSuccess(int statusCode, Header[] headers, 41 byte[] responseString) { 42 // TODO Auto-generated method stub 43 try { 44 //将byte类型转换为String 45 String resp = new String(responseString, "utf-8"); 46 //将String转成InputStream类型 47 // InputStream str = new ByteArrayInputStream(resp.getBytes()); 48 //这里调用pull解析的方式 49 final ManifestBean bean = parseXmlPull(resp); 50 SharedPreferences sp = mContext.getSharedPreferences( 51 "anhua", Context.MODE_APPEND); 52 int old_dianmian = sp.getInt("old_dianmian", 1);// 服务器端默认版本号为1 53 if (old_dianmian < Integer.parseInt(bean.getVersion())) { 54 // 服务器端版本大于本地版本需要更新 55 if ("0".equals(bean.getQiangzhi())) { 56 new AlertDialog.Builder(mContext) 57 .setTitle("发现新版本") 58 .setMessage("发现新版本,是否更新?") 59 .setNegativeButton( 60 "取消", 61 new DialogInterface.OnClickListener() { 62 @Override 63 public void onClick( 64 DialogInterface dialogInterface, 65 int i) { 66 dialogInterface.dismiss(); 67 } 68 }) 69 .setPositiveButton( 70 "确定", 71 new DialogInterface.OnClickListener() { 72 @Override 73 public void onClick( 74 DialogInterface dialogInterface, 75 int i) { 76 mCaller.call(bean); 77 } 78 }).show(); 79 } else if ("1".equals(bean.getQiangzhi())) { 80 mCaller.call(bean); 81 } 82 } else { 83 if (mIsShowDialog) { 84 new AlertDialog.Builder(mContext).setTitle("温馨提示") 85 .setMessage("已经是最新版本了!") 86 .setPositiveButton("确定", null).show(); 87 } 88 } 89 } catch (UnsupportedEncodingException e) { 90 // TODO Auto-generated catch block 91 e.printStackTrace(); 92 } 93 } 94 95 @Override 96 public void onFinish() { 97 // TODO Auto-generated method stub 98 super.onFinish(); 99 if (mIsShowDialog) {100 mWaitDialog.dismiss();101 }102 }103 104 @Override105 public void onFailure(int arg0, Header[] arg1, byte[] arg2,106 Throwable arg3) {107 // TODO Auto-generated method stub108 if (mIsShowDialog) {109 new AlertDialog.Builder(mContext).setTitle("温馨提示")110 .setMessage("网络异常,无法获取版本信息")111 .setPositiveButton("确定", null).show();112 }113 }114 });115 }116 117 ManifestBean parseXmlPull(String parseStr) {118 {119 ManifestBean bean = null;120 try {121 // 获取XMLPull的解析对象122 XmlPullParserFactory factory = XmlPullParserFactory123 .newInstance();124 XmlPullParser xmlPullParser = factory.newPullParser();125 // 将字节流传送到解析器中126 // xmlPullParser.setInput(parseStr, "utf-8");127 128 xmlPullParser.setInput(new StringReader(parseStr.toString()));129 // 记录下当前的读取事件130 int eventType = xmlPullParser.getEventType();131 // 用来临时记录id和name132 String version = "1";133 String qiangzhi = "0";134 String files = "";135 // 循环读取文档136 while (eventType != XmlPullParser.END_DOCUMENT) {137 // nodeName记录下当前读取的节点的名称138 String nodeName = xmlPullParser.getName();139 switch (eventType) {140 // 根据读取事件来判断执行的操作141 case XmlPullParser.START_DOCUMENT:// 开始文档事件142 // 初始化栈,用来存放读取到的节点的名称,因为该文件中的名称跟id的节点名称是重复的143 // 所以笔者想到了这种办法来控制判断目前读取的是哪一个类型的id和name,当然也有其他方法,读者可以自行试试144 break;145 case XmlPullParser.START_TAG:// 开始元素事件,凡是读取到的是开始节点,该节点名称就入栈146 if ("manifest".equals(xmlPullParser.getName())) { // 取得节点名称并判断147 bean = new ManifestBean();148 } else if ("files".equals(xmlPullParser.getName())) {149 eventType = xmlPullParser.next();150 files = xmlPullParser.getText();151 bean.setFiles(files);152 } else if ("version".equals(xmlPullParser.getName())) {153 eventType = xmlPullParser.next();154 version = xmlPullParser.getText();155 bean.setVersion(version);156 } else if ("qiangzhi".equals(xmlPullParser.getName())) {157 eventType = xmlPullParser.next();158 qiangzhi = xmlPullParser.getText();159 bean.setQiangzhi(qiangzhi);160 } else if ("dianmian".equals(xmlPullParser.getName())) {161 eventType = xmlPullParser.next();162 bean.setDianmian(Integer.parseInt(xmlPullParser163 .getText()));164 }165 break;166 case XmlPullParser.END_TAG:// 结束元素事件,凡是读取到结束节点则对应的开始元素节点出栈167 if (xmlPullParser.getName().equals("manifest")) {168 return bean;169 }170 break;171 default:172 break;173 174 }175 eventType = xmlPullParser.next();// 进入下一个元素并触发相应事件??176 }177 } catch (XmlPullParserException e) {178 e.printStackTrace();179 } catch (IOException e) {180 e.printStackTrace();181 }182 return bean;183 }184 }185 186 public interface RequestPermissions {187 void call(ManifestBean version);188 }
自己在使用Pull解析来自服务器的xml文件时。问题的关键在于以下几行代码:
问题出现在了下面这行代码中:
xmlPullParser.setInput(new StringReader(parseStr.toString()));
正常的使用String类型传入数据时数据可以被读取,但是到了上面的这行代码时就报错。因为个人能力有限,所以具体原因自己没能找出。但是查阅了很多资料后说使用Pull解析时最好将所有数据无论是什么类型,全部转换成InputStream类型,然后再将数据传入Pull中进行解析:
通过上面的InputStream的形式传送到解析器中的数据将不在出现错误,而且以流的形式传入可以设置传入参数的字符集。
总结起来就是:在使用Pull进行解析时,最好的方式是将所有类型的数据都转换成InputStream类型,然后以InputStream的形式进行解析,这样做程序才不会出错。