Esempio n. 1
0
            public static Chunk Get(BinaryReader input)
            {
                if ((input.BaseStream.Remaining()) < HeaderMinSizeBytes)
                {
                    // Android ignores the last chunk if its header is too big to fit into the file
                    input.BaseStream.Position = input.BaseStream.Length;
                    return(null);
                }
                long originalPosition = input.BaseStream.Position;
                int  type             = input.ReadUInt16();
                int  headerSize       = input.ReadUInt16();
                long chunkSize        = input.ReadUInt32();
                long chunkRemaining   = chunkSize - 8;

                if (chunkRemaining > input.BaseStream.Remaining())
                {
                    // Android ignores the last chunk if it's too big to fit into the file
                    input.BaseStream.Position = input.BaseStream.Length;
                    return(null);
                }
                if (headerSize < HeaderMinSizeBytes)
                {
                    throw new FormatException(
                              "Malformed chunk: header too short: " + headerSize + " bytes");
                }
                else if (headerSize > chunkSize)
                {
                    throw new FormatException(
                              "Malformed chunk: header too long: " + headerSize + " bytes. Chunk size: "
                              + chunkSize + " bytes");
                }
                long  contentStartPosition = originalPosition + headerSize;
                long  chunkEndPosition     = originalPosition + chunkSize;
                Chunk chunk =
                    new Chunk(
                        type,
                        AndroidBinXmlParser.SliceFromTo(input.BaseStream, originalPosition, contentStartPosition),
                        AndroidBinXmlParser.SliceFromTo(input.BaseStream, contentStartPosition, chunkEndPosition));

                input.BaseStream.Position = chunkEndPosition;
                return(chunk);
            }
Esempio n. 2
0
        /// <summary>
        /// Returns the lowest Android platform version (API Level) supported by an APK with the
        /// provided  <code>AndroidManifest.xml</code>
        /// </summary>
        /// <param name="androidManifest">contents of <code>AndroidManifest.xml</code> in binary Android resource format</param>
        /// <returns></returns>
        public static int GetMinSdkVersionFromBinaryAndroidManifest(byte[] androidManifest)
        {
            // IMPLEMENTATION NOTE: Minimum supported Android platform version number is declared using
            // uses-sdk elements which are children of the top-level manifest element. uses-sdk element
            // declares the minimum supported platform version using the android:minSdkVersion attribute
            // whose default value is 1.
            // For each encountered uses-sdk element, the Android runtime checks that its minSdkVersion
            // is not higher than the runtime's API Level and rejects APKs if it is higher. Thus, the
            // effective minSdkVersion value is the maximum over the encountered minSdkVersion values.
            try
            {
                // If no uses-sdk elements are encountered, Android accepts the APK. We treat this
                // scenario as though the minimum supported API Level is 1.
                int result = 1;
                AndroidBinXmlParser parser = new AndroidBinXmlParser(androidManifest);
                var eventType = parser.EventType;
                while (eventType != AndroidBinXmlParser.EndOfDocument)
                {
                    if ((eventType == AndroidBinXmlParser.EventStartElement) &&
                        (parser.Depth == 2) &&
                        ("uses-sdk" == parser.Name) &&
                        (String.IsNullOrEmpty(parser.Namespace)))
                    {
                        // In each uses-sdk element, minSdkVersion defaults to 1
                        int minSdkVersion = 1;
                        for (int i = 0; i < parser.AttributeCount; i++)
                        {
                            if (parser.GetAttributeNameResourceId(i) == MinSdkVersionAttrId)
                            {
                                int valueType = parser.GetAttributeValueType(i);
                                switch (valueType)
                                {
                                case AndroidBinXmlParser.ValueTypeInt:
                                    minSdkVersion = parser.GetAttributeIntValue(i);
                                    break;

                                case AndroidBinXmlParser.ValueTypeString:
                                    minSdkVersion = GetMinSdkVersionForCodename(parser.GetAttributeStringValue(i));
                                    break;

                                default:
                                    throw new FormatException(
                                              "Unable to determine APK's minimum supported Android"
                                              + ": unsupported value type in "
                                              + AndroidManifestZipEntryName + "'s"
                                              + " minSdkVersion"
                                              + ". Only integer values supported.");
                                }
                                break;
                            }
                        }
                        result = Math.Max(result, minSdkVersion);
                    }
                    eventType = parser.Next();
                }
                return(result);
            }
            catch (Exception e)
            {
                throw new FormatException(
                          "Unable to determine APK's minimum supported Android platform version"
                          + ": malformed binary resource: " + AndroidManifestZipEntryName,
                          e);
            }
        }