直接上代码,代码中有详细注释:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 @Override 105 public void onFailure(int arg0, Header[] arg1, byte[] arg2, 106 Throwable arg3) { 107 // TODO Auto-generated method stub 108 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 = XmlPullParserFactory 123 .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和name 132 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(xmlPullParser 163 .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文件时所遇到的问题:
看一下存在问题的版本:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 @Override 105 public void onFailure(int arg0, Header[] arg1, byte[] arg2, 106 Throwable arg3) { 107 // TODO Auto-generated method stub 108 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 = XmlPullParserFactory 123 .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和name 132 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(xmlPullParser 163 .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的形式进行解析,这样做程序才不会出错。