Android Ivy ActionBarSherlock

2019-08-04 05:14发布

问题:

Is it possible to use the type "apklib" for an Ivy dependency?

In my project I'm using the ActionBarSherlock lib and I want to use Ivy for retrieving the dependency.

Here is my not working xml:

<dependency
    name="actionbarsherlock"
    conf="binaries"
    org="com.actionbarsherlock"
    rev="4.2.0"
    transitive="true"
    type="apklib" />

Thank you for your help!

回答1:

In this case, all that's needed is a simple dependency declaration as follows:

<dependency org="com.actionbarsherlock" name="actionbarsherlock" rev="4.2.0" conf="default"/>

Why? This Maven module is special, the Maven POM has been configured with a packaging set to the value "apklib". This means the module's main file is "actionbarsherlock-4.2.0.apklib" instead of the default .jar file.

What's confusing is that there is also a jar file published.......To retrieve this, you can add the special artifact tag:

<dependency org="com.actionbarsherlock" name="actionbarsherlock" rev="4.2.0" conf="default">
    <artifact name="actionbarsherlock" type="jar"/>
</dependency>

To see all the files published by this module I'd recommend Maven search.



回答2:

You can have for example in ivy.xml:

  <configurations>
    <conf name="compiling"/>
  </configurations>
  <dependencies>
    <dependency org="com.actionbarsherlock" name="actionbarsherlock" rev="4.3.1" conf="compiling->master"/>

Then if you use ant, in build.xml you could have a target which prepares these "apklib" files for you:

  <target name="ivy">
    <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpath="ivy-2.3.0.jar"/>
    <ivy:retrieve conf="compiling" type="apklib" pattern="libs/[artifact].apklib"/>
    <!-- For each apklib artifact you need to unpack it so you can use it. -->
    <unzip src="libs/actionbarsherlock.apklib" dest="apklibs/action-bar-sherlock"/>

Now you have src/, res/, etc of the library project in apklibs/action-bar-sherlock.

Here is a full build.xml example of how to build an APK of an Android app which depends on multiple Android library projects:

<?xml version="1.0" encoding="utf-8"?>

