All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jayway.maven.plugins.android.standalonemojos.ZipalignMojo Maven / Gradle / Ivy

There is a newer version: 4.0.0-rc.2
Show newest version
package com.jayway.maven.plugins.android.standalonemojos;

import com.jayway.maven.plugins.android.AbstractAndroidMojo;
import com.jayway.maven.plugins.android.CommandExecutor;
import com.jayway.maven.plugins.android.ExecutionException;
import com.jayway.maven.plugins.android.config.ConfigHandler;
import com.jayway.maven.plugins.android.config.ConfigPojo;
import com.jayway.maven.plugins.android.config.PullParameter;
import com.jayway.maven.plugins.android.configuration.Zipalign;
import org.apache.commons.io.FilenameUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.util.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.jayway.maven.plugins.android.common.AndroidExtension.APK;

/**
 * ZipalignMojo can run the zipalign command against the apk. Implements parsing parameters from pom or command line
 * arguments and sets useful defaults as well.
 *
 * @author Manfred Moser 
 * @goal zipalign
 * @requiresProject true
 */
public class ZipalignMojo extends AbstractAndroidMojo 
{

    /**
     * The configuration for the zipalign goal. As soon as a zipalign goal is invoked the command will be executed
     * unless the skip parameter is set. By default the input file is the apk produced by the build in target. The
     * outputApk will use the postfix -aligned.apk. The following shows a default full configuration of the zipalign
     * goal as an example for changes as plugin configuration.
     * 
     * <zipalign>
     *     <skip>false</skip>
     *     <verbose>true</verbose>
     *     <inputApk>${project.build.directory}/${project.finalName}.apk</inputApk>
     *     <outputApk>${project.build.directory}/${project.finalName}-aligned.apk</outputApk>
     * </zipalign>
     * 
* * Values can also be configured as properties on the command line as android.zipalign.* * or in pom or settings file as properties like zipalign.*. * @parameter */ @ConfigPojo private Zipalign zipalign; /** * Skip the zipalign goal execution. Defaults to "true". * @parameter expression="${android.zipalign.skip}" * @see com.jayway.maven.plugins.android.configuration.Zipalign#skip */ private Boolean zipalignSkip; @PullParameter( defaultValue = "true" ) private Boolean parsedSkip; /** * Activate verbose output for the zipalign goal execution. Defaults to "false". * @parameter expression="${android.zipalign.verbose}" * @see com.jayway.maven.plugins.android.configuration.Zipalign#verbose */ private Boolean zipalignVerbose; @PullParameter( defaultValue = "false" ) private Boolean parsedVerbose; /** * The apk file to be zipaligned. Per default the file is taken from build directory (target normally) using the * build final name as file name and apk as extension. * * @parameter expression="${android.zipalign.inputApk}" * @see com.jayway.maven.plugins.android.configuration.Zipalign#inputApk */ private String zipalignInputApk; @PullParameter ( defaultValueGetterMethod = "getInputApkPath" ) private String parsedInputApk; /** * The apk file produced by the zipalign goal. Per default the file is placed into the build directory (target * normally) using the build final name appended with "-aligned" as file name and apk as extension. * * @parameter expression="${android.zipalign.outputApk}" * @see com.jayway.maven.plugins.android.configuration.Zipalign#outputApk */ private String zipalignOutputApk; @PullParameter( defaultValueGetterMethod = "getOutputApkPath" ) private String parsedOutputApk; /** * the apk file to be zipaligned. */ private File apkFile; /** * the output apk file for the zipalign process. */ private File alignedApkFile; /** * Execute the mojo by parsing the confign and actually doing the zipalign. * * @throws MojoExecutionException */ public void execute() throws MojoExecutionException, MojoFailureException { // If we're not on a supported packaging with just skip (Issue 87) // http://code.google.com/p/maven-android-plugin/issues/detail?id=87 if ( ! SUPPORTED_PACKAGING_TYPES.contains( project.getPackaging() ) ) { getLog().info( "Skipping zipalign on " + project.getPackaging() ); return; } ConfigHandler configHandler = new ConfigHandler( this ); configHandler.parseConfiguration(); parsedInputApk = FilenameUtils.separatorsToSystem( parsedInputApk ); parsedOutputApk = FilenameUtils.separatorsToSystem( parsedOutputApk ); getLog().debug( "skip:" + parsedSkip ); getLog().debug( "verbose:" + parsedVerbose ); getLog().debug( "inputApk:" + parsedInputApk ); getLog().debug( "outputApk:" + parsedOutputApk ); if ( parsedSkip ) { getLog().info( "Skipping zipalign" ); } else { boolean outputToSameFile = sameOutputAsInput(); CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor(); executor.setLogger( this.getLog() ); String command = getAndroidSdk().getZipalignPath(); List parameters = new ArrayList(); if ( parsedVerbose ) { parameters.add( "-v" ); } parameters.add( "-f" ); // force overwriting existing output file parameters.add( "4" ); // byte alignment has to be 4! parameters.add( parsedInputApk ); String outputApk = outputToSameFile ? getTemporaryOutputApkFilename() : parsedOutputApk; parameters.add( outputApk ); try { getLog().info( "Running command: " + command ); getLog().info( "with parameters: " + parameters ); executor.executeCommand( command, parameters ); if ( FileUtils.fileExists( outputApk ) ) { if ( outputToSameFile ) { // No needs to attach zipaligned apk to artifacts try { FileUtils.rename( new File( outputApk ), new File( parsedInputApk ) ); } catch ( IOException e ) { getLog().error( "Failed to replace original apk with aligned " + getFullPathWithName( outputApk ), e ); } } else { // Attach the resulting artifact (Issue 88) // http://code.google.com/p/maven-android-plugin/issues/detail?id=88 projectHelper.attachArtifact( project, APK, "aligned", new File( outputApk ) ); getLog().info( "Attach " + getFullPathWithName( outputApk ) + " to the project" ); } } else { getLog().error( "Cannot attach " + getFullPathWithName( outputApk ) + " to the project" + " - The file does not exist" ); } } catch ( ExecutionException e ) { throw new MojoExecutionException( "", e ); } } } private String getFullPathWithName( String filename ) { return FilenameUtils.getFullPath( filename ) + FilenameUtils.getName( filename ); } private boolean sameOutputAsInput() { return getFullPathWithName( parsedInputApk ).equals( getFullPathWithName( parsedOutputApk ) ); } // zipalign doesn't allow output file to be same as input private String getTemporaryOutputApkFilename() { return parsedOutputApk.substring( 0, parsedOutputApk.lastIndexOf( '.' ) ) + "-aligned-temp.apk"; } /** * Gets the apk file location from basedir/target/finalname.apk * * @return absolute path. */ // used via PullParameter annotation - do not remove private String getInputApkPath() { if ( apkFile == null ) { apkFile = new File( project.getBuild().getDirectory(), project.getBuild().getFinalName() + "." + APK ); } return apkFile.getAbsolutePath(); } /** * Gets the apk file location from basedir/target/finalname-aligned.apk. "-aligned" is the inserted string for the * output file. * * @return absolute path. */ // used via PullParameter annotation - do not remove private String getOutputApkPath() { if ( alignedApkFile == null ) { alignedApkFile = new File( project.getBuild().getDirectory(), project.getBuild().getFinalName() + "-aligned." + APK ); } return alignedApkFile.getAbsolutePath(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy