来自Google官方的有关Android平台的JSON解析示例,如果远程服务器使用了json而不是xml的数据提供,在Android平台上已经内置的org.json包可以很方便的实现手机客户端的解析处理。下面一起分析下这个例子,帮助Android开发者需要有关HTTP通讯、正则表达式、JSON解析、appWidget开发的一些知识。
示例一
- public class WordWidget extends AppWidgetProvider { // appWidget
- @Override
- public void onUpdate(Context context, AppWidgetManager appWidgetManager,
- int[] appWidgetIds) {
- context.startService(new Intent(context, UpdateService.class)); // 避免ANR,所以Widget中开了个服务
- }
- public static class UpdateService extends Service {
- @Override
- public void onStart(Intent intent, int startId) {
- // Build the widget update for today
- RemoteViews updateViews = buildUpdate(this);
- ComponentName thisWidget = new ComponentName(this, WordWidget.class);
- AppWidgetManager manager = AppWidgetManager.getInstance(this);
- manager.updateAppWidget(thisWidget, updateViews);
- }
- public RemoteViews buildUpdate(Context context) {
- // Pick out month names from resources
- Resources res = context.getResources();
- String[] monthNames = res.getStringArray(R.array.month_names);
- Time today = new Time();
- today.setToNow();
- String pageName = res.getString(R.string.template_wotd_title,
- monthNames[today.month], today.monthDay);
- RemoteViews updateViews = null;
- String pageContent = "";
- try {
- SimpleWikiHelper.prepareUserAgent(context);
- pageContent = SimpleWikiHelper.getPageContent(pageName, false);
- } catch (ApiException e) {
- Log.e("WordWidget", "Couldn't contact API", e);
- } catch (ParseException e) {
- Log.e("WordWidget", "Couldn't parse API response", e);
- }
- Pattern pattern = Pattern
- .compile(SimpleWikiHelper.WORD_OF_DAY_REGEX); // 正则表达式处理,有关定义见下面的SimpleWikiHelper类
- Matcher matcher = pattern.matcher(pageContent);
- if (matcher.find()) {
- updateViews = new RemoteViews(context.getPackageName(),
- R.layout.widget_word);
- String wordTitle = matcher.group(1);
- updateViews.setTextViewText(R.id.word_title, wordTitle);
- updateViews.setTextViewText(R.id.word_type, matcher.group(2));
- updateViews.setTextViewText(R.id.definition, matcher.group(3)
- .trim());
- String definePage = res.getString(R.string.template_define_url,
- Uri.encode(wordTitle));
- Intent defineIntent = new Intent(Intent.ACTION_VIEW,
- Uri.parse(definePage)); // 这里是打开相应的网页,所以Uri是http的url,action是view即打开web浏览器
- PendingIntent pendingIntent = PendingIntent.getActivity(
- context, 0 /* no requestCode */, defineIntent, 0 /*
- * no
- * flags
- */);
- updateViews.setOnClickPendingIntent(R.id.widget, pendingIntent); // 单击Widget打开Activity
- } else {
- updateViews = new RemoteViews(context.getPackageName(),
- R.layout.widget_message);
- CharSequence errorMessage = context
- .getText(R.string.widget_error);
- updateViews.setTextViewText(R.id.message, errorMessage);
- }
- return updateViews;
- }
- @Override
- public IBinder onBind(Intent intent) {
- // We don't need to bind to this service
- return null;
- }
- }
- }
- public class SimpleWikiHelper {
- private static final String TAG = "SimpleWikiHelper";
- public static final String WORD_OF_DAY_REGEX = "(?s)\\{\\{wotd\\|(.+?)\\|(.+?)\\|([^\\|]+).*?\\}\\}";
- private static final String WIKTIONARY_PAGE = "http://en.wiktionary.org/w/api.php?action=query&prop=revisions&titles=%s&
- + "rvprop=content&format=json%s";
- private static final String WIKTIONARY_EXPAND_TEMPLATES = "&rvexpandtemplates=true";
- private static final int HTTP_STATUS_OK = 200;
- private static byte[] sBuffer = new byte[512];
- private static String sUserAgent = null;
- public static class ApiException extends Exception {
- public ApiException(String detailMessage, Throwable throwable) {
- super(detailMessage, throwable);
- }
- public ApiException(String detailMessage) {
- super(detailMessage);
- }
- }
- public static class ParseException extends Exception {
- public ParseException(String detailMessage, Throwable throwable) {
- super(detailMessage, throwable);
- }
- }
- public static void prepareUserAgent(Context context) {
- try {
- // Read package name and version number from manifest
- PackageManager manager = context.getPackageManager();
- PackageInfo info = manager.getPackageInfo(context.getPackageName(),
- 0);
- sUserAgent = String.format(
- context.getString(R.string.template_user_agent),
- info.packageName, info.versionName);
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Couldn't find package information in PackageManager", e);
- }
- }
- public static String getPageContent(String title, boolean expandTemplates)
- throws ApiException, ParseException {
- String encodedTitle = Uri.encode(title);
- String expandClause = expandTemplates ? WIKTIONARY_EXPAND_TEMPLATES
- : "";
- String content = getUrlContent(String.format(WIKTIONARY_PAGE,
- encodedTitle, expandClause));
- try {
- JSONObject response = new JSONObject(content);
- JSONObject query = response.getJSONObject("query");
- JSONObject pages = query.getJSONObject("pages");
- JSONObject page = pages.getJSONObject((String) pages.keys().next());
- JSONArray revisions = page.getJSONArray("revisions");
- JSONObject revision = revisions.getJSONObject(0);
- return revision.getString("*");
- } catch (JSONException e) {
- throw new ParseException("Problem parsing API response", e);
- }
- }
- protected static synchronized String getUrlContent(String url)
- throws ApiException {
- if (sUserAgent == null) {
- throw new ApiException("User-Agent string must be prepared");
- }
- HttpClient client = new DefaultHttpClient();
- HttpGet request = new HttpGet(url);
- request.setHeader("User-Agent", sUserAgent); // 设置客户端标识
- try {
- HttpResponse response = client.execute(request);
- StatusLine status = response.getStatusLine();
- if (status.getStatusCode() != HTTP_STATUS_OK) {
- throw new ApiException("Invalid response from server:
- + status.toString());
- }
- HttpEntity entity = response.getEntity();
- InputStream inputStream = entity.getContent(); // 获取HTTP返回的数据流
- ByteArrayOutputStream content = new ByteArrayOutputStream();
- int readBytes = 0;
- while ((readBytes = inputStream.read(sBuffer)) != -1) {
- content.write(sBuffer, 0, readBytes); // 转化为字节数组流
- }
- return new String(content.toByteArray()); // 从字节数组构建String
- } catch (IOException e) {
- throw new ApiException("Problem communicating with API", e);
- }
- }
- }
示例二
- public class JSON {
- /**
- * 获取"数组形式"的JSON数据, 数据形式:[{"id":1,"name":"小猪"},{"id":2,"name":"小猫"}]
- *
- * @param path
- * 网页路径
- * @return 返回List
- * @throws Exception
- */
- public static List<Map<String, String>> getJSONArray(String path)
- throws Exception {
- String json = null;
- List<Map<String, String>> list = new ArrayList<Map<String, String>>();
- Map<String, String> map = null;
- URL url = new URL(path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 利用HttpURLConnection对象,我们可以从网络中获取网页数据.
- conn.setConnectTimeout(5 * 1000); // 单位是毫秒,设置超时时间为5秒
- conn.setRequestMethod("GET"); // HttpURLConnection是通过HTTP协议请求path路径的,所以需要设置请求方式,可以不设置,因为默认为GET
- if (conn.getResponseCode() == 200) {// 判断请求码是否是200码,否则失败
- InputStream is = conn.getInputStream(); // 获取输入流
- byte[] data = readStream(is); // 把输入流转换成字符数组
- json = new String(data); // 把字符数组转换成字符串
- // 数据形式:[{"id":1,"name":"小猪","age":22},{"id":2,"name":"小猫","age":23}]
- JSONArray jsonArray = new JSONArray(json); // 数据直接为一个数组形式,所以可以直接
- // 用android提供的框架JSONArray读取JSON数据,转换成Array
- for (int i = 0; i < jsonArray.length(); i++) {
- JSONObject item = jsonArray.getJSONObject(i); // 每条记录又由几个Object对象组成
- int id = item.getInt("id"); // 获取对象对应的值
- String name = item.getString("name");
- map = new HashMap<String, String>(); // 存放到MAP里面
- map.put("id", id + "");
- map.put("name", name);
- list.add(map);
- }
- }
- // ***********测试数据******************
- for (Map<String, String> list2 : list) {
- String id = list2.get("id");
- String name = list2.get("name");
- Log.i("abc", "id:" + id + " | name:" + name);
- }
- return list;
- }
- /**
- * 获取"对象形式"的JSON数据,
- * 数据形式:{"total":2,"success":true,"arrayData":[{"id":1,"name"
- * :"小猪"},{"id":2,"name":"小猫"}]}
- *
- * @param path
- * 网页路径
- * @return 返回List
- * @throws Exception
- */
- public static List<Map<String, String>> getJSONObject(String path)
- throws Exception {
- List<Map<String, String>> list = new ArrayList<Map<String, String>>();
- Map<String, String> map = null;
- URL url = new URL(path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 利用HttpURLConnection对象,我们可以从网络中获取网页数据.
- conn.setConnectTimeout(5 * 1000); // 单位是毫秒,设置超时时间为5秒
- conn.setRequestMethod("GET"); // HttpURLConnection是通过HTTP协议请求path路径的,所以需要设置请求方式,可以不设置,因为默认为GET
- if (conn.getResponseCode() == 200) {// 判断请求码是否是200码,否则失败
- InputStream is = conn.getInputStream(); // 获取输入流
- byte[] data = readStream(is); // 把输入流转换成字符数组
- String json = new String(data); // 把字符数组转换成字符串
- // 数据形式:{"total":2,"success":true,"arrayData":[{"id":1,"name":"小猪"},{"id":2,"name":"小猫"}]}
- JSONObject jsonObject = new JSONObject(json); // 返回的数据形式是一个Object类型,所以可以直接转换成一个Object
- int total = jsonObject.getInt("total");
- Boolean success = jsonObject.getBoolean("success");
- Log.i("abc", "total:" + total + " | success:" + success); // 测试数据
- JSONArray jsonArray = jsonObject.getJSONArray("arrayData");// 里面有一个数组数据,可以用getJSONArray获取数组
- for (int i = 0; i < jsonArray.length(); i++) {
- JSONObject item = jsonArray.getJSONObject(i); // 得到每个对象
- int id = item.getInt("id"); // 获取对象对应的值
- String name = item.getString("name");
- map = new HashMap<String, String>(); // 存放到MAP里面
- map.put("id", id + "");
- map.put("name", name);
- list.add(map);
- }
- }
- // ***********测试数据******************
- for (Map<String, String> list2 : list) {
- String id = list2.get("id");
- String name = list2.get("name");
- Log.i("abc", "id:" + id + " | name:" + name);
- }
- return list;
- }
- /**
- * 获取类型复杂的JSON数据 数据形式: {"name":"小猪", "age":23,
- * "content":{"questionsTotal":2, "questions": [ { "question":
- * "what's your name?", "answer": "小猪"},{"question": "what's your age",
- * "answer": "23"}] } }
- *
- * @param path
- * 网页路径
- * @return 返回List
- * @throws Exception
- */
- public static List<Map<String, String>> getJSON(String path)
- throws Exception {
- List<Map<String, String>> list = new ArrayList<Map<String, String>>();
- Map<String, String> map = null;
- URL url = new URL(path);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 利用HttpURLConnection对象,我们可以从网络中获取网页数据.
- conn.setConnectTimeout(5 * 1000); // 单位是毫秒,设置超时时间为5秒
- conn.setRequestMethod("GET"); // HttpURLConnection是通过HTTP协议请求path路径的,所以需要设置请求方式,可以不设置,因为默认为GET
- if (conn.getResponseCode() == 200) {// 判断请求码是否是200码,否则失败
- InputStream is = conn.getInputStream(); // 获取输入流
- byte[] data = readStream(is); // 把输入流转换成字符数组
- String json = new String(data); // 把字符数组转换成字符串
- /*
- * 数据形式: {"name":"小猪", "age":23, "content":{"questionsTotal":2,
- * "questions": [ { "question": "what's your name?", "answer":
- * "小猪"},{"question": "what's your age", "answer": "23"}] } }
- */
- JSONObject jsonObject = new JSONObject(json); // 返回的数据形式是一个Object类型,所以可以直接转换成一个Object
- String name = jsonObject.getString("name");
- int age = jsonObject.getInt("age");
- Log.i("abc", "name:" + name + " | age:" + age); // 测试数据
- JSONObject contentObject = jsonObject.getJSONObject("content"); // 获取对象中的对象
- String questionsTotal = contentObject.getString("questionsTotal"); // 获取对象中的一个值
- Log.i("abc", "questionsTotal:" + questionsTotal); // 测试数据
- JSONArray contentArray = contentObject.getJSONArray("questions"); // 获取对象中的数组
- for (int i = 0; i < contentArray.length(); i++) {
- JSONObject item = contentArray.getJSONObject(i); // 得到每个对象
- String question = item.getString("question"); // 获取对象对应的值
- String answer = item.getString("answer");
- map = new HashMap<String, String>(); // 存放到MAP里面
- map.put("question", question);
- map.put("answer", answer);
- list.add(map);
- }
- }
- // ***********测试数据******************
- for (Map<String, String> list2 : list) {
- String question = list2.get("question");
- String answer = list2.get("answer");
- Log.i("abc", "question:" + question + " | answer:" + answer);
- }
- return list;
- }
- /**
- * 把输入流转换成字符数组
- *
- * @param inputStream
- * 输入流
- * @return 字符数组
- * @throws Exception
- */
- public static byte[] readStream(InputStream inputStream) throws Exception {
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int len = 0;
- while ((len = inputStream.read(buffer)) != -1) {
- bout.write(buffer, 0, len);
- }
- bout.close();
- inputStream.close();
- return bout.toByteArray();
- }
- }