1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.simpligility.maven.plugins.android.phase09package;
18
19 import com.simpligility.maven.plugins.android.AbstractAndroidMojo;
20 import com.simpligility.maven.plugins.android.CommandExecutor;
21 import com.simpligility.maven.plugins.android.ExecutionException;
22 import com.simpligility.maven.plugins.android.common.AaptCommandBuilder;
23 import com.simpligility.maven.plugins.android.common.AndroidExtension;
24 import com.simpligility.maven.plugins.android.common.NativeHelper;
25 import com.simpligility.maven.plugins.android.config.PullParameter;
26
27 import org.apache.commons.io.FileUtils;
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.maven.artifact.Artifact;
30 import org.apache.maven.model.Resource;
31 import org.apache.maven.plugin.MojoExecutionException;
32 import org.apache.maven.plugin.MojoFailureException;
33 import org.apache.maven.plugins.annotations.LifecyclePhase;
34 import org.apache.maven.plugins.annotations.Mojo;
35 import org.apache.maven.plugins.annotations.Parameter;
36 import org.apache.maven.plugins.annotations.ResolutionScope;
37 import org.codehaus.plexus.archiver.ArchiverException;
38 import org.codehaus.plexus.archiver.jar.JarArchiver;
39 import org.codehaus.plexus.archiver.util.DefaultFileSet;
40
41 import java.io.File;
42 import java.io.FilenameFilter;
43 import java.io.IOException;
44 import java.util.ArrayList;
45 import java.util.List;
46
47 import static com.simpligility.maven.plugins.android.common.AndroidExtension.AAR;
48 import static com.simpligility.maven.plugins.android.common.AndroidExtension.APKLIB;
49
50
51
52
53
54
55
56
57
58 @Deprecated
59 @Mojo( name = "apklib", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE )
60 public class ApklibMojo extends AbstractAndroidMojo
61 {
62
63
64
65
66 public static final String NATIVE_LIBRARIES_FOLDER = "libs";
67
68
69
70
71 @Parameter
72 private String classifier;
73
74
75
76
77 @Parameter
78 @PullParameter
79 private String applicationMakefile;
80
81
82
83
84 @Parameter( property = "android.ndk.build.architecture" )
85 @PullParameter
86 private String ndkArchitecture;
87
88
89
90
91 @Parameter( property = "android.ndk.build.native-classifier" )
92 @PullParameter
93 private String ndkClassifier;
94
95 private List<String> sourceFolders = new ArrayList<String>();
96
97
98
99
100
101 public void execute() throws MojoExecutionException, MojoFailureException
102 {
103 String out = targetDirectory.getPath();
104 for ( String src : project.getCompileSourceRoots() )
105 {
106 if ( !src.startsWith( out ) )
107 {
108 sourceFolders.add( src );
109 }
110 }
111
112 generateIntermediateApk();
113
114 File outputFile = createApkLibraryFile();
115
116 if ( classifier == null )
117 {
118
119 project.getArtifact().setFile( outputFile );
120 }
121 else
122 {
123
124 projectHelper.attachArtifact( project, AndroidExtension.APKLIB, classifier, outputFile );
125 }
126
127 if ( attachJar )
128 {
129 final File jarFile = new File( targetDirectory,
130 finalName + ".jar" );
131 projectHelper.attachArtifact( project, "jar", project.getArtifact().getClassifier(), jarFile );
132 }
133 }
134
135 private File createApkLibraryFile() throws MojoExecutionException
136 {
137 final File apklibrary = new File( targetDirectory,
138 finalName + "." + APKLIB );
139 FileUtils.deleteQuietly( apklibrary );
140
141 try
142 {
143 JarArchiver jarArchiver = new JarArchiver();
144 jarArchiver.setDestFile( apklibrary );
145
146 jarArchiver.addFile( destinationManifestFile, "AndroidManifest.xml" );
147 addDirectory( jarArchiver, assetsDirectory, "assets" );
148 addDirectory( jarArchiver, resourceDirectory, "res" );
149
150 for ( String src : sourceFolders )
151 {
152 addDirectory( jarArchiver, new File( src ), "src" );
153 }
154
155 File[] overlayDirectories = getResourceOverlayDirectories();
156 for ( File resOverlayDir : overlayDirectories )
157 {
158 if ( resOverlayDir != null && resOverlayDir.exists() )
159 {
160 addDirectory( jarArchiver, resOverlayDir, "res" );
161 }
162 }
163
164 addJavaResources( jarArchiver, resources, "src" );
165
166
167 addNativeLibraries( jarArchiver );
168
169 jarArchiver.createArchive();
170 }
171 catch ( ArchiverException e )
172 {
173 throw new MojoExecutionException( "ArchiverException while creating ." + APKLIB + " file.", e );
174 }
175 catch ( IOException e )
176 {
177 throw new MojoExecutionException( "IOException while creating ." + APKLIB + " file.", e );
178 }
179
180 return apklibrary;
181 }
182
183 private void addNativeLibraries( final JarArchiver jarArchiver ) throws MojoExecutionException
184 {
185
186 try
187 {
188 if ( nativeLibrariesDirectory.exists() )
189 {
190 getLog().info( nativeLibrariesDirectory + " exists, adding libraries." );
191 addDirectory( jarArchiver, nativeLibrariesDirectory, NATIVE_LIBRARIES_FOLDER );
192 }
193 else
194 {
195 getLog().info( nativeLibrariesDirectory
196 + " does not exist, looking for libraries in target directory." );
197
198 String[] ndkArchitectures = NativeHelper.getNdkArchitectures( ndkArchitecture,
199 applicationMakefile,
200 project.getBasedir() );
201 for ( String architecture : ndkArchitectures )
202 {
203 final File ndkLibsDirectory = new File( ndkOutputDirectory, architecture );
204 addSharedLibraries( jarArchiver, ndkLibsDirectory, architecture );
205
206
207
208
209
210
211 }
212 }
213
214
215
216
217
218
219
220
221
222
223
224 }
225 catch ( ArchiverException e )
226 {
227 throw new MojoExecutionException( "IOException while creating ." + APKLIB + " file.", e );
228 }
229
230
231
232
233
234 }
235
236 protected void addJavaResources( JarArchiver jarArchiver, List<Resource> javaResources, String prefix )
237 throws IOException
238 {
239 for ( Resource javaResource : javaResources )
240 {
241 addJavaResource( jarArchiver, javaResource, prefix );
242 }
243 }
244
245
246
247
248
249
250
251
252
253 protected void addJavaResource( JarArchiver jarArchiver, Resource javaResource, String prefix )
254 throws IOException
255 {
256 if ( javaResource != null )
257 {
258 final File javaResourceDirectory = new File( javaResource.getDirectory() );
259 if ( javaResourceDirectory.exists() )
260 {
261 final String resourcePath = javaResourceDirectory.getCanonicalPath();
262 final String apkLibUnpackBasePath = getUnpackedLibsDirectory().getCanonicalPath();
263
264 if ( ! resourcePath.startsWith( apkLibUnpackBasePath ) )
265 {
266 final DefaultFileSet javaResourceFileSet = new DefaultFileSet();
267 javaResourceFileSet.setDirectory( javaResourceDirectory );
268 javaResourceFileSet.setPrefix( endWithSlash( prefix ) );
269 jarArchiver.addFileSet( javaResourceFileSet );
270 }
271 }
272 }
273 }
274
275
276
277
278
279
280
281 protected String endWithSlash( String prefix )
282 {
283 prefix = StringUtils.defaultIfEmpty( prefix, "/" );
284 if ( ! prefix.endsWith( "/" ) )
285 {
286 prefix = prefix + "/";
287 }
288 return prefix;
289 }
290
291
292
293
294
295
296
297
298 protected void addDirectory( JarArchiver jarArchiver, File directory, String prefix )
299 {
300 if ( directory != null && directory.exists() )
301 {
302 final DefaultFileSet fileSet = new DefaultFileSet();
303 fileSet.setPrefix( endWithSlash( prefix ) );
304 fileSet.setDirectory( directory );
305
306
307 fileSet.setExcludes( new String[] { "**/R.java", "**/BuildConfig.java" } );
308
309 jarArchiver.addFileSet( fileSet );
310 getLog().debug( "Added files from " + directory );
311 }
312 }
313
314
315
316
317
318
319
320
321 protected void addSharedLibraries( JarArchiver jarArchiver, File directory, String architecture )
322 {
323 getLog().debug( "Searching for shared libraries in " + directory );
324 File[] libFiles = directory.listFiles( new FilenameFilter()
325 {
326 public boolean accept( final File dir, final String name )
327 {
328 return name.startsWith( "lib" ) && name.endsWith( ".so" );
329 }
330 } );
331
332 if ( libFiles != null )
333 {
334 for ( File libFile : libFiles )
335 {
336 String dest = NATIVE_LIBRARIES_FOLDER + "/" + architecture + "/" + libFile.getName();
337 getLog().debug( "Adding " + libFile + " as " + dest );
338 jarArchiver.addFile( libFile, dest );
339 }
340 }
341 }
342
343
344
345
346
347
348 private void generateIntermediateApk() throws MojoExecutionException
349 {
350
351 CommandExecutor executor = CommandExecutor.Factory.createDefaultCommmandExecutor();
352 executor.setLogger( this.getLog() );
353 File[] overlayDirectories = getResourceOverlayDirectories();
354
355 File androidJar = getAndroidSdk().getAndroidJar();
356 File outputFile = new File( targetDirectory, finalName + ".ap_" );
357
358 List<File> dependencyArtifactResDirectoryList = new ArrayList<File>();
359 for ( Artifact libraryArtifact : getTransitiveDependencyArtifacts( APKLIB, AAR ) )
360 {
361 final File apklibResDirectory = getUnpackedLibResourceFolder( libraryArtifact );
362 if ( apklibResDirectory.exists() )
363 {
364 dependencyArtifactResDirectoryList.add( apklibResDirectory );
365 }
366 }
367
368 AaptCommandBuilder commandBuilder = AaptCommandBuilder
369 .packageResources( getLog() )
370 .forceOverwriteExistingFiles()
371 .setPathToAndroidManifest( destinationManifestFile )
372 .addResourceDirectoriesIfExists( overlayDirectories )
373 .addResourceDirectoryIfExists( resourceDirectory )
374 .addResourceDirectoriesIfExists( dependencyArtifactResDirectoryList )
375 .autoAddOverlay()
376
377 .addRawAssetsDirectoryIfExists( combinedAssets )
378 .addExistingPackageToBaseIncludeSet( androidJar )
379 .setOutputApkFile( outputFile )
380 .addConfigurations( configurations )
381 .setVerbose( aaptVerbose );
382
383 getLog().debug( getAndroidSdk().getAaptPath() + " " + commandBuilder.toString() );
384 getLog().info( "Generating apklib" );
385 try
386 {
387 executor.setCaptureStdOut( true );
388 List<String> commands = commandBuilder.build();
389 executor.executeCommand( getAndroidSdk().getAaptPath(), commands, project.getBasedir(), false );
390 }
391 catch ( ExecutionException e )
392 {
393 throw new MojoExecutionException( "", e );
394 }
395 }
396
397 }