View Javadoc

1   package com.jayway.maven.plugins.android;
2   
3   import com.jayway.maven.plugins.android.configuration.Zipalign;
4   import org.apache.maven.plugin.MojoExecutionException;
5   
6   import java.io.File;
7   import java.util.ArrayList;
8   import java.util.List;
9   
10  import static com.jayway.maven.plugins.android.common.AndroidExtension.APK;
11  
12  /**
13   * Implementation for the zipaplign goal. Implements parsing parameters from pom or command line arguments and sets
14   * useful defaults as well.
15   *
16   * @author Manfred Moser <manfred@simpligility.com>
17   */
18  public abstract class AbstractZipalignMojo extends AbstractAndroidMojo
19  {
20  
21      /**
22       * The configuration for the zipalign goal. As soon as a zipalign goal is invoked the command will be executed
23       * unless the skip parameter is set. By default the input file is the apk produced by the build in target. The
24       * outputApk will use the postfix -aligned.apk. The following shows a default full configuration of the zipalign
25       * goal as an example for changes as plugin configuration.
26       * <pre>
27       * &lt;zipalign&gt;
28       *     &lt;skip&gt;false&lt;/skip&gt;
29       *     &lt;verbose&gt;true&lt;/verbose&gt;
30       *     &lt;inputApk&gt;${project.build.directory}/${project.artifactId}.apk&lt;/inputApk&gt;
31       *     &lt;outputApk&gt;${project.build.directory}/${project.artifactId}-aligned.apk&lt;/outputApk&gt;
32       * &lt;/zipalign&gt;
33       * </pre>
34       * <p/>
35       * Values can also be configured as properties on the command line as android.zipalign.*
36       * or in pom or settings file as properties like zipalign.*.
37       *
38       * @parameter
39       */
40      private Zipalign zipalign;
41  
42      /**
43       * Skip the zipalign goal execution.
44       *
45       * @parameter expression="${android.zipalign.skip}"
46       * @see com.jayway.maven.plugins.android.configuration.Zipalign#skip
47       */
48      private Boolean zipalignSkip;
49  
50      /**
51       * Activate verbose output for the zipalign goal execution.
52       *
53       * @parameter expression="${android.zipalign.verbose}"
54       * @see com.jayway.maven.plugins.android.configuration.Zipalign#verbose
55       */
56      private Boolean zipalignVerbose;
57  
58      /**
59       * The apk file to be zipaligned. Per default the file is taken from build directory (target normally) using the
60       * build final name as file name and apk as extension.
61       *
62       * @parameter expression="${android.zipalign.inputApk}"
63       * @see com.jayway.maven.plugins.android.configuration.Zipalign#inputApk
64       */
65      private String zipalignInputApk;
66  
67      /**
68       * The apk file produced by the zipalign goal. Per default the file is placed into the build directory (target
69       * normally) using the build final name appended with "-aligned" as file name and apk as extension.
70       *
71       * @parameter expression="${android.zipalign.outputApk}"
72       * @see com.jayway.maven.plugins.android.configuration.Zipalign#outputApk
73       */
74      private String zipalignOutputApk;
75  
76      private Boolean parsedSkip;
77      private Boolean parsedVerbose;
78      private String parsedInputApk;
79      private String parsedOutputApk;
80  
81      /**
82       * the apk file to be zipaligned.
83       */
84      private File apkFile;
85      /**
86       * the output apk file for the zipalign process.
87       */
88      private File alignedApkFile;
89  
90      /**
91       * actually do the zipalign
92       *
93       * @throws MojoExecutionException
94       */
95      protected void zipalign() throws MojoExecutionException
96      {
97  
98          // If we're not on a supported packaging with just skip (Issue 87)
99          // http://code.google.com/p/maven-android-plugin/issues/detail?id=87
100         if ( ! SUPPORTED_PACKAGING_TYPES.contains( project.getPackaging() ) )
101         {
102             getLog().info( "Skipping zipalign on " + project.getPackaging() );
103             return;
104         }
105 
106         parseParameters();
107         if ( parsedSkip )
108         {
109             getLog().info( "Skipping zipalign" );
110         }
111         else
112         {
113             CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
114             executor.setLogger( this.getLog() );
115 
116             String command = getAndroidSdk().getZipalignPath();
117 
118             List<String> parameters = new ArrayList<String>();
119             if ( parsedVerbose )
120             {
121                 parameters.add( "-v" );
122             }
123             parameters.add( "-f" ); // force overwriting existing output file
124             parameters.add( "4" ); // byte alignment has to be 4!
125             parameters.add( parsedInputApk );
126             parameters.add( parsedOutputApk );
127 
128             try
129             {
130                 getLog().info( "Running command: " + command );
131                 getLog().info( "with parameters: " + parameters );
132                 executor.executeCommand( command, parameters );
133 
134                 // Attach the resulting artifact (Issue 88)
135                 // http://code.google.com/p/maven-android-plugin/issues/detail?id=88
136                 File aligned = new File( parsedOutputApk );
137                 if ( aligned.exists() )
138                 {
139                     projectHelper.attachArtifact( project, APK, "aligned", aligned );
140                     getLog().info( "Attach " + aligned.getAbsolutePath() + " to the project" );
141                 }
142                 else
143                 {
144                     getLog().error( "Cannot attach " + aligned.getAbsolutePath() + " to the project - the file does "
145                             + "not exist" );
146                 }
147             }
148             catch ( ExecutionException e )
149             {
150                 throw new MojoExecutionException( "", e );
151             }
152         }
153     }
154 
155     private void parseParameters()
156     {
157         getLog().debug( "Parsing parameters" );
158         // <zipalign> exist in pom file
159         if ( zipalign != null )
160         {
161             // <zipalign><skip> exists in pom file
162             if ( zipalign.isSkip() != null )
163             {
164                 parsedSkip = zipalign.isSkip();
165             }
166             else
167             {
168                 parsedSkip = determineSkip();
169             }
170 
171             // <zipalign><verbose> exists in pom file
172             if ( zipalign.isVerbose() != null )
173             {
174                 parsedVerbose = zipalign.isVerbose();
175             }
176             else
177             {
178                 parsedVerbose = determineVerbose();
179             }
180 
181             // <zipalign><inputApk> exists in pom file
182             if ( zipalign.getInputApk() != null )
183             {
184                 parsedInputApk = zipalign.getInputApk();
185             }
186             else
187             {
188                 parsedInputApk = determineInputApk();
189             }
190 
191 
192             // <zipalign><outputApk> exists in pom file
193             if ( zipalign.getOutputApk() != null )
194             {
195                 parsedOutputApk = zipalign.getOutputApk();
196             }
197             else
198             {
199                 parsedOutputApk = determineOutputApk();
200             }
201 
202         }
203         // command line options
204         else
205         {
206             parsedSkip = determineSkip();
207             parsedVerbose = determineVerbose();
208             parsedInputApk = determineInputApk();
209             parsedOutputApk = determineOutputApk();
210         }
211 
212         getLog().debug( "skip:" + parsedSkip );
213         getLog().debug( "verbose:" + parsedVerbose );
214         getLog().debug( "inputApk:" + parsedInputApk );
215         getLog().debug( "outputApk:" + parsedOutputApk );
216     }
217 
218     /**
219      * Get skip value for zipalign from command line option.
220      *
221      * @return if available return command line value otherwise return default false.
222      */
223     private Boolean determineSkip()
224     {
225         Boolean enabled;
226         if ( zipalignSkip != null )
227         {
228             enabled = zipalignSkip;
229         }
230         else
231         {
232             getLog().debug( "Using default for zipalign.skip=false" );
233             enabled = Boolean.FALSE;
234         }
235         return enabled;
236     }
237 
238     /**
239      * Get verbose value for zipalign from command line option.
240      *
241      * @return if available return command line value otherwise return default false.
242      */
243     private Boolean determineVerbose()
244     {
245         Boolean enabled;
246         if ( zipalignVerbose != null )
247         {
248             enabled = zipalignVerbose;
249         }
250         else
251         {
252             getLog().debug( "Using default for zipalign.verbose=false" );
253             enabled = Boolean.FALSE;
254         }
255         return enabled;
256     }
257 
258     /**
259      * Gets the apk file location from basedir/target/finalname.apk
260      *
261      * @return absolute path.
262      */
263     private String getApkLocation()
264     {
265         if ( apkFile == null )
266         {
267             apkFile = new File( project.getBuild().getDirectory(), project.getBuild().getFinalName() + "." + APK );
268         }
269         return apkFile.getAbsolutePath();
270     }
271 
272     /**
273      * Gets the apk file location from basedir/target/finalname-aligned.apk. "-aligned" is the inserted string for the
274      * output file.
275      *
276      * @return absolute path.
277      */
278     private String getAlignedApkLocation()
279     {
280         if ( alignedApkFile == null )
281         {
282             alignedApkFile = new File( project.getBuild().getDirectory(),
283                     project.getBuild().getFinalName() + "-aligned." + APK );
284         }
285         return alignedApkFile.getAbsolutePath();
286     }
287 
288     /**
289      * Get inputApk value for zipalign from command line option.
290      *
291      * @return if available return command line value otherwise return default.
292      */
293     private String determineInputApk()
294     {
295         String inputApk;
296         if ( zipalignInputApk != null )
297         {
298             inputApk = zipalignInputApk;
299         }
300         else
301         {
302             String inputPath = getApkLocation();
303             getLog().debug( "Using default for zipalign.inputApk: " + inputPath );
304             inputApk = inputPath;
305         }
306         return inputApk;
307     }
308 
309     /**
310      * Get outputApk value for zipalign from command line option.
311      *
312      * @return if available return command line value otherwise return default.
313      */
314     private String determineOutputApk()
315     {
316         String outputApk;
317         if ( zipalignOutputApk != null )
318         {
319             outputApk = zipalignOutputApk;
320         }
321         else
322         {
323             String outputPath = getAlignedApkLocation();
324             getLog().debug( "Using default for zipalign.outputApk: " + outputPath );
325             outputApk = outputPath;
326         }
327         return outputApk;
328     }
329 
330 }