1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.util; 18 19 import android.graphics.Bitmap; 20 import android.graphics.BitmapFactory; 21 import android.graphics.Bitmap.CompressFormat; 22 import android.net.Uri; 23 import android.util.Base64; 24 import android.util.Xml; 25 26 import org.xmlpull.v1.XmlPullParser; 27 import org.xmlpull.v1.XmlPullParserException; 28 import org.xmlpull.v1.XmlSerializer; 29 30 import java.io.ByteArrayOutputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.io.OutputStream; 34 import java.net.ProtocolException; 35 import java.util.ArrayList; 36 import java.util.HashMap; 37 import java.util.HashSet; 38 import java.util.Iterator; 39 import java.util.List; 40 import java.util.Map; 41 import java.util.Set; 42 43 /** {@hide} */ 44 public class XmlUtils { 45 46 public static void skipCurrentTag(XmlPullParser parser) 47 throws XmlPullParserException, IOException { 48 int outerDepth = parser.getDepth(); 49 int type; 50 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 51 && (type != XmlPullParser.END_TAG 52 || parser.getDepth() > outerDepth)) { 53 } 54 } 55 56 public static final int 57 convertValueToList(CharSequence value, String[] options, int defaultValue) 58 { 59 if (null != value) { 60 for (int i = 0; i < options.length; i++) { 61 if (value.equals(options[i])) 62 return i; 63 } 64 } 65 66 return defaultValue; 67 } 68 69 public static final boolean 70 convertValueToBoolean(CharSequence value, boolean defaultValue) 71 { 72 boolean result = false; 73 74 if (null == value) 75 return defaultValue; 76 77 if (value.equals("1") 78 || value.equals("true") 79 || value.equals("TRUE")) 80 result = true; 81 82 return result; 83 } 84 85 public static final int 86 convertValueToInt(CharSequence charSeq, int defaultValue) 87 { 88 if (null == charSeq) 89 return defaultValue; 90 91 String nm = charSeq.toString(); 92 93 // XXX This code is copied from Integer.decode() so we don't 94 // have to instantiate an Integer! 95 96 int value; 97 int sign = 1; 98 int index = 0; 99 int len = nm.length(); 100 int base = 10; 101 102 if ('-' == nm.charAt(0)) { 103 sign = -1; 104 index++; 105 } 106 107 if ('0' == nm.charAt(index)) { 108 // Quick check for a zero by itself 109 if (index == (len - 1)) 110 return 0; 111 112 char c = nm.charAt(index + 1); 113 114 if ('x' == c || 'X' == c) { 115 index += 2; 116 base = 16; 117 } else { 118 index++; 119 base = 8; 120 } 121 } 122 else if ('#' == nm.charAt(index)) 123 { 124 index++; 125 base = 16; 126 } 127 128 return Integer.parseInt(nm.substring(index), base) * sign; 129 } 130 131 public static int convertValueToUnsignedInt(String value, int defaultValue) { 132 if (null == value) { 133 return defaultValue; 134 } 135 136 return parseUnsignedIntAttribute(value); 137 } 138 139 public static int parseUnsignedIntAttribute(CharSequence charSeq) { 140 String value = charSeq.toString(); 141 142 long bits; 143 int index = 0; 144 int len = value.length(); 145 int base = 10; 146 147 if ('0' == value.charAt(index)) { 148 // Quick check for zero by itself 149 if (index == (len - 1)) 150 return 0; 151 152 char c = value.charAt(index + 1); 153 154 if ('x' == c || 'X' == c) { // check for hex 155 index += 2; 156 base = 16; 157 } else { // check for octal 158 index++; 159 base = 8; 160 } 161 } else if ('#' == value.charAt(index)) { 162 index++; 163 base = 16; 164 } 165 166 return (int) Long.parseLong(value.substring(index), base); 167 } 168 169 /** 170 * Flatten a Map into an output stream as XML. The map can later be 171 * read back with readMapXml(). 172 * 173 * @param val The map to be flattened. 174 * @param out Where to write the XML data. 175 * 176 * @see #writeMapXml(Map, String, XmlSerializer) 177 * @see #writeListXml 178 * @see #writeValueXml 179 * @see #readMapXml 180 */ 181 public static final void writeMapXml(Map val, OutputStream out) 182 throws XmlPullParserException, java.io.IOException { 183 XmlSerializer serializer = new FastXmlSerializer(); 184 serializer.setOutput(out, "utf-8"); 185 serializer.startDocument(null, true); 186 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 187 writeMapXml(val, null, serializer); 188 serializer.endDocument(); 189 } 190 191 /** 192 * Flatten a List into an output stream as XML. The list can later be 193 * read back with readListXml(). 194 * 195 * @param val The list to be flattened. 196 * @param out Where to write the XML data. 197 * 198 * @see #writeListXml(List, String, XmlSerializer) 199 * @see #writeMapXml 200 * @see #writeValueXml 201 * @see #readListXml 202 */ 203 public static final void writeListXml(List val, OutputStream out) 204 throws XmlPullParserException, java.io.IOException 205 { 206 XmlSerializer serializer = Xml.newSerializer(); 207 serializer.setOutput(out, "utf-8"); 208 serializer.startDocument(null, true); 209 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 210 writeListXml(val, null, serializer); 211 serializer.endDocument(); 212 } 213 214 /** 215 * Flatten a Map into an XmlSerializer. The map can later be read back 216 * with readThisMapXml(). 217 * 218 * @param val The map to be flattened. 219 * @param name Name attribute to include with this list's tag, or null for 220 * none. 221 * @param out XmlSerializer to write the map into. 222 * 223 * @see #writeMapXml(Map, OutputStream) 224 * @see #writeListXml 225 * @see #writeValueXml 226 * @see #readMapXml 227 */ 228 public static final void writeMapXml(Map val, String name, XmlSerializer out) 229 throws XmlPullParserException, java.io.IOException { 230 writeMapXml(val, name, out, null); 231 } 232 233 /** 234 * Flatten a Map into an XmlSerializer. The map can later be read back 235 * with readThisMapXml(). 236 * 237 * @param val The map to be flattened. 238 * @param name Name attribute to include with this list's tag, or null for 239 * none. 240 * @param out XmlSerializer to write the map into. 241 * @param callback Method to call when an Object type is not recognized. 242 * 243 * @see #writeMapXml(Map, OutputStream) 244 * @see #writeListXml 245 * @see #writeValueXml 246 * @see #readMapXml 247 * 248 * @hide 249 */ 250 public static final void writeMapXml(Map val, String name, XmlSerializer out, 251 WriteMapCallback callback) throws XmlPullParserException, java.io.IOException { 252 253 if (val == null) { 254 out.startTag(null, "null"); 255 out.endTag(null, "null"); 256 return; 257 } 258 259 out.startTag(null, "map"); 260 if (name != null) { 261 out.attribute(null, "name", name); 262 } 263 264 writeMapXml(val, out, callback); 265 266 out.endTag(null, "map"); 267 } 268 269 /** 270 * Flatten a Map into an XmlSerializer. The map can later be read back 271 * with readThisMapXml(). This method presumes that the start tag and 272 * name attribute have already been written and does not write an end tag. 273 * 274 * @param val The map to be flattened. 275 * @param out XmlSerializer to write the map into. 276 * 277 * @see #writeMapXml(Map, OutputStream) 278 * @see #writeListXml 279 * @see #writeValueXml 280 * @see #readMapXml 281 * 282 * @hide 283 */ 284 public static final void writeMapXml(Map val, XmlSerializer out, 285 WriteMapCallback callback) throws XmlPullParserException, java.io.IOException { 286 if (val == null) { 287 return; 288 } 289 290 Set s = val.entrySet(); 291 Iterator i = s.iterator(); 292 293 while (i.hasNext()) { 294 Map.Entry e = (Map.Entry)i.next(); 295 writeValueXml(e.getValue(), (String)e.getKey(), out, callback); 296 } 297 } 298 299 /** 300 * Flatten a List into an XmlSerializer. The list can later be read back 301 * with readThisListXml(). 302 * 303 * @param val The list to be flattened. 304 * @param name Name attribute to include with this list's tag, or null for 305 * none. 306 * @param out XmlSerializer to write the list into. 307 * 308 * @see #writeListXml(List, OutputStream) 309 * @see #writeMapXml 310 * @see #writeValueXml 311 * @see #readListXml 312 */ 313 public static final void writeListXml(List val, String name, XmlSerializer out) 314 throws XmlPullParserException, java.io.IOException 315 { 316 if (val == null) { 317 out.startTag(null, "null"); 318 out.endTag(null, "null"); 319 return; 320 } 321 322 out.startTag(null, "list"); 323 if (name != null) { 324 out.attribute(null, "name", name); 325 } 326 327 int N = val.size(); 328 int i=0; 329 while (i < N) { 330 writeValueXml(val.get(i), null, out); 331 i++; 332 } 333 334 out.endTag(null, "list"); 335 } 336 337 public static final void writeSetXml(Set val, String name, XmlSerializer out) 338 throws XmlPullParserException, java.io.IOException { 339 if (val == null) { 340 out.startTag(null, "null"); 341 out.endTag(null, "null"); 342 return; 343 } 344 345 out.startTag(null, "set"); 346 if (name != null) { 347 out.attribute(null, "name", name); 348 } 349 350 for (Object v : val) { 351 writeValueXml(v, null, out); 352 } 353 354 out.endTag(null, "set"); 355 } 356 357 /** 358 * Flatten a byte[] into an XmlSerializer. The list can later be read back 359 * with readThisByteArrayXml(). 360 * 361 * @param val The byte array to be flattened. 362 * @param name Name attribute to include with this array's tag, or null for 363 * none. 364 * @param out XmlSerializer to write the array into. 365 * 366 * @see #writeMapXml 367 * @see #writeValueXml 368 */ 369 public static final void writeByteArrayXml(byte[] val, String name, 370 XmlSerializer out) 371 throws XmlPullParserException, java.io.IOException { 372 373 if (val == null) { 374 out.startTag(null, "null"); 375 out.endTag(null, "null"); 376 return; 377 } 378 379 out.startTag(null, "byte-array"); 380 if (name != null) { 381 out.attribute(null, "name", name); 382 } 383 384 final int N = val.length; 385 out.attribute(null, "num", Integer.toString(N)); 386 387 StringBuilder sb = new StringBuilder(val.length*2); 388 for (int i=0; i<N; i++) { 389 int b = val[i]; 390 int h = b>>4; 391 sb.append(h >= 10 ? ('a'+h-10) : ('0'+h)); 392 h = b&0xff; 393 sb.append(h >= 10 ? ('a'+h-10) : ('0'+h)); 394 } 395 396 out.text(sb.toString()); 397 398 out.endTag(null, "byte-array"); 399 } 400 401 /** 402 * Flatten an int[] into an XmlSerializer. The list can later be read back 403 * with readThisIntArrayXml(). 404 * 405 * @param val The int array to be flattened. 406 * @param name Name attribute to include with this array's tag, or null for 407 * none. 408 * @param out XmlSerializer to write the array into. 409 * 410 * @see #writeMapXml 411 * @see #writeValueXml 412 * @see #readThisIntArrayXml 413 */ 414 public static final void writeIntArrayXml(int[] val, String name, 415 XmlSerializer out) 416 throws XmlPullParserException, java.io.IOException { 417 418 if (val == null) { 419 out.startTag(null, "null"); 420 out.endTag(null, "null"); 421 return; 422 } 423 424 out.startTag(null, "int-array"); 425 if (name != null) { 426 out.attribute(null, "name", name); 427 } 428 429 final int N = val.length; 430 out.attribute(null, "num", Integer.toString(N)); 431 432 for (int i=0; i<N; i++) { 433 out.startTag(null, "item"); 434 out.attribute(null, "value", Integer.toString(val[i])); 435 out.endTag(null, "item"); 436 } 437 438 out.endTag(null, "int-array"); 439 } 440 441 /** 442 * Flatten a long[] into an XmlSerializer. The list can later be read back 443 * with readThisLongArrayXml(). 444 * 445 * @param val The long array to be flattened. 446 * @param name Name attribute to include with this array's tag, or null for 447 * none. 448 * @param out XmlSerializer to write the array into. 449 * 450 * @see #writeMapXml 451 * @see #writeValueXml 452 * @see #readThisIntArrayXml 453 */ 454 public static final void writeLongArrayXml(long[] val, String name, XmlSerializer out) 455 throws XmlPullParserException, java.io.IOException { 456 457 if (val == null) { 458 out.startTag(null, "null"); 459 out.endTag(null, "null"); 460 return; 461 } 462 463 out.startTag(null, "long-array"); 464 if (name != null) { 465 out.attribute(null, "name", name); 466 } 467 468 final int N = val.length; 469 out.attribute(null, "num", Integer.toString(N)); 470 471 for (int i=0; i<N; i++) { 472 out.startTag(null, "item"); 473 out.attribute(null, "value", Long.toString(val[i])); 474 out.endTag(null, "item"); 475 } 476 477 out.endTag(null, "long-array"); 478 } 479 480 /** 481 * Flatten a double[] into an XmlSerializer. The list can later be read back 482 * with readThisDoubleArrayXml(). 483 * 484 * @param val The double array to be flattened. 485 * @param name Name attribute to include with this array's tag, or null for 486 * none. 487 * @param out XmlSerializer to write the array into. 488 * 489 * @see #writeMapXml 490 * @see #writeValueXml 491 * @see #readThisIntArrayXml 492 */ 493 public static final void writeDoubleArrayXml(double[] val, String name, XmlSerializer out) 494 throws XmlPullParserException, java.io.IOException { 495 496 if (val == null) { 497 out.startTag(null, "null"); 498 out.endTag(null, "null"); 499 return; 500 } 501 502 out.startTag(null, "double-array"); 503 if (name != null) { 504 out.attribute(null, "name", name); 505 } 506 507 final int N = val.length; 508 out.attribute(null, "num", Integer.toString(N)); 509 510 for (int i=0; i<N; i++) { 511 out.startTag(null, "item"); 512 out.attribute(null, "value", Double.toString(val[i])); 513 out.endTag(null, "item"); 514 } 515 516 out.endTag(null, "double-array"); 517 } 518 519 /** 520 * Flatten a String[] into an XmlSerializer. The list can later be read back 521 * with readThisStringArrayXml(). 522 * 523 * @param val The long array to be flattened. 524 * @param name Name attribute to include with this array's tag, or null for 525 * none. 526 * @param out XmlSerializer to write the array into. 527 * 528 * @see #writeMapXml 529 * @see #writeValueXml 530 * @see #readThisIntArrayXml 531 */ 532 public static final void writeStringArrayXml(String[] val, String name, XmlSerializer out) 533 throws XmlPullParserException, java.io.IOException { 534 535 if (val == null) { 536 out.startTag(null, "null"); 537 out.endTag(null, "null"); 538 return; 539 } 540 541 out.startTag(null, "string-array"); 542 if (name != null) { 543 out.attribute(null, "name", name); 544 } 545 546 final int N = val.length; 547 out.attribute(null, "num", Integer.toString(N)); 548 549 for (int i=0; i<N; i++) { 550 out.startTag(null, "item"); 551 out.attribute(null, "value", val[i]); 552 out.endTag(null, "item"); 553 } 554 555 out.endTag(null, "string-array"); 556 } 557 558 /** 559 * Flatten an object's value into an XmlSerializer. The value can later 560 * be read back with readThisValueXml(). 561 * 562 * Currently supported value types are: null, String, Integer, Long, 563 * Float, Double Boolean, Map, List. 564 * 565 * @param v The object to be flattened. 566 * @param name Name attribute to include with this value's tag, or null 567 * for none. 568 * @param out XmlSerializer to write the object into. 569 * 570 * @see #writeMapXml 571 * @see #writeListXml 572 * @see #readValueXml 573 */ 574 public static final void writeValueXml(Object v, String name, XmlSerializer out) 575 throws XmlPullParserException, java.io.IOException { 576 writeValueXml(v, name, out, null); 577 } 578 579 /** 580 * Flatten an object's value into an XmlSerializer. The value can later 581 * be read back with readThisValueXml(). 582 * 583 * Currently supported value types are: null, String, Integer, Long, 584 * Float, Double Boolean, Map, List. 585 * 586 * @param v The object to be flattened. 587 * @param name Name attribute to include with this value's tag, or null 588 * for none. 589 * @param out XmlSerializer to write the object into. 590 * @param callback Handler for Object types not recognized. 591 * 592 * @see #writeMapXml 593 * @see #writeListXml 594 * @see #readValueXml 595 */ 596 private static final void writeValueXml(Object v, String name, XmlSerializer out, 597 WriteMapCallback callback) throws XmlPullParserException, java.io.IOException { 598 String typeStr; 599 if (v == null) { 600 out.startTag(null, "null"); 601 if (name != null) { 602 out.attribute(null, "name", name); 603 } 604 out.endTag(null, "null"); 605 return; 606 } else if (v instanceof String) { 607 out.startTag(null, "string"); 608 if (name != null) { 609 out.attribute(null, "name", name); 610 } 611 out.text(v.toString()); 612 out.endTag(null, "string"); 613 return; 614 } else if (v instanceof Integer) { 615 typeStr = "int"; 616 } else if (v instanceof Long) { 617 typeStr = "long"; 618 } else if (v instanceof Float) { 619 typeStr = "float"; 620 } else if (v instanceof Double) { 621 typeStr = "double"; 622 } else if (v instanceof Boolean) { 623 typeStr = "boolean"; 624 } else if (v instanceof byte[]) { 625 writeByteArrayXml((byte[])v, name, out); 626 return; 627 } else if (v instanceof int[]) { 628 writeIntArrayXml((int[])v, name, out); 629 return; 630 } else if (v instanceof long[]) { 631 writeLongArrayXml((long[])v, name, out); 632 return; 633 } else if (v instanceof double[]) { 634 writeDoubleArrayXml((double[])v, name, out); 635 return; 636 } else if (v instanceof String[]) { 637 writeStringArrayXml((String[])v, name, out); 638 return; 639 } else if (v instanceof Map) { 640 writeMapXml((Map)v, name, out); 641 return; 642 } else if (v instanceof List) { 643 writeListXml((List) v, name, out); 644 return; 645 } else if (v instanceof Set) { 646 writeSetXml((Set) v, name, out); 647 return; 648 } else if (v instanceof CharSequence) { 649 // XXX This is to allow us to at least write something if 650 // we encounter styled text... but it means we will drop all 651 // of the styling information. :( 652 out.startTag(null, "string"); 653 if (name != null) { 654 out.attribute(null, "name", name); 655 } 656 out.text(v.toString()); 657 out.endTag(null, "string"); 658 return; 659 } else if (callback != null) { 660 callback.writeUnknownObject(v, name, out); 661 return; 662 } else { 663 throw new RuntimeException("writeValueXml: unable to write value " + v); 664 } 665 666 out.startTag(null, typeStr); 667 if (name != null) { 668 out.attribute(null, "name", name); 669 } 670 out.attribute(null, "value", v.toString()); 671 out.endTag(null, typeStr); 672 } 673 674 /** 675 * Read a HashMap from an InputStream containing XML. The stream can 676 * previously have been written by writeMapXml(). 677 * 678 * @param in The InputStream from which to read. 679 * 680 * @return HashMap The resulting map. 681 * 682 * @see #readListXml 683 * @see #readValueXml 684 * @see #readThisMapXml 685 * #see #writeMapXml 686 */ 687 @SuppressWarnings("unchecked") 688 public static final HashMap<String, ?> readMapXml(InputStream in) 689 throws XmlPullParserException, java.io.IOException 690 { 691 XmlPullParser parser = Xml.newPullParser(); 692 parser.setInput(in, null); 693 return (HashMap<String, ?>) readValueXml(parser, new String[1]); 694 } 695 696 /** 697 * Read an ArrayList from an InputStream containing XML. The stream can 698 * previously have been written by writeListXml(). 699 * 700 * @param in The InputStream from which to read. 701 * 702 * @return ArrayList The resulting list. 703 * 704 * @see #readMapXml 705 * @see #readValueXml 706 * @see #readThisListXml 707 * @see #writeListXml 708 */ 709 public static final ArrayList readListXml(InputStream in) 710 throws XmlPullParserException, java.io.IOException 711 { 712 XmlPullParser parser = Xml.newPullParser(); 713 parser.setInput(in, null); 714 return (ArrayList)readValueXml(parser, new String[1]); 715 } 716 717 718 /** 719 * Read a HashSet from an InputStream containing XML. The stream can 720 * previously have been written by writeSetXml(). 721 * 722 * @param in The InputStream from which to read. 723 * 724 * @return HashSet The resulting set. 725 * 726 * @throws XmlPullParserException 727 * @throws java.io.IOException 728 * 729 * @see #readValueXml 730 * @see #readThisSetXml 731 * @see #writeSetXml 732 */ 733 public static final HashSet readSetXml(InputStream in) 734 throws XmlPullParserException, java.io.IOException { 735 XmlPullParser parser = Xml.newPullParser(); 736 parser.setInput(in, null); 737 return (HashSet) readValueXml(parser, new String[1]); 738 } 739 740 /** 741 * Read a HashMap object from an XmlPullParser. The XML data could 742 * previously have been generated by writeMapXml(). The XmlPullParser 743 * must be positioned <em>after</em> the tag that begins the map. 744 * 745 * @param parser The XmlPullParser from which to read the map data. 746 * @param endTag Name of the tag that will end the map, usually "map". 747 * @param name An array of one string, used to return the name attribute 748 * of the map's tag. 749 * 750 * @return HashMap The newly generated map. 751 * 752 * @see #readMapXml 753 */ 754 public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag, 755 String[] name) throws XmlPullParserException, java.io.IOException { 756 return readThisMapXml(parser, endTag, name, null); 757 } 758 759 /** 760 * Read a HashMap object from an XmlPullParser. The XML data could 761 * previously have been generated by writeMapXml(). The XmlPullParser 762 * must be positioned <em>after</em> the tag that begins the map. 763 * 764 * @param parser The XmlPullParser from which to read the map data. 765 * @param endTag Name of the tag that will end the map, usually "map". 766 * @param name An array of one string, used to return the name attribute 767 * of the map's tag. 768 * 769 * @return HashMap The newly generated map. 770 * 771 * @see #readMapXml 772 * @hide 773 */ 774 public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag, 775 String[] name, ReadMapCallback callback) 776 throws XmlPullParserException, java.io.IOException 777 { 778 HashMap<String, Object> map = new HashMap<String, Object>(); 779 780 int eventType = parser.getEventType(); 781 do { 782 if (eventType == parser.START_TAG) { 783 Object val = readThisValueXml(parser, name, callback); 784 map.put(name[0], val); 785 } else if (eventType == parser.END_TAG) { 786 if (parser.getName().equals(endTag)) { 787 return map; 788 } 789 throw new XmlPullParserException( 790 "Expected " + endTag + " end tag at: " + parser.getName()); 791 } 792 eventType = parser.next(); 793 } while (eventType != parser.END_DOCUMENT); 794 795 throw new XmlPullParserException( 796 "Document ended before " + endTag + " end tag"); 797 } 798 799 /** 800 * Read an ArrayList object from an XmlPullParser. The XML data could 801 * previously have been generated by writeListXml(). The XmlPullParser 802 * must be positioned <em>after</em> the tag that begins the list. 803 * 804 * @param parser The XmlPullParser from which to read the list data. 805 * @param endTag Name of the tag that will end the list, usually "list". 806 * @param name An array of one string, used to return the name attribute 807 * of the list's tag. 808 * 809 * @return HashMap The newly generated list. 810 * 811 * @see #readListXml 812 */ 813 public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, 814 String[] name) throws XmlPullParserException, java.io.IOException { 815 return readThisListXml(parser, endTag, name, null); 816 } 817 818 /** 819 * Read an ArrayList object from an XmlPullParser. The XML data could 820 * previously have been generated by writeListXml(). The XmlPullParser 821 * must be positioned <em>after</em> the tag that begins the list. 822 * 823 * @param parser The XmlPullParser from which to read the list data. 824 * @param endTag Name of the tag that will end the list, usually "list". 825 * @param name An array of one string, used to return the name attribute 826 * of the list's tag. 827 * 828 * @return HashMap The newly generated list. 829 * 830 * @see #readListXml 831 */ 832 private static final ArrayList readThisListXml(XmlPullParser parser, String endTag, 833 String[] name, ReadMapCallback callback) 834 throws XmlPullParserException, java.io.IOException { 835 ArrayList list = new ArrayList(); 836 837 int eventType = parser.getEventType(); 838 do { 839 if (eventType == parser.START_TAG) { 840 Object val = readThisValueXml(parser, name, callback); 841 list.add(val); 842 //System.out.println("Adding to list: " + val); 843 } else if (eventType == parser.END_TAG) { 844 if (parser.getName().equals(endTag)) { 845 return list; 846 } 847 throw new XmlPullParserException( 848 "Expected " + endTag + " end tag at: " + parser.getName()); 849 } 850 eventType = parser.next(); 851 } while (eventType != parser.END_DOCUMENT); 852 853 throw new XmlPullParserException( 854 "Document ended before " + endTag + " end tag"); 855 } 856 857 /** 858 * Read a HashSet object from an XmlPullParser. The XML data could previously 859 * have been generated by writeSetXml(). The XmlPullParser must be positioned 860 * <em>after</em> the tag that begins the set. 861 * 862 * @param parser The XmlPullParser from which to read the set data. 863 * @param endTag Name of the tag that will end the set, usually "set". 864 * @param name An array of one string, used to return the name attribute 865 * of the set's tag. 866 * 867 * @return HashSet The newly generated set. 868 * 869 * @throws XmlPullParserException 870 * @throws java.io.IOException 871 * 872 * @see #readSetXml 873 */ 874 public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name) 875 throws XmlPullParserException, java.io.IOException { 876 return readThisSetXml(parser, endTag, name, null); 877 } 878 879 /** 880 * Read a HashSet object from an XmlPullParser. The XML data could previously 881 * have been generated by writeSetXml(). The XmlPullParser must be positioned 882 * <em>after</em> the tag that begins the set. 883 * 884 * @param parser The XmlPullParser from which to read the set data. 885 * @param endTag Name of the tag that will end the set, usually "set". 886 * @param name An array of one string, used to return the name attribute 887 * of the set's tag. 888 * 889 * @return HashSet The newly generated set. 890 * 891 * @throws XmlPullParserException 892 * @throws java.io.IOException 893 * 894 * @see #readSetXml 895 * @hide 896 */ 897 private static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name, 898 ReadMapCallback callback) throws XmlPullParserException, java.io.IOException { 899 HashSet set = new HashSet(); 900 901 int eventType = parser.getEventType(); 902 do { 903 if (eventType == parser.START_TAG) { 904 Object val = readThisValueXml(parser, name, callback); 905 set.add(val); 906 //System.out.println("Adding to set: " + val); 907 } else if (eventType == parser.END_TAG) { 908 if (parser.getName().equals(endTag)) { 909 return set; 910 } 911 throw new XmlPullParserException( 912 "Expected " + endTag + " end tag at: " + parser.getName()); 913 } 914 eventType = parser.next(); 915 } while (eventType != parser.END_DOCUMENT); 916 917 throw new XmlPullParserException( 918 "Document ended before " + endTag + " end tag"); 919 } 920 921 /** 922 * Read an int[] object from an XmlPullParser. The XML data could 923 * previously have been generated by writeIntArrayXml(). The XmlPullParser 924 * must be positioned <em>after</em> the tag that begins the list. 925 * 926 * @param parser The XmlPullParser from which to read the list data. 927 * @param endTag Name of the tag that will end the list, usually "list". 928 * @param name An array of one string, used to return the name attribute 929 * of the list's tag. 930 * 931 * @return Returns a newly generated int[]. 932 * 933 * @see #readListXml 934 */ 935 public static final int[] readThisIntArrayXml(XmlPullParser parser, 936 String endTag, String[] name) 937 throws XmlPullParserException, java.io.IOException { 938 939 int num; 940 try { 941 num = Integer.parseInt(parser.getAttributeValue(null, "num")); 942 } catch (NullPointerException e) { 943 throw new XmlPullParserException( 944 "Need num attribute in byte-array"); 945 } catch (NumberFormatException e) { 946 throw new XmlPullParserException( 947 "Not a number in num attribute in byte-array"); 948 } 949 parser.next(); 950 951 int[] array = new int[num]; 952 int i = 0; 953 954 int eventType = parser.getEventType(); 955 do { 956 if (eventType == parser.START_TAG) { 957 if (parser.getName().equals("item")) { 958 try { 959 array[i] = Integer.parseInt( 960 parser.getAttributeValue(null, "value")); 961 } catch (NullPointerException e) { 962 throw new XmlPullParserException( 963 "Need value attribute in item"); 964 } catch (NumberFormatException e) { 965 throw new XmlPullParserException( 966 "Not a number in value attribute in item"); 967 } 968 } else { 969 throw new XmlPullParserException( 970 "Expected item tag at: " + parser.getName()); 971 } 972 } else if (eventType == parser.END_TAG) { 973 if (parser.getName().equals(endTag)) { 974 return array; 975 } else if (parser.getName().equals("item")) { 976 i++; 977 } else { 978 throw new XmlPullParserException( 979 "Expected " + endTag + " end tag at: " 980 + parser.getName()); 981 } 982 } 983 eventType = parser.next(); 984 } while (eventType != parser.END_DOCUMENT); 985 986 throw new XmlPullParserException( 987 "Document ended before " + endTag + " end tag"); 988 } 989 990 /** 991 * Read a long[] object from an XmlPullParser. The XML data could 992 * previously have been generated by writeLongArrayXml(). The XmlPullParser 993 * must be positioned <em>after</em> the tag that begins the list. 994 * 995 * @param parser The XmlPullParser from which to read the list data. 996 * @param endTag Name of the tag that will end the list, usually "list". 997 * @param name An array of one string, used to return the name attribute 998 * of the list's tag. 999 * 1000 * @return Returns a newly generated long[]. 1001 * 1002 * @see #readListXml 1003 */ 1004 public static final long[] readThisLongArrayXml(XmlPullParser parser, 1005 String endTag, String[] name) 1006 throws XmlPullParserException, java.io.IOException { 1007 1008 int num; 1009 try { 1010 num = Integer.parseInt(parser.getAttributeValue(null, "num")); 1011 } catch (NullPointerException e) { 1012 throw new XmlPullParserException("Need num attribute in long-array"); 1013 } catch (NumberFormatException e) { 1014 throw new XmlPullParserException("Not a number in num attribute in long-array"); 1015 } 1016 parser.next(); 1017 1018 long[] array = new long[num]; 1019 int i = 0; 1020 1021 int eventType = parser.getEventType(); 1022 do { 1023 if (eventType == parser.START_TAG) { 1024 if (parser.getName().equals("item")) { 1025 try { 1026 array[i] = Long.parseLong(parser.getAttributeValue(null, "value")); 1027 } catch (NullPointerException e) { 1028 throw new XmlPullParserException("Need value attribute in item"); 1029 } catch (NumberFormatException e) { 1030 throw new XmlPullParserException("Not a number in value attribute in item"); 1031 } 1032 } else { 1033 throw new XmlPullParserException("Expected item tag at: " + parser.getName()); 1034 } 1035 } else if (eventType == parser.END_TAG) { 1036 if (parser.getName().equals(endTag)) { 1037 return array; 1038 } else if (parser.getName().equals("item")) { 1039 i++; 1040 } else { 1041 throw new XmlPullParserException("Expected " + endTag + " end tag at: " + 1042 parser.getName()); 1043 } 1044 } 1045 eventType = parser.next(); 1046 } while (eventType != parser.END_DOCUMENT); 1047 1048 throw new XmlPullParserException("Document ended before " + endTag + " end tag"); 1049 } 1050 1051 /** 1052 * Read a double[] object from an XmlPullParser. The XML data could 1053 * previously have been generated by writeDoubleArrayXml(). The XmlPullParser 1054 * must be positioned <em>after</em> the tag that begins the list. 1055 * 1056 * @param parser The XmlPullParser from which to read the list data. 1057 * @param endTag Name of the tag that will end the list, usually "double-array". 1058 * @param name An array of one string, used to return the name attribute 1059 * of the list's tag. 1060 * 1061 * @return Returns a newly generated double[]. 1062 * 1063 * @see #readListXml 1064 */ 1065 public static final double[] readThisDoubleArrayXml(XmlPullParser parser, String endTag, 1066 String[] name) throws XmlPullParserException, java.io.IOException { 1067 1068 int num; 1069 try { 1070 num = Integer.parseInt(parser.getAttributeValue(null, "num")); 1071 } catch (NullPointerException e) { 1072 throw new XmlPullParserException("Need num attribute in double-array"); 1073 } catch (NumberFormatException e) { 1074 throw new XmlPullParserException("Not a number in num attribute in double-array"); 1075 } 1076 parser.next(); 1077 1078 double[] array = new double[num]; 1079 int i = 0; 1080 1081 int eventType = parser.getEventType(); 1082 do { 1083 if (eventType == parser.START_TAG) { 1084 if (parser.getName().equals("item")) { 1085 try { 1086 array[i] = Double.parseDouble(parser.getAttributeValue(null, "value")); 1087 } catch (NullPointerException e) { 1088 throw new XmlPullParserException("Need value attribute in item"); 1089 } catch (NumberFormatException e) { 1090 throw new XmlPullParserException("Not a number in value attribute in item"); 1091 } 1092 } else { 1093 throw new XmlPullParserException("Expected item tag at: " + parser.getName()); 1094 } 1095 } else if (eventType == parser.END_TAG) { 1096 if (parser.getName().equals(endTag)) { 1097 return array; 1098 } else if (parser.getName().equals("item")) { 1099 i++; 1100 } else { 1101 throw new XmlPullParserException("Expected " + endTag + " end tag at: " + 1102 parser.getName()); 1103 } 1104 } 1105 eventType = parser.next(); 1106 } while (eventType != parser.END_DOCUMENT); 1107 1108 throw new XmlPullParserException("Document ended before " + endTag + " end tag"); 1109 } 1110 1111 /** 1112 * Read a String[] object from an XmlPullParser. The XML data could 1113 * previously have been generated by writeStringArrayXml(). The XmlPullParser 1114 * must be positioned <em>after</em> the tag that begins the list. 1115 * 1116 * @param parser The XmlPullParser from which to read the list data. 1117 * @param endTag Name of the tag that will end the list, usually "string-array". 1118 * @param name An array of one string, used to return the name attribute 1119 * of the list's tag. 1120 * 1121 * @return Returns a newly generated String[]. 1122 * 1123 * @see #readListXml 1124 */ 1125 public static final String[] readThisStringArrayXml(XmlPullParser parser, String endTag, 1126 String[] name) throws XmlPullParserException, java.io.IOException { 1127 1128 int num; 1129 try { 1130 num = Integer.parseInt(parser.getAttributeValue(null, "num")); 1131 } catch (NullPointerException e) { 1132 throw new XmlPullParserException("Need num attribute in string-array"); 1133 } catch (NumberFormatException e) { 1134 throw new XmlPullParserException("Not a number in num attribute in string-array"); 1135 } 1136 parser.next(); 1137 1138 String[] array = new String[num]; 1139 int i = 0; 1140 1141 int eventType = parser.getEventType(); 1142 do { 1143 if (eventType == parser.START_TAG) { 1144 if (parser.getName().equals("item")) { 1145 try { 1146 array[i] = parser.getAttributeValue(null, "value"); 1147 } catch (NullPointerException e) { 1148 throw new XmlPullParserException("Need value attribute in item"); 1149 } catch (NumberFormatException e) { 1150 throw new XmlPullParserException("Not a number in value attribute in item"); 1151 } 1152 } else { 1153 throw new XmlPullParserException("Expected item tag at: " + parser.getName()); 1154 } 1155 } else if (eventType == parser.END_TAG) { 1156 if (parser.getName().equals(endTag)) { 1157 return array; 1158 } else if (parser.getName().equals("item")) { 1159 i++; 1160 } else { 1161 throw new XmlPullParserException("Expected " + endTag + " end tag at: " + 1162 parser.getName()); 1163 } 1164 } 1165 eventType = parser.next(); 1166 } while (eventType != parser.END_DOCUMENT); 1167 1168 throw new XmlPullParserException("Document ended before " + endTag + " end tag"); 1169 } 1170 1171 /** 1172 * Read a flattened object from an XmlPullParser. The XML data could 1173 * previously have been written with writeMapXml(), writeListXml(), or 1174 * writeValueXml(). The XmlPullParser must be positioned <em>at</em> the 1175 * tag that defines the value. 1176 * 1177 * @param parser The XmlPullParser from which to read the object. 1178 * @param name An array of one string, used to return the name attribute 1179 * of the value's tag. 1180 * 1181 * @return Object The newly generated value object. 1182 * 1183 * @see #readMapXml 1184 * @see #readListXml 1185 * @see #writeValueXml 1186 */ 1187 public static final Object readValueXml(XmlPullParser parser, String[] name) 1188 throws XmlPullParserException, java.io.IOException 1189 { 1190 int eventType = parser.getEventType(); 1191 do { 1192 if (eventType == parser.START_TAG) { 1193 return readThisValueXml(parser, name, null); 1194 } else if (eventType == parser.END_TAG) { 1195 throw new XmlPullParserException( 1196 "Unexpected end tag at: " + parser.getName()); 1197 } else if (eventType == parser.TEXT) { 1198 throw new XmlPullParserException( 1199 "Unexpected text: " + parser.getText()); 1200 } 1201 eventType = parser.next(); 1202 } while (eventType != parser.END_DOCUMENT); 1203 1204 throw new XmlPullParserException( 1205 "Unexpected end of document"); 1206 } 1207 1208 private static final Object readThisValueXml(XmlPullParser parser, String[] name, 1209 ReadMapCallback callback) throws XmlPullParserException, java.io.IOException { 1210 final String valueName = parser.getAttributeValue(null, "name"); 1211 final String tagName = parser.getName(); 1212 1213 //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName); 1214 1215 Object res; 1216 1217 if (tagName.equals("null")) { 1218 res = null; 1219 } else if (tagName.equals("string")) { 1220 String value = ""; 1221 int eventType; 1222 while ((eventType = parser.next()) != parser.END_DOCUMENT) { 1223 if (eventType == parser.END_TAG) { 1224 if (parser.getName().equals("string")) { 1225 name[0] = valueName; 1226 //System.out.println("Returning value for " + valueName + ": " + value); 1227 return value; 1228 } 1229 throw new XmlPullParserException( 1230 "Unexpected end tag in <string>: " + parser.getName()); 1231 } else if (eventType == parser.TEXT) { 1232 value += parser.getText(); 1233 } else if (eventType == parser.START_TAG) { 1234 throw new XmlPullParserException( 1235 "Unexpected start tag in <string>: " + parser.getName()); 1236 } 1237 } 1238 throw new XmlPullParserException( 1239 "Unexpected end of document in <string>"); 1240 } else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) { 1241 // all work already done by readThisPrimitiveValueXml 1242 } else if (tagName.equals("int-array")) { 1243 res = readThisIntArrayXml(parser, "int-array", name); 1244 name[0] = valueName; 1245 //System.out.println("Returning value for " + valueName + ": " + res); 1246 return res; 1247 } else if (tagName.equals("long-array")) { 1248 res = readThisLongArrayXml(parser, "long-array", name); 1249 name[0] = valueName; 1250 //System.out.println("Returning value for " + valueName + ": " + res); 1251 return res; 1252 } else if (tagName.equals("double-array")) { 1253 res = readThisDoubleArrayXml(parser, "double-array", name); 1254 name[0] = valueName; 1255 //System.out.println("Returning value for " + valueName + ": " + res); 1256 return res; 1257 } else if (tagName.equals("string-array")) { 1258 res = readThisStringArrayXml(parser, "string-array", name); 1259 name[0] = valueName; 1260 //System.out.println("Returning value for " + valueName + ": " + res); 1261 return res; 1262 } else if (tagName.equals("map")) { 1263 parser.next(); 1264 res = readThisMapXml(parser, "map", name); 1265 name[0] = valueName; 1266 //System.out.println("Returning value for " + valueName + ": " + res); 1267 return res; 1268 } else if (tagName.equals("list")) { 1269 parser.next(); 1270 res = readThisListXml(parser, "list", name); 1271 name[0] = valueName; 1272 //System.out.println("Returning value for " + valueName + ": " + res); 1273 return res; 1274 } else if (tagName.equals("set")) { 1275 parser.next(); 1276 res = readThisSetXml(parser, "set", name); 1277 name[0] = valueName; 1278 //System.out.println("Returning value for " + valueName + ": " + res); 1279 return res; 1280 } else if (callback != null) { 1281 res = callback.readThisUnknownObjectXml(parser, tagName); 1282 name[0] = valueName; 1283 return res; 1284 } else { 1285 throw new XmlPullParserException("Unknown tag: " + tagName); 1286 } 1287 1288 // Skip through to end tag. 1289 int eventType; 1290 while ((eventType = parser.next()) != parser.END_DOCUMENT) { 1291 if (eventType == parser.END_TAG) { 1292 if (parser.getName().equals(tagName)) { 1293 name[0] = valueName; 1294 //System.out.println("Returning value for " + valueName + ": " + res); 1295 return res; 1296 } 1297 throw new XmlPullParserException( 1298 "Unexpected end tag in <" + tagName + ">: " + parser.getName()); 1299 } else if (eventType == parser.TEXT) { 1300 throw new XmlPullParserException( 1301 "Unexpected text in <" + tagName + ">: " + parser.getName()); 1302 } else if (eventType == parser.START_TAG) { 1303 throw new XmlPullParserException( 1304 "Unexpected start tag in <" + tagName + ">: " + parser.getName()); 1305 } 1306 } 1307 throw new XmlPullParserException( 1308 "Unexpected end of document in <" + tagName + ">"); 1309 } 1310 1311 private static final Object readThisPrimitiveValueXml(XmlPullParser parser, String tagName) 1312 throws XmlPullParserException, java.io.IOException 1313 { 1314 try { 1315 if (tagName.equals("int")) { 1316 return Integer.parseInt(parser.getAttributeValue(null, "value")); 1317 } else if (tagName.equals("long")) { 1318 return Long.valueOf(parser.getAttributeValue(null, "value")); 1319 } else if (tagName.equals("float")) { 1320 return new Float(parser.getAttributeValue(null, "value")); 1321 } else if (tagName.equals("double")) { 1322 return new Double(parser.getAttributeValue(null, "value")); 1323 } else if (tagName.equals("boolean")) { 1324 return Boolean.valueOf(parser.getAttributeValue(null, "value")); 1325 } else { 1326 return null; 1327 } 1328 } catch (NullPointerException e) { 1329 throw new XmlPullParserException("Need value attribute in <" + tagName + ">"); 1330 } catch (NumberFormatException e) { 1331 throw new XmlPullParserException( 1332 "Not a number in value attribute in <" + tagName + ">"); 1333 } 1334 } 1335 1336 public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException 1337 { 1338 int type; 1339 while ((type=parser.next()) != parser.START_TAG 1340 && type != parser.END_DOCUMENT) { 1341 ; 1342 } 1343 1344 if (type != parser.START_TAG) { 1345 throw new XmlPullParserException("No start tag found"); 1346 } 1347 1348 if (!parser.getName().equals(firstElementName)) { 1349 throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + 1350 ", expected " + firstElementName); 1351 } 1352 } 1353 1354 public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException 1355 { 1356 int type; 1357 while ((type=parser.next()) != parser.START_TAG 1358 && type != parser.END_DOCUMENT) { 1359 ; 1360 } 1361 } 1362 1363 public static boolean nextElementWithin(XmlPullParser parser, int outerDepth) 1364 throws IOException, XmlPullParserException { 1365 for (;;) { 1366 int type = parser.next(); 1367 if (type == XmlPullParser.END_DOCUMENT 1368 || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) { 1369 return false; 1370 } 1371 if (type == XmlPullParser.START_TAG 1372 && parser.getDepth() == outerDepth + 1) { 1373 return true; 1374 } 1375 } 1376 } 1377 1378 public static int readIntAttribute(XmlPullParser in, String name, int defaultValue) { 1379 final String value = in.getAttributeValue(null, name); 1380 try { 1381 return Integer.parseInt(value); 1382 } catch (NumberFormatException e) { 1383 return defaultValue; 1384 } 1385 } 1386 1387 public static int readIntAttribute(XmlPullParser in, String name) throws IOException { 1388 final String value = in.getAttributeValue(null, name); 1389 try { 1390 return Integer.parseInt(value); 1391 } catch (NumberFormatException e) { 1392 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 1393 } 1394 } 1395 1396 public static void writeIntAttribute(XmlSerializer out, String name, int value) 1397 throws IOException { 1398 out.attribute(null, name, Integer.toString(value)); 1399 } 1400 1401 public static long readLongAttribute(XmlPullParser in, String name, long defaultValue) { 1402 final String value = in.getAttributeValue(null, name); 1403 try { 1404 return Long.parseLong(value); 1405 } catch (NumberFormatException e) { 1406 return defaultValue; 1407 } 1408 } 1409 1410 public static long readLongAttribute(XmlPullParser in, String name) throws IOException { 1411 final String value = in.getAttributeValue(null, name); 1412 try { 1413 return Long.parseLong(value); 1414 } catch (NumberFormatException e) { 1415 throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); 1416 } 1417 } 1418 1419 public static void writeLongAttribute(XmlSerializer out, String name, long value) 1420 throws IOException { 1421 out.attribute(null, name, Long.toString(value)); 1422 } 1423 1424 public static float readFloatAttribute(XmlPullParser in, String name) throws IOException { 1425 final String value = in.getAttributeValue(null, name); 1426 try { 1427 return Float.parseFloat(value); 1428 } catch (NumberFormatException e) { 1429 throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); 1430 } 1431 } 1432 1433 public static void writeFloatAttribute(XmlSerializer out, String name, float value) 1434 throws IOException { 1435 out.attribute(null, name, Float.toString(value)); 1436 } 1437 1438 public static boolean readBooleanAttribute(XmlPullParser in, String name) { 1439 final String value = in.getAttributeValue(null, name); 1440 return Boolean.parseBoolean(value); 1441 } 1442 1443 public static boolean readBooleanAttribute(XmlPullParser in, String name, 1444 boolean defaultValue) { 1445 final String value = in.getAttributeValue(null, name); 1446 if (value == null) { 1447 return defaultValue; 1448 } else { 1449 return Boolean.parseBoolean(value); 1450 } 1451 } 1452 1453 public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value) 1454 throws IOException { 1455 out.attribute(null, name, Boolean.toString(value)); 1456 } 1457 1458 public static Uri readUriAttribute(XmlPullParser in, String name) { 1459 final String value = in.getAttributeValue(null, name); 1460 return (value != null) ? Uri.parse(value) : null; 1461 } 1462 1463 public static void writeUriAttribute(XmlSerializer out, String name, Uri value) 1464 throws IOException { 1465 if (value != null) { 1466 out.attribute(null, name, value.toString()); 1467 } 1468 } 1469 1470 public static String readStringAttribute(XmlPullParser in, String name) { 1471 return in.getAttributeValue(null, name); 1472 } 1473 1474 public static void writeStringAttribute(XmlSerializer out, String name, String value) 1475 throws IOException { 1476 if (value != null) { 1477 out.attribute(null, name, value); 1478 } 1479 } 1480 1481 public static byte[] readByteArrayAttribute(XmlPullParser in, String name) { 1482 final String value = in.getAttributeValue(null, name); 1483 if (value != null) { 1484 return Base64.decode(value, Base64.DEFAULT); 1485 } else { 1486 return null; 1487 } 1488 } 1489 1490 public static void writeByteArrayAttribute(XmlSerializer out, String name, byte[] value) 1491 throws IOException { 1492 if (value != null) { 1493 out.attribute(null, name, Base64.encodeToString(value, Base64.DEFAULT)); 1494 } 1495 } 1496 1497 public static Bitmap readBitmapAttribute(XmlPullParser in, String name) { 1498 final byte[] value = readByteArrayAttribute(in, name); 1499 if (value != null) { 1500 return BitmapFactory.decodeByteArray(value, 0, value.length); 1501 } else { 1502 return null; 1503 } 1504 } 1505 1506 @Deprecated 1507 public static void writeBitmapAttribute(XmlSerializer out, String name, Bitmap value) 1508 throws IOException { 1509 if (value != null) { 1510 final ByteArrayOutputStream os = new ByteArrayOutputStream(); 1511 value.compress(CompressFormat.PNG, 90, os); 1512 writeByteArrayAttribute(out, name, os.toByteArray()); 1513 } 1514 } 1515 1516 /** @hide */ 1517 public interface WriteMapCallback { 1518 /** 1519 * Called from writeMapXml when an Object type is not recognized. The implementer 1520 * must write out the entire element including start and end tags. 1521 * 1522 * @param v The object to be written out 1523 * @param name The mapping key for v. Must be written into the "name" attribute of the 1524 * start tag. 1525 * @param out The XML output stream. 1526 * @throws XmlPullParserException on unrecognized Object type. 1527 * @throws IOException on XmlSerializer serialization errors. 1528 * @hide 1529 */ 1530 public void writeUnknownObject(Object v, String name, XmlSerializer out) 1531 throws XmlPullParserException, IOException; 1532 } 1533 1534 /** @hide */ 1535 public interface ReadMapCallback { 1536 /** 1537 * Called from readThisMapXml when a START_TAG is not recognized. The input stream 1538 * is positioned within the start tag so that attributes can be read using in.getAttribute. 1539 * 1540 * @param in the XML input stream 1541 * @param tag the START_TAG that was not recognized. 1542 * @return the Object parsed from the stream which will be put into the map. 1543 * @throws XmlPullParserException if the START_TAG is not recognized. 1544 * @throws IOException on XmlPullParser serialization errors. 1545 * @hide 1546 */ 1547 public Object readThisUnknownObjectXml(XmlPullParser in, String tag) 1548 throws XmlPullParserException, IOException; 1549 } 1550 } 1551