Пример #1
0
  /**
   * read String pool, for apk binary xml file and resource table.
   *
   * @param in
   * @param stringPoolHeader
   * @return
   * @throws IOException
   */
  public static StringPool readStringPool(TellableInputStream in, StringPoolHeader stringPoolHeader)
      throws IOException {

    long beginPos = in.tell();
    long[] offsets = new long[(int) stringPoolHeader.stringCount];
    // read strings offset
    if (stringPoolHeader.stringCount > 0) {
      for (int idx = 0; idx < stringPoolHeader.stringCount; idx++) {
        offsets[idx] = in.readUInt();
      }
    }
    // read flag
    boolean sorted = (stringPoolHeader.flags & StringPoolHeader.SORTED_FLAG) != 0;
    StringEncoding stringEncoding =
        (stringPoolHeader.flags & StringPoolHeader.UTF8_FLAG) != 0
            ? StringEncoding.UTF8
            : StringEncoding.UTF16;

    // read strings. the head and metas have 28 bytes
    long stringPos = beginPos + stringPoolHeader.stringsStart - stringPoolHeader.headerSize;
    in.advanceIfNotRearch(stringPos);

    StringPoolEntry[] entries = new StringPoolEntry[offsets.length];
    for (int i = 0; i < offsets.length; i++) {
      entries[i] = new StringPoolEntry(i, stringPos + offsets[i]);
    }
    Arrays.sort(entries);

    String lastStr = null;
    long lastOffset = -1;
    StringPool stringPool = new StringPool((int) stringPoolHeader.stringCount);
    for (StringPoolEntry entry : entries) {
      if (entry.getOffset() == lastOffset) {
        stringPool.set(entry.getIdx(), lastStr);
        continue;
      }

      in.advanceIfNotRearch(entry.getOffset());
      lastOffset = entry.getOffset();
      String str = ParseUtils.readString(in, stringEncoding);
      lastStr = str;
      stringPool.set(entry.getIdx(), str);
    }

    // read styles
    if (stringPoolHeader.styleCount > 0) {
      // now we just skip it
    }

    in.advanceIfNotRearch(beginPos + stringPoolHeader.chunkSize - stringPoolHeader.headerSize);

    return stringPool;
  }
Пример #2
0
  /**
   * read res value, convert from different types to string.
   *
   * @param in
   * @param stringPool
   * @return
   * @throws IOException
   */
  public static ResValue readResValue(
      TellableInputStream in,
      StringPool stringPool,
      ResourceTable resourceTable,
      boolean isStyle,
      Locale locale)
      throws IOException {
    ResValue resValue = new ResValue();
    resValue.size = in.readUShort();
    resValue.res0 = in.readUByte();
    resValue.dataType = in.readUByte();

    switch (resValue.dataType) {
      case ResValue.ResType.INT_DEC:
      case ResValue.ResType.INT_HEX:
        resValue.data = String.valueOf(in.readInt());
        break;
      case ResValue.ResType.STRING:
        int strRef = in.readInt();
        if (strRef > 0) {
          resValue.data = stringPool.get(strRef);
        }
        break;
      case ResValue.ResType.REFERENCE:
        long resourceId = in.readUInt();
        resValue.data = getResourceByid(resourceId, isStyle, resourceTable, locale);
        break;
      case ResValue.ResType.INT_BOOLEAN:
        resValue.data = String.valueOf(in.readInt() != 0);
        break;
      case ResValue.ResType.NULL:
        resValue.data = "";
        break;
      case ResValue.ResType.INT_COLOR_RGB8:
      case ResValue.ResType.INT_COLOR_RGB4:
        resValue.data = readRGBs(in, 6);
        break;
      case ResValue.ResType.INT_COLOR_ARGB8:
      case ResValue.ResType.INT_COLOR_ARGB4:
        resValue.data = readRGBs(in, 8);
        break;
      case ResValue.ResType.DIMENSION:
        resValue.data = getDemension(in);
        break;
      case ResValue.ResType.FRACTION:
        resValue.data = getFraction(in);
        break;
      default:
        resValue.data = "{" + resValue.dataType + ":" + in.readUInt() + "}";
    }
    return resValue;
  }