<project name="dev" default="release" xmlns:ivy="antlib:org.apache.ivy.ant">

  <!-- According to http://developer.android.com/sdk/requirements.html -->
  <property name="ant.build.javac.source" value="1.6"/>
  <property name="ant.build.javac.target" value="1.6"/>

  <property file="local.properties"/>
  <property file="project.properties" prefix="android.project"/>

  <property name="android.target.dir" value="${sdk.dir}/platforms/${android.project.target}"/>
  <property name="android.jar" value="${android.target.dir}/android.jar"/>
  <property name="apk.name" value="YOUR_APP.apk"/>
  <property name="out.dir" value="build/compiled"/>
  <property name="out.test-classes.dir" value="build/compiled-test"/>
  <property name="test.libs.dir" value="libs/test"/>

  <target name="clean">
    <delete dir="build"/>
    <delete dir="gen"/>
    <delete dir="apklibs"/>
    <delete file="${apk.name}"/>
  </target>

  <target name="ivy">
    <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpath="ivy-2.3.0.jar"/>
    <ivy:retrieve conf="compiling" type="bundle,jar" pattern="libs/[artifact].[ext]"/>
    <ivy:retrieve conf="compiling" type="apklib" pattern="libs/[artifact].apklib"/>
    <unzip src="libs/actionbarsherlock.apklib" dest="apklibs/action-bar-sherlock"/>
    <unzip src="libs/library.apklib" dest="apklibs/view-pager-indicator"/>
    <path id="lib.path.id">
      <fileset dir="libs" includes="*.jar"/>
    </path>
    <ivy:retrieve conf="compiling" type="source" pattern="sources/[artifact].[ext]" sync="true"/>
    <ivy:retrieve conf="packaging" type="bundle,jar" pattern="[artifact]-[revision].[ext]"/>
    <ivy:retrieve conf="testing" type="bundle,jar" pattern="libs/test/[artifact].[ext]"/>
  </target>

  <target name="-check-properties" unless="sdk.dir">
    <echo>
      You need to create a local.properties file with:
      storepass=...the password...
      sdk.dir=...path to Android SDK...
    </echo>
  </target>

  <target name="generate" depends="-check-properties">
    <mkdir dir="gen"/>
    <mkdir dir="build"/>
    <condition property="debug.mode" value="--debug-mode" else="">
      <istrue value="${debug}"/>
    </condition>
    <echo>debug=${debug}</echo>
    <echo>debug.mode=${debug.mode}</echo>
    <exec executable="${sdk.dir}/platform-tools/aapt" failonerror="true">
      <arg value="package"/>
      <arg line="${debug.mode}"/>
      <arg value="-f"/>
      <arg value="-m"/>
      <arg value="--auto-add-overlay"/>
      <arg value="-M"/>
      <arg file="AndroidManifest.xml"/>
      <arg value="-F"/>
      <arg file="build/resources.arsc"/>
      <arg value="-I"/>
      <arg file="${android.jar}"/>
      <arg value="-J"/>
      <arg file="gen"/>
      <arg value="-S"/>
      <arg file="facebook-android-sdk/facebook/res"/>
      <arg value="-S"/>
      <arg file="apklibs/view-pager-indicator/res"/>
      <arg value="-S"/>
      <arg file="barone/res"/>
      <arg value="-S"/>
      <arg file="apklibs/action-bar-sherlock/res"/>
      <arg value="-S"/>
      <arg file="res"/>
      <arg value="--extra-packages"/>
      <arg value="com.facebook.android:com.viewpagerindicator:com.triposo.barone:com.actionbarsherlock"/>
      <arg value="-A"/>
      <arg file="assets"/>
    </exec>
    <taskdef name="buildconfig" classname="com.android.ant.BuildConfigTask"
             classpath="${sdk.dir}/tools/lib/anttasks.jar"/>
    <buildconfig
        genFolder="gen"
        package="com.actionbarsherlock"
        buildType="${debug}"
        previousBuildType=""/>
    <buildconfig
        genFolder="gen"
        package="COM.YOUR.PACKAGE"
        buildType="${debug}"
        previousBuildType=""/>
  </target>

  <target name="compile" depends="clean, ivy, generate">
    <mkdir dir="${out.dir}"/>
    <javac destdir="${out.dir}" debug="true" includeantruntime="false">
      <src path="src"/>
      <src path="facebook-android-sdk/facebook/src"/>
      <src path="apklibs/view-pager-indicator/src"/>
      <src path="barone/src"/>
      <src path="apklibs/action-bar-sherlock/src"/>
      <src path="gen"/>
      <classpath>
        <path refid="lib.path.id"/>
        <pathelement path="${android.jar}"/>
      </classpath>
    </javac>
    <copy todir="${out.dir}">
      <fileset dir="src" excludes="**/*.java"/>
      <fileset dir="gen" excludes="**/*.java"/>
    </copy>
  </target>

  <target name="apk-unsigned" depends="compile">
    <!-- Prepare the .class files and the .properties files. -->
    <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask"
             classpath="jarjar-1.1.jar"/>
    <jarjar jarfile="build/app.jar" duplicate="preserve">
      <fileset dir="${out.dir}"/>
      <zipgroupfileset dir="libs" includes="*.jar"/>
      <keep pattern="COM.YOUR.PACKAGE.**"/>
      <keep pattern="com.amazonaws.**"/>
      <keep pattern="com.facebook.android.**"/>
      <keep pattern="com.google.android.apps.analytics.**"/>
      <keep pattern="com.google.gson.GsonBuilder"/>
      <keep pattern="com.google.common.base.Splitter"/>
      <keep pattern="com.google.common.io.Files"/>
      <keep pattern="com.google.common.base.Charsets"/>
      <keep pattern="javax.annotation.Nullable"/>
      <keep pattern="org.apache.commons.lang3.**"/>
      <keep pattern="android.support.v4.**"/>
      <!-- Required because these seem to be missing from the phone JVM
           and they are used by our CursorMapper. -->
      <keep pattern="javax.annotation.**"/>
      <!-- From http://actionbarsherlock.com/faq.html -->
      <keep pattern="com.actionbarsherlock.**"/>
      <keep pattern="*Annotation*"/>
      <rule pattern="com.google.common.**" result="COM.YOUR.PACKAGE.vendor.com.google.common.@1"/>
      <!-- We rename this because at least "HTC Sensation XL with Beats Audio"
           has a bad Gson library which we don't want to use. -->
      <rule pattern="com.google.gson.**" result="COM.YOUR.PACKAGE.vendor.com.google.gson.@1"/>
    </jarjar>
    <!-- Convert the .class files to Dalvik byte code. -->
    <exec executable="${sdk.dir}/platform-tools/dx" failonerror="true">
      <arg value="--dex"/>
      <arg value="--output=build/classes.dex"/>
      <arg file="build/app.jar"/>
    </exec>
    <!-- Package the resources and the classes into an apk. -->
    <taskdef name="apkbuilder" classname="com.android.ant.ApkBuilderTask"
             classpath="${sdk.dir}/tools/lib/anttasks.jar"/>
    <apkbuilder outfolder="."
                resourcefile="build/resources.arsc"
                apkfilepath="build/unsigned.apk"
                verbose="false">
      <dex path="build/classes.dex"/>
      <sourcefolder path="${out.dir}"/>
    </apkbuilder>
  </target>

  <!-- We need this because I use JDK 7, see the Caution in:
       http://developer.android.com/guide/publishing/app-signing.html#signapp
       Ant 1.8.3 allows specifying a sigalg and a digestalg, but
       I don't have it yet, so we have this macro instead. -->
  <macrodef name="signjarjdk7">
    <attribute name="jar" />
    <attribute name="signedjar" />
    <attribute name="keystore" />
    <attribute name="storepass" />
    <attribute name="alias" />
    <sequential>
      <exec executable="jarsigner" failonerror="true">
        <arg line="-digestalg SHA1 -sigalg MD5withRSA" />
        <arg line="-keystore @{keystore} -storepass @{storepass}" />
        <arg line="-signedjar &quot;@{signedjar}&quot;" />
        <arg line="&quot;@{jar}&quot; @{alias}" />
      </exec>
    </sequential>
  </macrodef>

  <macrodef name="zipalign">
    <attribute name="apk" />
    <attribute name="optimizedapk" />
    <sequential>
      <exec executable="${sdk.dir}/tools/zipalign" failonerror="true">
        <arg value="-f"/>
        <arg value="4"/>
        <arg file="@{apk}"/>
        <arg file="@{optimizedapk}"/>
      </exec>
    </sequential>
  </macrodef>

  <!-- Make an apk.
       See http://developer.android.com/guide/developing/building/index.html -->
  <macrodef name="apk">
    <attribute name="keystore"/>
    <attribute name="storepass"/>
    <attribute name="alias"/>
    <sequential>
      <antcall target="apk-unsigned"/>
      <!-- Sign the apk for release. -->
      <signjarjdk7
          keystore="@{keystore}" storepass="@{storepass}" alias="@{alias}"
          jar="build/unsigned.apk" signedjar="build/unaligned.apk"/>
      <!-- Optimize the apk to improve speed. -->
      <zipalign apk="build/unaligned.apk" optimizedapk="${apk.name}"/>
    </sequential>
  </macrodef>

  <target name="release">
    <property name="debug" value="false"/>
    <apk keystore="keystore" storepass="${storepass}" alias="YOUR ALIAS"/>
  </target>

  <target name="debug">
    <property name="debug" value="true"/>
    <apk keystore="debug.keystore" storepass="android" alias="androiddebugkey"/>
  </target>

  <target name="compile.tests" depends="compile">
    <mkdir dir="${out.test-classes.dir}"/>

    <javac encoding="ascii" source="1.6" target="1.6" debug="true" extdirs=""
           includeantruntime="false"
           destdir="${out.test-classes.dir}">
      <src path="test"/>
      <classpath>
        <pathelement path="${out.dir}"/>
        <path refid="lib.path.id"/>
        <fileset dir="${test.libs.dir}" includes="*.jar"/>
        <pathelement path="${android.jar}"/>
      </classpath>
    </javac>
  </target>

  <target name="test" depends="compile.tests">
    <mkdir dir="${basedir}/out/reports/tests"/>
    <junit showoutput="true" failureproperty="junit.failure">
      <formatter type="plain" usefile="false"/>
      <formatter type="xml"/>
      <batchtest todir="${basedir}/out/reports/tests">
        <fileset dir="test">
          <include name="**/*Test.java"/>
        </fileset>
      </batchtest>
      <classpath>
        <pathelement path="${out.dir}"/>
        <path refid="lib.path.id"/>
        <fileset dir="${test.libs.dir}" includes="*.jar"/>
        <pathelement path="${android.jar}"/>
        <pathelement path="${out.test-classes.dir}"/>
      </classpath>
    </junit>
    <fail if="junit.failure" message="Unit test(s) failed.  See reports!"/>
  </target>
</project>