我有一个Android库的问题。
我想从库org.apache.commons.codec.binary.Hex(版本1.6)使用方法Hex.encodeHexString(Byte Array)
在我的Android平台(SDK 2.3.1)上,commons-codec库版本1.3已经存在,但是在这个版本中还没有存在该方法(只有encodeHex())。
我添加了1.6版本的jar库到我的Eclipse项目(到/ libs目录下),但是当我在模拟器上运行这个项目时,我得到了这个:
E/AndroidRuntime(1632): FATAL EXCEPTION: main E/AndroidRuntime(1632): java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString
我怎么能指出操作系统在哪里好图书馆?
我在Mac OS X上使用Java 1.6.0的Eclipse Juno
对不起,我的英语不好,并提前致谢!
编辑:我的问题可以显然用jarjar工具解决。 http://code.google.com/p/google-http-java-client/issues/detail?id=75
有人可以帮我用这个工具? 我不知道如何创build一个Ant清单或jar文件。
谢谢
晚回复,但也许有用的人。
通过使用Maven Shade插件解决了问题
这个插件允许在编译时重命名冲突库的包名称。
用法:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <relocations> <relocation> <pattern>org.apache.commons</pattern> <shadedPattern>com.example.shaded.org.apache.commons</shadedPattern> </relocation> </relocations> <promoteTransitiveDependencies>true</promoteTransitiveDependencies> </configuration> </execution> </executions> </plugin>
nbe_42的答案的扩展版本,完整的文档…
commons-codec-shaded jar项目:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>commons-codec</groupId> <artifactId>commons-codec-shaded</artifactId> <name>Apache Commons Codec (shaded)</name> <!-- The version of this project specifies the Apache Commons Codec version which will be used, it must therefore match an existing (and preferably current) version. --> <version>1.9</version> <packaging>jar</packaging> <!-- ************************************************************* Rationale for this "shaded" version of Apache Commons Codec ************************************************************* Context: Android includes an outdated version (v1.3) of commons-codec as an internal library. This library is not exposed in the Android SDK so app developers who want to rely on commons-codec need to treat it as an addition dependency and include it in the APK of their app. However, at runtime Android will always favour its internal version of the library which causes trouble when app code tries to call methods that don't exist in v1.3 but do exist in the version the developer expected to be using. Solution: After experimenting with many different variations the current (and final) solution to this problem is implemented in this project and does not require big hacks or changes in projects which depend on commons-codec, expect for declaring dependency on commons-codec-shaded (ie this project) instead of the original commons-codec. What we do here is take the "original" commons-codec library (currently version 1.9) and use the maven-shade-plugin to "shade" it, which means we modify the package name of the library (both in the compiled classes and the sources jar) in order to avoid the clash with Android's version. The package name is changes from "org.apache.commons.codec" to "shaded.org.apache.commons.codec". The result is published to the local Maven repository for other projects to use by simple dependency declaration on this project. Because we only apply the shading to commons-codec itself (and not to other classes using it; which is possible using the shade plug-in but doesn't work in combination with android-maven-plugin) any client classes which make use of commons-codec will have to import the new "shaded" package name instead of the old one. Issue on android-maven-plugin github which I posted to discuss all this: https://github.com/jayway/maven-android-plugin/issues/487 --> <description> The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities. </description> <url>http://commons.apache.org/proper/commons-codec/</url> <organization> <name>The Apache Software Foundation</name> <url>http://www.apache.org/</url> </organization> <licenses> <license> <name>The Apache Software License, Version 2.0</name> <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> <distribution>repo</distribution> </license> </licenses> <contributors> <contributor> <name>Matthias Stevens</name> <email>m.stevens {at} ucl.ac.uk</email> <roles> <role>Shading for use on Android</role> </roles> </contributor> <!-- see commons-codec:commons-codec pom for original contributors/developers --> </contributors> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.source>1.6</maven.compiler.source> <maven.compiler.target>1.6</maven.compiler.target> <commons-codec-package>org.apache.commons.codec</commons-codec-package> <shading.prefix>shaded</shading.prefix> <shaded-commons-codec-package>${shading.prefix}.${commons-codec-package}</shaded-commons-codec-package> <commons-codec-src-folder>${project.build.directory}/commons-codec-src</commons-codec-src-folder> <commons-codec-res-folder>${project.build.directory}/commons-codec-res</commons-codec-res-folder> <manifest.path>${project.build.directory}/MANIFEST.MF</manifest.path> <!-- plugin versions --> <dependency-plugin-version>2.9</dependency-plugin-version> <compiler-plugin-version>3.2</compiler-plugin-version> <antrun-plugin-version>1.7</antrun-plugin-version> <jar-plugin-version>2.5</jar-plugin-version> <source-plugin-version>2.4</source-plugin-version> <shade-plugin-version>2.3</shade-plugin-version> <bundle-plugin-version>2.5.3</bundle-plugin-version> <!-- taken/modified from: http://svn.apache.org/repos/asf/commons/proper/commons-parent/trunk/pom.xml --> <commons.osgi.symbolicName>${shaded-commons-codec-package}</commons.osgi.symbolicName> <commons.osgi.export>${shaded-commons-codec-package}.*;version=${project.version};-noimport:=true</commons.osgi.export> <commons.osgi.import>*</commons.osgi.import> <commons.osgi.dynamicImport /> <commons.osgi.private /> </properties> <build> <finalName>${project.artifactId}</finalName> <sourceDirectory>${commons-codec-src-folder}</sourceDirectory> <resources> <resource> <!-- txt files in shaded\org\apache\commons\codec\language\bm --> <directory>${commons-codec-res-folder}</directory> <includes> <include>${shading.prefix}/**/*.txt</include> </includes> </resource> <resource> <!-- LICENSE & NOTICE files --> <directory>${commons-codec-res-folder}/META-INF</directory> <targetPath>META-INF</targetPath> <includes> <include>*.txt</include> </includes> </resource> </resources> <plugins> <plugin> <!-- fetch & unpack commons-codec sources and resources --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>${dependency-plugin-version}</version> <executions> <execution> <id>unpack_commons-codec_sources_and_resources</id> <phase>process-sources</phase> <goals> <goal>unpack</goal> </goals> <configuration> <artifactItems> <!-- commons-codec sources --> <artifactItem> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <!-- the project version specifies the commons-codec version to use: --> <version>${project.version}</version> <classifier>sources</classifier> <overWrite>true</overWrite> <excludes>**/*.txt,META-INF/*</excludes> <outputDirectory>${commons-codec-src-folder}</outputDirectory> </artifactItem> <!-- commons-codec resources (in package) --> <artifactItem> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <!-- the project version specifies the commons-codec version to use: --> <version>${project.version}</version> <classifier>sources</classifier> <overWrite>true</overWrite> <includes>org/**/*.txt</includes> <!-- apply shading: --> <outputDirectory>${commons-codec-res-folder}/${shading.prefix}</outputDirectory> </artifactItem> --> <!-- commons-codec resources (in META-INF) --> <artifactItem> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <!-- the project version specifies the commons-codec version to use: --> <version>${project.version}</version> <classifier>sources</classifier> <overWrite>true</overWrite> <includes>META-INF/*.txt</includes> <outputDirectory>${commons-codec-res-folder}</outputDirectory> </artifactItem> --> </artifactItems> </configuration> </execution> </executions> </plugin> <plugin> <!-- compile commons-codec sources --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${compiler-plugin-version}</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>${jar-plugin-version}</version> <executions> <execution> <!-- jar unshaded classes (& resources) --> <id>jar-unshaded</id> <phase>package</phase> <goals> <goal>jar</goal> </goals> </execution> <execution> <!-- rejar shaded classes (& resources), with proper manifest partially generated by bundle plugin --> <id>jar-shaded</id> <!-- runs after bundle plugin has done its work to generate bundle manifest --> <phase>post-integration-test</phase> <goals> <goal>jar</goal> </goals> <configuration> <archive> <manifestFile>${manifest.path}</manifestFile> <manifestEntries> <Specification-Title>${project.name}</Specification-Title> <Specification-Version>${project.version}</Specification-Version> <Specification-Vendor>${project.organization.name}</Specification-Vendor> <Implementation-Title>${project.name}</Implementation-Title> <Implementation-Version>${project.version}</Implementation-Version> <Implementation-Vendor>${project.organization.name}</Implementation-Vendor> <Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id> <Implementation-Build>${implementation.build}</Implementation-Build> <X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK> <X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK> </manifestEntries> </archive> </configuration> </execution> </executions> </plugin> <plugin> <!-- attach sources jar --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>${source-plugin-version}</version> <configuration> <archive> <manifest> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> </manifest> </archive> </configuration> <executions> <execution> <!-- jar unshaded sources --> <id>attach-unshaded-sources</id> <!-- <phase>package</phase> (default) --> <goals> <goal>jar</goal> </goals> </execution> <execution> <!-- rejar shaded sources --> <id>attach-shaded-sources</id> <phase>post-integration-test</phase> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <!-- apply the shading to main jar and sources jar --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>${shade-plugin-version}</version> <executions> <execution> <id>shading-main-jar-and-sources-jar</id> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <!-- (not needed as it is the one and only artifact/dependency) <artifactSet> <includes> <include>commons-codec:*</include> </includes> </artifactSet> --> <relocations> <relocation> <pattern>${commons-codec-package}</pattern> <shadedPattern>${shaded-commons-codec-package}</shadedPattern> </relocation> </relocations> <createDependencyReducedPom>false</createDependencyReducedPom> <!-- (only needed when dependency reduced pom is generated) <dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation> <keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope> <promoteTransitiveDependencies>true</promoteTransitiveDependencies> --> <createSourcesJar>true</createSourcesJar> <shadeSourcesContent>true</shadeSourcesContent> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>${antrun-plugin-version}</version> <executions> <execution> <!-- unpack shaded classes & sources for manifest generation and re-jarring --> <id>post-shading-tasks</id> <phase>package</phase> <goals> <goal>run</goal> </goals> <configuration> <target> <!-- Unjar shaded classes for generation of manifest --> <echo>Deleting unshaded classes...</echo> <delete dir="${project.build.directory}/classes"/> <echo>Unjarring shaded main jar...</echo> <unzip src="${project.build.directory}/${project.artifactId}.jar" dest="${project.build.directory}/classes"/> <!-- delete to prevent dual inclusion in new main jar --> <delete dir="${project.build.directory}/classes/META-INF/maven"/> <!-- Unjar shaded sources --> <echo>Deleting unshaded sources...</echo> <delete dir="${commons-codec-src-folder}"/> <echo>Unjarring shaded sources jar...</echo> <unzip src="${project.build.directory}/${project.artifactId}-sources.jar" dest="${commons-codec-src-folder}"/> <!-- delete to prevent dual inclusion in new sources jar --> <delete dir="${commons-codec-src-folder}/META-INF"/> </target> </configuration> </execution> <execution> <id>delete-orginals</id> <phase>verify</phase> <goals> <goal>run</goal> </goals> <configuration> <target> <echo>Deleting unshaded jar files...</echo> <delete> <fileset dir="${project.build.directory}" includes="**/original-*.jar" /> </delete> </target> </configuration> </execution> </executions> </plugin> <plugin> <!-- taken/modified from: http://svn.apache.org/repos/asf/commons/proper/commons-parent/trunk/pom.xml --> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>${bundle-plugin-version}</version> <configuration> <archive> <forced>true</forced> </archive> <excludeDependencies>true</excludeDependencies> <manifestLocation>${project.build.directory}</manifestLocation> <instructions> <!-- stops the "uses" clauses being added to "Export-Package" manifest entry --> <_nouses>true</_nouses> <!-- Stop the JAVA_1_n_HOME variables from being treated as headers by Bnd --> <_removeheaders>JAVA_1_3_HOME,JAVA_1_4_HOME,JAVA_1_5_HOME,JAVA_1_6_HOME,JAVA_1_7_HOME,JAVA_1_8_HOME</_removeheaders> <Bundle-SymbolicName>${commons.osgi.symbolicName}</Bundle-SymbolicName> <Export-Package>${commons.osgi.export}</Export-Package> <Private-Package>${commons.osgi.private}</Private-Package> <Import-Package>${commons.osgi.import}</Import-Package> <DynamicImport-Package>${commons.osgi.dynamicImport}</DynamicImport-Package> <Bundle-DocURL>${project.url}</Bundle-DocURL> </instructions> </configuration> <executions> <execution> <id>bundle-manifest</id> <!-- runs after the unjarring of the shaded classes --> <phase>integration-test</phase><!-- default is: process-classes --> <goals> <goal>manifest</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
在你想使用阴影库的(apk / apklib / aar / jar)项目中:
<!-- ... --> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec-shaded</artifactId> <version>1.9</version> </dependency> <!-- ... -->
这是由于与旧版(1.2)版本的Commons Codec产生的命名空间冲突,与Android打包的新版本相冲突。 虽然着色是一个很好的解决方法,但我认为从长远来看这不是一个可持续的解决方案。 这是Android中打包的任何开源库可能出现的系统性问题。 我向Google提交了一个问题。 如果你同意,我鼓励你“星”它,以便得到它需要的关注。 以下是链接 – https://code.google.com/p/android/issues/detail?id=160578
你有没有添加库到项目的构建路径? 当你这样做的时候,你应该可以从jar文件中调用这个方法。
如果没有添加库就可以生成OK,那么你可能正在构建一个更新版本的android,然后有效地部署到一个较旧的版本,我发现了String.isEmpty()
不是在2.1中的困难方式,但是当我编写代码它构建好,因为我正在建立对4.1
您可能需要将jar导出到您的项目中(也可以在配置构建路径时执行此操作)。
希望这可以帮助
关于nbe_42的maven遮罩插件,插件块放在pom.xml文件中是非常重要的,否则maven会错过它。
对我来说有效的是把它放在pom.xml的<build> <plugins>
块的末尾:
<build> <plugins> {all other plugins} ... {shade plugin} </plugins> </build>
原本我在开始的时候已经有了它,maven没有运行它。
要创建.jar文件,请从apache.org下载commons-codec-1.8-src.zip源.zip文件。 解压缩它。 pom.xml文件将位于归档的基本目录中。 像上面描述的那样将nbe_42的插件块插入到pom.xml文件中,然后运行:
mvn install
这将为您建立,测试,替换和安装插件。
成功的输出应该如下所示:
[INFO] --- maven-shade-plugin:2.2:shade (default) @ commons-codec --- [INFO] Replacing original artifact with shaded artifact. ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS ...`