mirror of
https://github.com/revanced/Apktool.git
synced 2024-12-12 13:57:46 +01:00
Merge branch 'master' into patch-1
This commit is contained in:
commit
8e00de38a0
2
.gitignore
vendored
2
.gitignore
vendored
@ -20,7 +20,7 @@ bin/
|
||||
# IntelliJ
|
||||
*.iml
|
||||
.idea/*
|
||||
/out
|
||||
**/out/
|
||||
|
||||
# Patches
|
||||
*.patch
|
29
.travis.yml
29
.travis.yml
@ -1,28 +1,35 @@
|
||||
env:
|
||||
- TERM=dumb GROOVY_TURN_OFF_JAVA_WARNINGS=true
|
||||
global:
|
||||
- TERM=dumb
|
||||
- GROOVY_TURN_OFF_JAVA_WARNINGS=true
|
||||
|
||||
language: java
|
||||
|
||||
dist: trusty
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
jdk: openjdk8
|
||||
# - os: linux
|
||||
# jdk: openjdk9
|
||||
- os: linux
|
||||
jdk: oraclejdk8
|
||||
# - os: linux
|
||||
# jdk: oraclejdk9
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
# - os: osx
|
||||
# osx_image: xcode9.4
|
||||
- os: windows
|
||||
language: shell
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
install: ./gradlew clean
|
||||
script: ./gradlew build shadowJar proguard
|
||||
|
||||
install:
|
||||
- chmod +x ./scripts/travis-ci/clean-tests.sh
|
||||
- ./scripts/travis-ci/clean-tests.sh
|
||||
|
||||
script:
|
||||
- chmod +x ./scripts/travis-ci/run-tests.sh
|
||||
- ./scripts/travis-ci/run-tests.sh
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- stable
|
||||
- master
|
@ -194,7 +194,7 @@ is just a guideline but helps me to release a new version every 3 months.
|
||||
### Social Spam
|
||||
|
||||
The final step is to send this release into the wild via some social posting. Head to the blog
|
||||
where the release post was and send that link to Twiter, Google and whatever else you use.
|
||||
where the release post was and send that link to Twitter, Google and whatever else you use.
|
||||
|
||||
Relax and watch the bug tracker.
|
||||
|
||||
@ -225,8 +225,8 @@ we aren't building the entire AOSP package, the initial build is to just see if
|
||||
|
||||
We check out a certain tag. Currently we use
|
||||
|
||||
* aapt2 - `android-9.0.0_r3`.
|
||||
* aapt1 - `android-9.0.0_r3`.
|
||||
* aapt2 - `android-9.0.0_r22`.
|
||||
* aapt1 - `android-9.0.0_r22`.
|
||||
|
||||
### Including our modified `frameworks/base` package.
|
||||
|
||||
@ -254,6 +254,7 @@ we lose the ability to quickly build just the aapt binary. So the Windows proced
|
||||
1. `source build/envsetup.sh`
|
||||
2. `lunch sdk-eng`
|
||||
3. `make OUT_DIR=out-x64 LOCAL_MULTILIB=64 USE_NINJA=false aapt`
|
||||
4. `strip out-x64/host/darwin-x86/bin/aapt_64`
|
||||
|
||||
As of Android Oreo (API 26) all aapt binaries are 64 bit (With exception of Windows).
|
||||
|
||||
@ -274,7 +275,7 @@ we lose the ability to quickly build just the aapt2 binary. So the Windows proce
|
||||
1. `export ANDROID_JAVA_HOME=/Path/To/Jdk`
|
||||
2. `source build/envsetup.sh`
|
||||
3. `make OUT_DIR=out-x64 LOCAL_MULTILIB=64 USE_NINJA=false aapt2`
|
||||
4. `strip out-x64/host/darwin-x86/bin/aapt2`
|
||||
4. `strip out-x64/host/darwin-x86/bin/aapt2_64`
|
||||
|
||||
#### Confirming aapt/aapt2 builds are static
|
||||
|
||||
|
@ -36,6 +36,9 @@ import java.util.logging.*;
|
||||
public class Main {
|
||||
public static void main(String[] args) throws IOException, InterruptedException, BrutException {
|
||||
|
||||
// headless
|
||||
System.setProperty("java.awt.headless", "true");
|
||||
|
||||
// set verbosity default
|
||||
Verbosity verbosity = Verbosity.NORMAL;
|
||||
|
||||
@ -218,12 +221,18 @@ public class Main {
|
||||
if (cli.hasOption("p") || cli.hasOption("frame-path")) {
|
||||
apkOptions.frameworkFolderLocation = cli.getOptionValue("p");
|
||||
}
|
||||
if (cli.hasOption("nc") || cli.hasOption("no-crunch")) {
|
||||
apkOptions.noCrunch = true;
|
||||
}
|
||||
|
||||
// Temporary flag to enable the use of aapt2. This will tranform in time to a use-aapt1 flag, which will be
|
||||
// legacy and eventually removed.
|
||||
if (cli.hasOption("use-aapt2")) {
|
||||
apkOptions.useAapt2 = true;
|
||||
}
|
||||
if (cli.hasOption("api") || cli.hasOption("api-level")) {
|
||||
apkOptions.forceApi = Integer.parseInt(cli.getOptionValue("api"));
|
||||
}
|
||||
if (cli.hasOption("o") || cli.hasOption("output")) {
|
||||
outFile = new File(cli.getOptionValue("o"));
|
||||
} else {
|
||||
@ -397,6 +406,11 @@ public class Main {
|
||||
.desc("Copies original AndroidManifest.xml and META-INF. See project page for more info.")
|
||||
.build();
|
||||
|
||||
Option noCrunchOption = Option.builder("nc")
|
||||
.longOpt("no-crunch")
|
||||
.desc("Disable crunching of resource files during the build step.")
|
||||
.build();
|
||||
|
||||
Option tagOption = Option.builder("t")
|
||||
.longOpt("tag")
|
||||
.desc("Tag frameworks using <tag>.")
|
||||
@ -439,6 +453,7 @@ public class Main {
|
||||
BuildOptions.addOption(aaptOption);
|
||||
BuildOptions.addOption(originalOption);
|
||||
BuildOptions.addOption(aapt2Option);
|
||||
BuildOptions.addOption(noCrunchOption);
|
||||
}
|
||||
|
||||
// add global options
|
||||
@ -492,6 +507,7 @@ public class Main {
|
||||
allOptions.addOption(verboseOption);
|
||||
allOptions.addOption(quietOption);
|
||||
allOptions.addOption(aapt2Option);
|
||||
allOptions.addOption(noCrunchOption);
|
||||
}
|
||||
|
||||
private static String verbosityHelp() {
|
||||
|
@ -416,7 +416,7 @@ public class Androlib {
|
||||
if (apkOptions.forceBuildAll || isModified(smaliDir, dex)) {
|
||||
LOGGER.info("Smaling " + folder + " folder into " + filename + "...");
|
||||
dex.delete();
|
||||
SmaliBuilder.build(smaliDir, dex, mMinSdkVersion);
|
||||
SmaliBuilder.build(smaliDir, dex, apkOptions.forceApi > 0 ? apkOptions.forceApi : mMinSdkVersion);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -377,6 +377,25 @@ public class ApkDecoder {
|
||||
private void putSdkInfo(MetaInfo meta) throws AndrolibException {
|
||||
Map<String, String> info = getResTable().getSdkInfo();
|
||||
if (info.size() > 0) {
|
||||
String refValue;
|
||||
if (info.get("minSdkVersion") != null) {
|
||||
refValue = ResXmlPatcher.pullValueFromIntegers(mOutDir, info.get("minSdkVersion"));
|
||||
if (refValue != null) {
|
||||
info.put("minSdkVersion", refValue);
|
||||
}
|
||||
}
|
||||
if (info.get("targetSdkVersion") != null) {
|
||||
refValue = ResXmlPatcher.pullValueFromIntegers(mOutDir, info.get("targetSdkVersion"));
|
||||
if (refValue != null) {
|
||||
info.put("targetSdkVersion", refValue);
|
||||
}
|
||||
}
|
||||
if (info.get("maxSdkVersion") != null) {
|
||||
refValue = ResXmlPatcher.pullValueFromIntegers(mOutDir, info.get("maxSdkVersion"));
|
||||
if (refValue != null) {
|
||||
info.put("maxSdkVersion", refValue);
|
||||
}
|
||||
}
|
||||
meta.sdkInfo = info;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ public class ApkOptions {
|
||||
public boolean isFramework = false;
|
||||
public boolean resourcesAreCompressed = false;
|
||||
public boolean useAapt2 = false;
|
||||
public boolean noCrunch = false;
|
||||
public int forceApi = 0;
|
||||
public Collection<String> doNotCompress;
|
||||
|
||||
public String frameworkFolderLocation = null;
|
||||
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (C) 2018 Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
* Copyright (C) 2018 Connor Tumbleson <connor.tumbleson@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package brut.androlib.err;
|
||||
|
||||
import brut.androlib.AndrolibException;
|
||||
|
||||
public class AXmlDecodingException extends AndrolibException {
|
||||
|
||||
public AXmlDecodingException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public AXmlDecodingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public AXmlDecodingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AXmlDecodingException() {
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (C) 2018 Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
* Copyright (C) 2018 Connor Tumbleson <connor.tumbleson@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package brut.androlib.err;
|
||||
|
||||
import brut.androlib.AndrolibException;
|
||||
|
||||
public class RawXmlEncounteredException extends AndrolibException {
|
||||
|
||||
public RawXmlEncounteredException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public RawXmlEncounteredException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public RawXmlEncounteredException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RawXmlEncounteredException() {
|
||||
}
|
||||
}
|
@ -29,14 +29,14 @@ import org.jf.smali.*;
|
||||
*/
|
||||
public class SmaliMod {
|
||||
|
||||
public static boolean assembleSmaliFile(String smali, DexBuilder dexBuilder, boolean verboseErrors,
|
||||
public static boolean assembleSmaliFile(String smali, DexBuilder dexBuilder, int apiLevel, boolean verboseErrors,
|
||||
boolean printTokens, File smaliFile) throws IOException, RuntimeException, RecognitionException {
|
||||
|
||||
InputStream is = new ByteArrayInputStream(smali.getBytes());
|
||||
return assembleSmaliFile(is, dexBuilder, verboseErrors, printTokens, smaliFile);
|
||||
return assembleSmaliFile(is, dexBuilder, apiLevel, verboseErrors, printTokens, smaliFile);
|
||||
}
|
||||
|
||||
public static boolean assembleSmaliFile(InputStream is,DexBuilder dexBuilder, boolean verboseErrors,
|
||||
public static boolean assembleSmaliFile(InputStream is,DexBuilder dexBuilder, int apiLevel, boolean verboseErrors,
|
||||
boolean printTokens, File smaliFile) throws IOException, RecognitionException {
|
||||
|
||||
// copy our filestream into a tmp file, so we don't overwrite
|
||||
@ -47,10 +47,10 @@ public class SmaliMod {
|
||||
IOUtils.copy(is, os);
|
||||
os.close();
|
||||
|
||||
return assembleSmaliFile(tmp,dexBuilder, verboseErrors, printTokens);
|
||||
return assembleSmaliFile(tmp,dexBuilder, apiLevel, verboseErrors, printTokens);
|
||||
}
|
||||
|
||||
public static boolean assembleSmaliFile(File smaliFile,DexBuilder dexBuilder, boolean verboseErrors,
|
||||
public static boolean assembleSmaliFile(File smaliFile,DexBuilder dexBuilder, int apiLevel, boolean verboseErrors,
|
||||
boolean printTokens) throws IOException, RecognitionException {
|
||||
|
||||
CommonTokenStream tokens;
|
||||
@ -77,6 +77,7 @@ public class SmaliMod {
|
||||
}
|
||||
|
||||
smaliParser parser = new smaliParser(tokens);
|
||||
parser.setApiLevel(apiLevel);
|
||||
parser.setVerboseErrors(verboseErrors);
|
||||
|
||||
smaliParser.smali_file_return result = parser.smali_file();
|
||||
@ -93,7 +94,7 @@ public class SmaliMod {
|
||||
treeStream.setTokenStream(tokens);
|
||||
|
||||
smaliTreeWalker dexGen = new smaliTreeWalker(treeStream);
|
||||
|
||||
dexGen.setApiLevel(apiLevel);
|
||||
dexGen.setVerboseErrors(verboseErrors);
|
||||
dexGen.setDexBuilder(dexBuilder);
|
||||
dexGen.smali_file();
|
||||
|
@ -350,6 +350,10 @@ final public class AndrolibResources {
|
||||
cmd.add("-v");
|
||||
}
|
||||
|
||||
if (apkOptions.noCrunch) {
|
||||
cmd.add("--no-crunch");
|
||||
}
|
||||
|
||||
try {
|
||||
OS.exec(cmd.toArray(new String[0]));
|
||||
LOGGER.fine("aapt2 compile command ran: ");
|
||||
@ -485,6 +489,9 @@ final public class AndrolibResources {
|
||||
if (apkOptions.debugMode) { // inject debuggable="true" into manifest
|
||||
cmd.add("--debug-mode");
|
||||
}
|
||||
if (apkOptions.noCrunch) {
|
||||
cmd.add("--no-crunch");
|
||||
}
|
||||
// force package id so that some frameworks build with correct id
|
||||
// disable if user adds own aapt (can't know if they have this feature)
|
||||
if (mPackageId != null && ! customAapt && ! mSharedLibrary) {
|
||||
|
@ -24,6 +24,11 @@ import java.util.*;
|
||||
* @author Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
*/
|
||||
public final class ResTypeSpec {
|
||||
|
||||
public static final String RES_TYPE_NAME_ARRAY = "array";
|
||||
public static final String RES_TYPE_NAME_PLURALS = "plurals";
|
||||
public static final String RES_TYPE_NAME_STYLES = "style";
|
||||
|
||||
private final String mName;
|
||||
private final Map<String, ResResSpec> mResSpecs = new LinkedHashMap<String, ResResSpec>();
|
||||
|
||||
|
@ -83,6 +83,13 @@ public abstract class ResScalarValue extends ResIntBasedValue implements
|
||||
}
|
||||
}
|
||||
|
||||
// Android does not allow values (false) for ids.xml anymore
|
||||
// https://issuetracker.google.com/issues/80475496
|
||||
// But it decodes as a ResBoolean, which makes no sense. So force it to empty
|
||||
if (type.equalsIgnoreCase("id") && !body.isEmpty()) {
|
||||
body = "";
|
||||
}
|
||||
|
||||
// check for using attrib as node or item
|
||||
String tagName = item ? "item" : type;
|
||||
|
||||
|
@ -19,6 +19,7 @@ package brut.androlib.res.data.value;
|
||||
import android.util.TypedValue;
|
||||
import brut.androlib.AndrolibException;
|
||||
import brut.androlib.res.data.ResPackage;
|
||||
import brut.androlib.res.data.ResTypeSpec;
|
||||
import brut.util.Duo;
|
||||
|
||||
/**
|
||||
@ -41,7 +42,7 @@ public class ResValueFactory {
|
||||
}
|
||||
return new ResReferenceValue(mPackage, 0, null);
|
||||
case TypedValue.TYPE_REFERENCE:
|
||||
return newReference(value, rawValue);
|
||||
return newReference(value, null);
|
||||
case TypedValue.TYPE_ATTRIBUTE:
|
||||
return newReference(value, rawValue, true);
|
||||
case TypedValue.TYPE_STRING:
|
||||
@ -83,7 +84,7 @@ public class ResValueFactory {
|
||||
return new ResStringValue(value, rawValue);
|
||||
}
|
||||
|
||||
public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items) throws AndrolibException {
|
||||
public ResBagValue bagFactory(int parent, Duo<Integer, ResScalarValue>[] items, ResTypeSpec resTypeSpec) throws AndrolibException {
|
||||
ResReferenceValue parentVal = newReference(parent, null);
|
||||
|
||||
if (items.length == 0) {
|
||||
@ -93,14 +94,25 @@ public class ResValueFactory {
|
||||
if (key == ResAttr.BAG_KEY_ATTR_TYPE) {
|
||||
return ResAttr.factory(parentVal, items, this, mPackage);
|
||||
}
|
||||
// Android O Preview added an unknown enum for ResTable_map. This is hardcoded as 0 for now.
|
||||
if (key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) {
|
||||
|
||||
String resTypeName = resTypeSpec.getName();
|
||||
|
||||
// Android O Preview added an unknown enum for c. This is hardcoded as 0 for now.
|
||||
if (ResTypeSpec.RES_TYPE_NAME_ARRAY.equals(resTypeName)
|
||||
|| key == ResArrayValue.BAG_KEY_ARRAY_START || key == 0) {
|
||||
return new ResArrayValue(parentVal, items);
|
||||
}
|
||||
if (key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END) {
|
||||
|
||||
if (ResTypeSpec.RES_TYPE_NAME_PLURALS.equals(resTypeName) ||
|
||||
(key >= ResPluralsValue.BAG_KEY_PLURALS_START && key <= ResPluralsValue.BAG_KEY_PLURALS_END)) {
|
||||
return new ResPluralsValue(parentVal, items);
|
||||
}
|
||||
return new ResStyleValue(parentVal, items, this);
|
||||
|
||||
if (ResTypeSpec.RES_TYPE_NAME_STYLES.equals(resTypeName)) {
|
||||
return new ResStyleValue(parentVal, items, this);
|
||||
}
|
||||
|
||||
throw new AndrolibException("unsupported res type name for bags. Found: " + resTypeName);
|
||||
}
|
||||
|
||||
public ResReferenceValue newReference(int resID, String rawValue) {
|
||||
|
@ -347,7 +347,7 @@ public class ARSCDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
return factory.bagFactory(parent, items);
|
||||
return factory.bagFactory(parent, items, mTypeSpec);
|
||||
}
|
||||
|
||||
private ResIntBasedValue readValue() throws IOException, AndrolibException {
|
||||
|
@ -852,7 +852,7 @@ public class AXmlResourceParser implements XmlResourceParser {
|
||||
private final void doNext() throws IOException {
|
||||
// Delayed initialization.
|
||||
if (m_strings == null) {
|
||||
m_reader.skipCheckInt(CHUNK_AXML_FILE);
|
||||
m_reader.skipCheckInt(CHUNK_AXML_FILE, CHUNK_AXML_FILE_BROKEN);
|
||||
|
||||
/*
|
||||
* chunkSize
|
||||
@ -1004,7 +1004,7 @@ public class AXmlResourceParser implements XmlResourceParser {
|
||||
ATTRIBUTE_IX_VALUE_TYPE = 3, ATTRIBUTE_IX_VALUE_DATA = 4,
|
||||
ATTRIBUTE_LENGTH = 5;
|
||||
|
||||
private static final int CHUNK_AXML_FILE = 0x00080003,
|
||||
private static final int CHUNK_AXML_FILE = 0x00080003, CHUNK_AXML_FILE_BROKEN = 0x00080001,
|
||||
CHUNK_RESOURCEIDS = 0x00080180, CHUNK_XML_FIRST = 0x00100100,
|
||||
CHUNK_XML_START_NAMESPACE = 0x00100100,
|
||||
CHUNK_XML_END_NAMESPACE = 0x00100101,
|
||||
|
@ -65,13 +65,21 @@ public class Res9patchStreamDecoder implements ResStreamDecoder {
|
||||
drawVLine(im2, w + 1, np.padTop + 1, h - np.padBottom);
|
||||
|
||||
int[] xDivs = np.xDivs;
|
||||
for (int i = 0; i < xDivs.length; i += 2) {
|
||||
drawHLine(im2, 0, xDivs[i] + 1, xDivs[i + 1]);
|
||||
if (xDivs.length == 0) {
|
||||
drawHLine(im2, 0, 1, w);
|
||||
} else {
|
||||
for (int i = 0; i < xDivs.length; i += 2) {
|
||||
drawHLine(im2, 0, xDivs[i] + 1, xDivs[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
int[] yDivs = np.yDivs;
|
||||
for (int i = 0; i < yDivs.length; i += 2) {
|
||||
drawVLine(im2, 0, yDivs[i] + 1, yDivs[i + 1]);
|
||||
if (yDivs.length == 0) {
|
||||
drawVLine(im2, 0, 1, h);
|
||||
} else {
|
||||
for (int i = 0; i < yDivs.length; i += 2) {
|
||||
drawVLine(im2, 0, yDivs[i] + 1, yDivs[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Some images additionally use Optical Bounds
|
||||
|
@ -18,6 +18,7 @@ package brut.androlib.res.decoder;
|
||||
|
||||
import brut.androlib.AndrolibException;
|
||||
import brut.androlib.err.CantFind9PatchChunk;
|
||||
import brut.androlib.err.RawXmlEncounteredException;
|
||||
import brut.androlib.res.data.ResResource;
|
||||
import brut.androlib.res.data.value.ResBoolValue;
|
||||
import brut.androlib.res.data.value.ResFileValue;
|
||||
@ -118,6 +119,11 @@ public class ResFileDecoder {
|
||||
}
|
||||
|
||||
decode(inDir, inFileName, outDir, outFileName, "xml");
|
||||
} catch (RawXmlEncounteredException ex) {
|
||||
// If we got an error to decode XML, lets assume the file is in raw format.
|
||||
// This is a large assumption, that might increase runtime, but will save us for situations where
|
||||
// XSD files are AXML`d on aapt1, but left in plaintext in aapt2.
|
||||
decode(inDir, inFileName, outDir, outFileName, "raw");
|
||||
} catch (AndrolibException ex) {
|
||||
LOGGER.log(Level.SEVERE, String.format(
|
||||
"Could not decode file, replacing by FALSE value: %s",
|
||||
|
@ -19,8 +19,9 @@ package brut.androlib.res.decoder;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import brut.androlib.err.AXmlDecodingException;
|
||||
import brut.androlib.err.RawXmlEncounteredException;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.wrapper.XmlPullParserWrapper;
|
||||
@ -142,9 +143,9 @@ public class XmlPullStreamDecoder implements ResStreamDecoder {
|
||||
}
|
||||
ser.flush();
|
||||
} catch (XmlPullParserException ex) {
|
||||
throw new AndrolibException("Could not decode XML", ex);
|
||||
throw new AXmlDecodingException("Could not decode XML", ex);
|
||||
} catch (IOException ex) {
|
||||
throw new AndrolibException("Could not decode XML", ex);
|
||||
throw new RawXmlEncounteredException("Could not decode XML", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,6 +156,4 @@ public class XmlPullStreamDecoder implements ResStreamDecoder {
|
||||
|
||||
private final XmlPullParser mParser;
|
||||
private final ExtXmlSerializer mSerial;
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(XmlPullStreamDecoder.class.getName());
|
||||
}
|
||||
|
@ -197,6 +197,41 @@ public final class ResXmlPatcher {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds key in integers.xml file and returns text value
|
||||
*
|
||||
* @param directory Root directory of apk
|
||||
* @param key Integer reference (ie @integer/foo)
|
||||
* @return String|null
|
||||
* @throws AndrolibException
|
||||
*/
|
||||
public static String pullValueFromIntegers(File directory, String key) throws AndrolibException {
|
||||
if (key == null || ! key.contains("@")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
File file = new File(directory, "/res/values/integers.xml");
|
||||
key = key.replace("@integer/", "");
|
||||
|
||||
if (file.exists()) {
|
||||
try {
|
||||
Document doc = loadDocument(file);
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
XPathExpression expression = xPath.compile("/resources/integer[@name=" + '"' + key + "\"]/text()");
|
||||
|
||||
Object result = expression.evaluate(doc, XPathConstants.STRING);
|
||||
|
||||
if (result != null) {
|
||||
return (String) result;
|
||||
}
|
||||
|
||||
} catch (SAXException | ParserConfigurationException | IOException | XPathExpressionException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes attributes like "versionCode" and "versionName" from file.
|
||||
*
|
||||
|
@ -71,7 +71,7 @@ public class SmaliBuilder {
|
||||
|
||||
if (fileName.endsWith(".smali")) {
|
||||
try {
|
||||
if (!SmaliMod.assembleSmaliFile(inFile, dexBuilder, false, false)) {
|
||||
if (!SmaliMod.assembleSmaliFile(inFile, dexBuilder, mApiLevel, false, false)) {
|
||||
throw new AndrolibException("Could not smali file: " + fileName);
|
||||
}
|
||||
} catch (IOException | RecognitionException ex) {
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt
Executable file
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2
Executable file
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2_64
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt2_64
Executable file
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt_64
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/linux/aapt_64
Executable file
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt2_64
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt2_64
Executable file
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt_64
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/macosx/aapt_64
Executable file
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt.exe
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt.exe
Executable file
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2.exe
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2.exe
Executable file
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2_64.exe
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt2_64.exe
Executable file
Binary file not shown.
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt_64.exe
Executable file
BIN
brut.apktool/apktool-lib/src/main/resources/prebuilt/windows/aapt_64.exe
Executable file
Binary file not shown.
@ -198,6 +198,16 @@ public class BuildAndDecodeTest extends BaseTest {
|
||||
compareXmlFiles("res/xml/references.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlXsdFileTest() throws BrutException {
|
||||
compareXmlFiles("res/xml/ww_box_styles_schema.xsd");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlIdsEmptyTest() throws BrutException {
|
||||
compareXmlFiles("res/values/ids.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlReferenceAttributeTest() throws BrutException {
|
||||
compareXmlFiles("res/layout/issue1040.xml");
|
||||
@ -231,7 +241,7 @@ public class BuildAndDecodeTest extends BaseTest {
|
||||
@Test
|
||||
public void qualifiersTest() throws BrutException {
|
||||
compareValuesFiles("values-mcc004-mnc4-en-rUS-ldrtl-sw100dp-w200dp-h300dp"
|
||||
+ "-xlarge-long-round-highdr-land-desk-night-xhdpi-finger-keyssoft-12key"
|
||||
+ "-long-round-highdr-land-desk-night-xhdpi-finger-keyssoft-12key"
|
||||
+ "-navhidden-dpad-v26/strings.xml");
|
||||
}
|
||||
|
||||
|
@ -77,8 +77,8 @@ public class DebugTagRetainedTest extends BaseTest {
|
||||
|
||||
String expected = TestUtils.replaceNewlines("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>" +
|
||||
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" android:compileSdkVersion=\"23\" " +
|
||||
"android:compileSdkVersionCodename=\"6.0-2438415\" package=\"com.ibotpeaches.issue1235\" platformBuildVersionCode=\"23\" " +
|
||||
"platformBuildVersionName=\"6.0-2438415\"> <application android:debuggable=\"true\"/></manifest>");
|
||||
"android:compileSdkVersionCodename=\"6.0-2438415\" package=\"com.ibotpeaches.issue1235\" platformBuildVersionCode=\"20\" " +
|
||||
"platformBuildVersionName=\"4.4W.2-1537038\"> <application android:debuggable=\"true\"/></manifest>");
|
||||
|
||||
byte[] encoded = Files.readAllBytes(Paths.get(sTmpDir + File.separator + apk + File.separator + "AndroidManifest.xml"));
|
||||
String obtained = TestUtils.replaceNewlines(new String(encoded));
|
||||
|
@ -72,7 +72,7 @@ public class ProviderAttributeTest extends BaseTest {
|
||||
apkDecoder.decode();
|
||||
|
||||
String expected = TestUtils.replaceNewlines("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n" +
|
||||
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" android:compileSdkVersion=\"23\" android:compileSdkVersionCodename=\"6.0-2438415\" package=\"com.ibotpeaches.issue636\" platformBuildVersionCode=\"23\" platformBuildVersionName=\"6.0-2438415\">\n" +
|
||||
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" android:compileSdkVersion=\"23\" android:compileSdkVersionCodename=\"6.0-2438415\" package=\"com.ibotpeaches.issue636\" platformBuildVersionCode=\"22\" platformBuildVersionName=\"5.1-1756733\">\n" +
|
||||
" <application android:allowBackup=\"true\" android:debuggable=\"true\" android:icon=\"@mipmap/ic_launcher\" android:label=\"@string/app_name\" android:theme=\"@style/AppTheme\">\n" +
|
||||
" <provider android:authorities=\"com.ibotpeaches.issue636.Provider\" android:exported=\"false\" android:grantUriPermissions=\"true\" android:label=\"@string/app_name\" android:multiprocess=\"false\" android:name=\"com.ibotpeaches.issue636.Provider\"/>\n" +
|
||||
" <provider android:authorities=\"com.ibotpeaches.issue636.ProviderTwo\" android:exported=\"false\" android:grantUriPermissions=\"true\" android:label=\"@string/app_name\" android:multiprocess=\"false\" android:name=\"com.ibotpeaches.issue636.ProviderTwo\"/>\n" +
|
||||
|
@ -84,6 +84,11 @@ public class BuildAndDecodeTest extends BaseTest {
|
||||
compareXmlFiles("res/navigation/nav_graph.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlIdsEmptyTest() throws BrutException {
|
||||
compareXmlFiles("res/values/ids.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leadingDollarSignResourceNameTest() throws BrutException {
|
||||
compareXmlFiles("res/drawable/$avd_hide_password__0.xml");
|
||||
@ -93,4 +98,9 @@ public class BuildAndDecodeTest extends BaseTest {
|
||||
public void confirmManifestStructureTest() throws BrutException {
|
||||
compareXmlFiles("AndroidManifest.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlXsdFileTest() throws BrutException {
|
||||
compareXmlFiles("res/xml/ww_box_styles_schema.xsd");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
package brut.androlib.decode;
|
||||
|
||||
import brut.androlib.ApkDecoder;
|
||||
import brut.androlib.BaseTest;
|
||||
import brut.androlib.TestUtils;
|
||||
import brut.androlib.res.data.ResTable;
|
||||
import brut.androlib.res.data.value.ResArrayValue;
|
||||
import brut.androlib.res.data.value.ResValue;
|
||||
import brut.common.BrutException;
|
||||
import brut.directory.ExtFile;
|
||||
import brut.util.OS;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
public class DecodeArrayTest extends BaseTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
TestUtils.cleanFrameworkFile();
|
||||
sTmpDir = new ExtFile(OS.createTempDirectory());
|
||||
TestUtils.copyResourceDir(MissingVersionManifestTest.class, "decode/issue1994/", sTmpDir);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws BrutException {
|
||||
OS.rmdir(sTmpDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decodeStringArray() throws BrutException {
|
||||
String apk = "issue1994.apk";
|
||||
ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk));
|
||||
|
||||
ResTable resTable = apkDecoder.getResTable();
|
||||
ResValue value = resTable.getResSpec(0x7f020001).getDefaultResource().getValue();
|
||||
|
||||
assertTrue("Not a ResArrayValue. Found: " + value.getClass(), value instanceof ResArrayValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decodeArray() throws BrutException {
|
||||
String apk = "issue1994.apk";
|
||||
ApkDecoder apkDecoder = new ApkDecoder(new File(sTmpDir + File.separator + apk));
|
||||
|
||||
ResTable resTable = apkDecoder.getResTable();
|
||||
ResValue value = resTable.getResSpec(0x7f020000).getDefaultResource().getValue();
|
||||
|
||||
assertTrue("Not a ResArrayValue. Found: " + value.getClass(), value instanceof ResArrayValue);
|
||||
}
|
||||
}
|
@ -64,7 +64,7 @@ public class ExternalEntityTest extends BaseTest {
|
||||
|
||||
String expected = TestUtils.replaceNewlines("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
|
||||
"<manifest android:versionCode=\"1\" android:versionName=\"1.0\" android:compileSdkVersion=\"23\" android:compileSdkVersionCodename=\"6.0-2438415\" " +
|
||||
"hardwareAccelerated=\"true\" package=\"com.ibotpeaches.doctype\" platformBuildVersionCode=\"23\" platformBuildVersionName=\"6.0-2438415\" " +
|
||||
"hardwareAccelerated=\"true\" package=\"com.ibotpeaches.doctype\" platformBuildVersionCode=\"24\" platformBuildVersionName=\"6.0-2456767\" " +
|
||||
"xmlns:android=\"http://schemas.android.com/apk/res/android\"> <supports-screens android:anyDensity=\"true\" android:smallScreens=\"true\" " +
|
||||
"android:normalScreens=\"true\" android:largeScreens=\"true\" android:resizeable=\"true\" android:xlargeScreens=\"true\" /></manifest>");
|
||||
|
||||
|
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (C) 2018 Ryszard Wiśniewski <brut.alll@gmail.com>
|
||||
* Copyright (C) 2018 Connor Tumbleson <connor.tumbleson@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package brut.androlib.decode;
|
||||
|
||||
import brut.androlib.BaseTest;
|
||||
import brut.androlib.TestUtils;
|
||||
import brut.androlib.res.decoder.Res9patchStreamDecoder;
|
||||
import brut.common.BrutException;
|
||||
import brut.directory.ExtFile;
|
||||
import brut.util.OS;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class MissingDiv9PatchTest extends BaseTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
TestUtils.cleanFrameworkFile();
|
||||
sTmpDir = new ExtFile(OS.createTempDirectory());
|
||||
TestUtils.copyResourceDir(MissingDiv9PatchTest.class, "decode/issue1522/", sTmpDir);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() throws BrutException {
|
||||
OS.rmdir(sTmpDir);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertMissingDivAdded() throws Exception {
|
||||
InputStream inputStream = getFileInputStream();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
||||
Res9patchStreamDecoder decoder = new Res9patchStreamDecoder();
|
||||
decoder.decode(inputStream, outputStream);
|
||||
|
||||
BufferedImage image = ImageIO.read(new ByteArrayInputStream(outputStream.toByteArray()));
|
||||
int height = image.getHeight() - 1;
|
||||
|
||||
// First and last pixel will be invisible, so lets check the first column and ensure its all black
|
||||
for (int y = 1; y < height; y++) {
|
||||
assertEquals("y coordinate failed at: " + y, NP_COLOR, image.getRGB(0, y));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private FileInputStream getFileInputStream() throws IOException {
|
||||
File file = new File(sTmpDir, "pip_dismiss_scrim.9.png");
|
||||
return new FileInputStream(file.toPath().toString());
|
||||
}
|
||||
|
||||
private static final int NP_COLOR = 0xff000000;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<resources>
|
||||
<item type="id" name="test_attr1" />
|
||||
</resources>
|
@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<public type="string" name="hello_world" id="0x7f020000" />
|
||||
<public type="xml" name="ww_box_styles_schema" id="0x7f1500df" />
|
||||
</resources>
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="test">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="person" type="xs:string"/>
|
||||
<xs:element name="address">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="name" type="xs:string"/>
|
||||
<xs:element name="address" type="xs:string"/>
|
||||
<xs:element name="city" type="xs:string"/>
|
||||
<xs:element name="country" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<resources>
|
||||
<attr format="integer" name="test_attr1"/>
|
||||
</resources>
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<resources>
|
||||
<item type="id" name="test_attr1" />
|
||||
</resources>
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="test">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="person" type="xs:string"/>
|
||||
<xs:element name="address">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="name" type="xs:string"/>
|
||||
<xs:element name="address" type="xs:string"/>
|
||||
<xs:element name="city" type="xs:string"/>
|
||||
<xs:element name="country" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
Binary file not shown.
After Width: | Height: | Size: 230 B |
Binary file not shown.
@ -35,17 +35,20 @@ public class AaptManager {
|
||||
File aaptBinary;
|
||||
String aaptVersion = getAaptBinaryName(version);
|
||||
|
||||
if (! OSDetection.is64Bit() && ! OSDetection.isWindows()) {
|
||||
if (! OSDetection.is64Bit() && OSDetection.isMacOSX()) {
|
||||
throw new BrutException("32 bit OS detected. No 32 bit binaries available.");
|
||||
}
|
||||
|
||||
// Set the 64 bit flag
|
||||
aaptVersion += OSDetection.is64Bit() ? "_64" : "";
|
||||
|
||||
try {
|
||||
if (OSDetection.isMacOSX()) {
|
||||
aaptBinary = Jar.getResourceAsFile("/prebuilt/" + aaptVersion + "/macosx/" + aaptVersion, AaptManager.class);
|
||||
aaptBinary = Jar.getResourceAsFile("/prebuilt/macosx/" + aaptVersion, AaptManager.class);
|
||||
} else if (OSDetection.isUnix()) {
|
||||
aaptBinary = Jar.getResourceAsFile("/prebuilt/" + aaptVersion + "/linux/" + aaptVersion, AaptManager.class);
|
||||
aaptBinary = Jar.getResourceAsFile("/prebuilt/linux/" + aaptVersion, AaptManager.class);
|
||||
} else if (OSDetection.isWindows()) {
|
||||
aaptBinary = Jar.getResourceAsFile("/prebuilt/" + aaptVersion + "/windows/" + aaptVersion + ".exe", AaptManager.class);
|
||||
aaptBinary = Jar.getResourceAsFile("/prebuilt/windows/" + aaptVersion + ".exe", AaptManager.class);
|
||||
} else {
|
||||
throw new BrutException("Could not identify platform: " + OSDetection.returnOS());
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ public class ExtDataInput extends DataInputDelegate {
|
||||
skipBytes(4);
|
||||
}
|
||||
|
||||
public void skipCheckInt(int expected) throws IOException {
|
||||
public void skipCheckInt(int expected1, int expected2) throws IOException {
|
||||
int got = readInt();
|
||||
if (got != expected) {
|
||||
if (got != expected1 && got != expected2) {
|
||||
throw new IOException(String.format(
|
||||
"Expected: 0x%08x, got: 0x%08x", expected, got));
|
||||
"Expected: 0x%08x or 0x%08x, got: 0x%08x", expected1, expected2, got));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ subprojects {
|
||||
|
||||
ext {
|
||||
depends = [
|
||||
baksmali: 'org.smali:baksmali:2.2.5',
|
||||
baksmali: 'org.smali:baksmali:2.2.6',
|
||||
commons_cli: 'commons-cli:commons-cli:1.4',
|
||||
commons_io: 'commons-io:commons-io:2.4',
|
||||
commons_lang: 'org.apache.commons:commons-lang3:3.1',
|
||||
@ -115,7 +115,7 @@ subprojects {
|
||||
junit: 'junit:junit:4.12',
|
||||
proguard_gradle: 'net.sf.proguard:proguard-gradle:6.0.3',
|
||||
snakeyaml: 'org.yaml:snakeyaml:1.18:android',
|
||||
smali: 'org.smali:smali:2.2.5',
|
||||
smali: 'org.smali:smali:2.2.6',
|
||||
xmlpull: 'xpp3:xpp3:1.1.4c',
|
||||
xmlunit: 'xmlunit:xmlunit:1.6',
|
||||
]
|
||||
|
12
scripts/travis-ci/clean-tests.sh
Executable file
12
scripts/travis-ci/clean-tests.sh
Executable file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
|
||||
export GRADLE_OPTS=-Dorg.gradle.daemon=false
|
||||
choco install jdk8
|
||||
export PATH=$PATH:"/c/Program Files/Java/jdk1.8.0_201/bin"
|
||||
./gradlew.bat clean
|
||||
else
|
||||
./gradlew clean
|
||||
fi
|
||||
|
||||
exit $?
|
@ -1,2 +1,11 @@
|
||||
#!/usr/bin/env sh
|
||||
./gradlew build shadowJar
|
||||
|
||||
if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then
|
||||
export GRADLE_OPTS=-Dorg.gradle.daemon=false
|
||||
export PATH=$PATH:"/c/Program Files/Java/jdk1.8.0_201/bin"
|
||||
./gradlew.bat build shadowJar proguard
|
||||
else
|
||||
./gradlew build shadowJar proguard
|
||||
fi
|
||||
|
||||
exit $?
|
Loading…
Reference in New Issue
Block a user