@@ -10,8 +10,7 @@ import fs = require("fs");
10
10
import os = require( "os" ) ;
11
11
12
12
class AndroidProjectService implements IPlatformProjectService {
13
- private SUPPORTED_TARGETS = [ "android-17" , "android-18" , "android-19" , "android-21" ] ;
14
- private static METADATA_DIRNAME = "__metadata" ;
13
+ private SUPPORTED_TARGETS = [ "android-17" , "android-18" , "android-19" , "android-21" , "android-MNC" ] ;
15
14
private static RES_DIRNAME = "res" ;
16
15
private static VALUES_DIRNAME = "values" ;
17
16
private static VALUES_VERSION_DIRNAME_PREFIX = AndroidProjectService . VALUES_DIRNAME + "-v" ;
@@ -32,7 +31,7 @@ class AndroidProjectService implements IPlatformProjectService {
32
31
private _platformData : IPlatformData = null ;
33
32
public get platformData ( ) : IPlatformData {
34
33
if ( ! this . _platformData ) {
35
- var projectRoot = path . join ( this . $projectData . platformsDir , "android" ) ;
34
+ let projectRoot = path . join ( this . $projectData . platformsDir , "android" ) ;
36
35
37
36
this . _platformData = {
38
37
frameworkPackageName : "tns-android" ,
@@ -66,8 +65,8 @@ class AndroidProjectService implements IPlatformProjectService {
66
65
public createProject ( projectRoot : string , frameworkDir : string ) : IFuture < void > {
67
66
return ( ( ) => {
68
67
this . $fs . ensureDirectoryExists ( projectRoot ) . wait ( ) ;
69
- var newTarget = this . getLatestValidAndroidTarget ( frameworkDir ) . wait ( ) ;
70
- var versionNumber = _ . last ( newTarget . split ( "-" ) ) ;
68
+ let newTarget = this . getLatestValidAndroidTarget ( frameworkDir ) . wait ( ) ;
69
+ let versionNumber = _ . last ( newTarget . split ( "-" ) ) ;
71
70
if ( this . $options . symlink ) {
72
71
this . copyResValues ( projectRoot , frameworkDir , versionNumber ) . wait ( ) ;
73
72
this . copy ( projectRoot , frameworkDir , ".project AndroidManifest.xml project.properties custom_rules.xml" , "-f" ) . wait ( ) ;
@@ -85,21 +84,21 @@ class AndroidProjectService implements IPlatformProjectService {
85
84
}
86
85
87
86
// Create src folder
88
- var packageName = this . $projectData . projectId ;
89
- var packageAsPath = packageName . replace ( / \. / g, path . sep ) ;
90
- var activityDir = path . join ( projectRoot , 'src' , packageAsPath ) ;
87
+ let packageName = this . $projectData . projectId ;
88
+ let packageAsPath = packageName . replace ( / \. / g, path . sep ) ;
89
+ let activityDir = path . join ( projectRoot , 'src' , packageAsPath ) ;
91
90
this . $fs . createDirectory ( activityDir ) . wait ( ) ;
92
91
93
92
} ) . future < any > ( ) ( ) ;
94
93
}
95
94
96
95
private copyResValues ( projectRoot : string , frameworkDir : string , versionNumber : string ) : IFuture < void > {
97
96
return ( ( ) => {
98
- var resSourceDir = path . join ( frameworkDir , AndroidProjectService . RES_DIRNAME ) ;
99
- var resDestinationDir = path . join ( projectRoot , AndroidProjectService . RES_DIRNAME ) ;
97
+ let resSourceDir = path . join ( frameworkDir , AndroidProjectService . RES_DIRNAME ) ;
98
+ let resDestinationDir = path . join ( projectRoot , AndroidProjectService . RES_DIRNAME ) ;
100
99
this . $fs . createDirectory ( resDestinationDir ) . wait ( ) ;
101
- var versionDirName = AndroidProjectService . VALUES_VERSION_DIRNAME_PREFIX + versionNumber ;
102
- var directoriesToCopy = [ AndroidProjectService . VALUES_DIRNAME ] ;
100
+ let versionDirName = AndroidProjectService . VALUES_VERSION_DIRNAME_PREFIX + versionNumber ;
101
+ let directoriesToCopy = [ AndroidProjectService . VALUES_DIRNAME ] ;
103
102
if ( this . $fs . exists ( path . join ( resSourceDir , versionDirName ) ) . wait ( ) ) {
104
103
directoriesToCopy . push ( versionDirName ) ;
105
104
}
@@ -111,27 +110,35 @@ class AndroidProjectService implements IPlatformProjectService {
111
110
public interpolateData ( projectRoot : string ) : IFuture < void > {
112
111
return ( ( ) => {
113
112
// Interpolate the activity name and package
114
- var manifestPath = path . join ( projectRoot , "AndroidManifest.xml" ) ;
115
- var safeActivityName = this . $projectData . projectName . replace ( / \W / g, '' ) ;
113
+ let manifestPath = path . join ( projectRoot , "AndroidManifest.xml" ) ;
114
+ let safeActivityName = this . $projectData . projectName . replace ( / \W / g, '' ) ;
116
115
shell . sed ( '-i' , / _ _ P A C K A G E _ _ / , this . $projectData . projectId , manifestPath ) ;
117
116
shell . sed ( '-i' , / _ _ A P I L E V E L _ _ / , this . getTarget ( projectRoot ) . wait ( ) . split ( '-' ) [ 1 ] , manifestPath ) ;
118
117
119
- var stringsFilePath = path . join ( projectRoot , 'res' , 'values' , 'strings.xml' ) ;
118
+ let stringsFilePath = path . join ( projectRoot , 'res' , 'values' , 'strings.xml' ) ;
120
119
shell . sed ( '-i' , / _ _ N A M E _ _ / , this . $projectData . projectName , stringsFilePath ) ;
121
120
shell . sed ( '-i' , / _ _ T I T L E _ A C T I V I T Y _ _ / , this . $projectData . projectName , stringsFilePath ) ;
122
121
shell . sed ( '-i' , / _ _ N A M E _ _ / , this . $projectData . projectName , path . join ( projectRoot , '.project' ) ) ;
123
-
124
122
} ) . future < void > ( ) ( ) ;
125
123
}
126
124
127
125
public afterCreateProject ( projectRoot : string ) : IFuture < void > {
128
126
return ( ( ) => {
129
- var targetApi = this . getTarget ( projectRoot ) . wait ( ) ;
127
+ let targetApi = this . getTarget ( projectRoot ) . wait ( ) ;
130
128
this . $logger . trace ( "Android target: %s" , targetApi ) ;
131
129
this . runAndroidUpdate ( projectRoot , targetApi ) . wait ( ) ;
130
+ this . adjustMinSdk ( projectRoot ) ;
132
131
} ) . future < void > ( ) ( ) ;
133
132
}
134
133
134
+ private adjustMinSdk ( projectRoot : string ) : void {
135
+ let manifestPath = path . join ( projectRoot , "AndroidManifest.xml" ) ;
136
+ let apiLevel = this . getTarget ( projectRoot ) . wait ( ) . split ( '-' ) [ 1 ] ;
137
+ if ( apiLevel === "MNC" ) { // MNC SDK requires that minSdkVersion is set to "MNC"
138
+ shell . sed ( '-i' , / a n d r o i d : m i n S d k V e r s i o n = " .* ?" / , `android:minSdkVersion="${ apiLevel } "` , manifestPath ) ;
139
+ }
140
+ }
141
+
135
142
public getDebugOnDeviceSetup ( ) : Mobile . IDebugOnDeviceSetup {
136
143
return { } ;
137
144
}
@@ -145,32 +152,30 @@ class AndroidProjectService implements IPlatformProjectService {
145
152
}
146
153
147
154
public buildProject ( projectRoot : string ) : IFuture < void > {
148
- return ( ( ) => {
149
- var buildConfiguration = this . $options . release ? "release" : "debug" ;
150
- var args = this . getAntArgs ( buildConfiguration , projectRoot ) ;
151
- this . spawn ( 'ant' , args ) . wait ( ) ;
152
- } ) . future < void > ( ) ( ) ;
155
+ let buildConfiguration = this . $options . release ? "release" : "debug" ;
156
+ let args = this . getAntArgs ( buildConfiguration , projectRoot ) ;
157
+ return this . spawn ( 'ant' , args ) ;
153
158
}
154
159
155
160
public isPlatformPrepared ( projectRoot : string ) : IFuture < boolean > {
156
161
return this . $fs . exists ( path . join ( projectRoot , "assets" , constants . APP_FOLDER_NAME ) ) ;
157
162
}
158
163
159
164
private parseProjectProperties ( projDir : string , destDir : string ) : void {
160
- var projProp = path . join ( projDir , "project.properties" ) ;
165
+ let projProp = path . join ( projDir , "project.properties" ) ;
161
166
162
167
if ( ! this . $fs . exists ( projProp ) . wait ( ) ) {
163
168
this . $logger . warn ( "Warning: File %s does not exist" , projProp ) ;
164
169
return ;
165
170
}
166
171
167
- var lines = this . $fs . readText ( projProp , "utf-8" ) . wait ( ) . split ( os . EOL ) ;
172
+ let lines = this . $fs . readText ( projProp , "utf-8" ) . wait ( ) . split ( os . EOL ) ;
168
173
169
- var regEx = / a n d r o i d \. l i b r a r y \. r e f e r e n c e \. ( \d + ) = ( .* ) / ;
174
+ let regEx = / a n d r o i d \. l i b r a r y \. r e f e r e n c e \. ( \d + ) = ( .* ) / ;
170
175
lines . forEach ( elem => {
171
- var match = elem . match ( regEx ) ;
176
+ let match = elem . match ( regEx ) ;
172
177
if ( match ) {
173
- var libRef : ILibRef = { idx : parseInt ( match [ 1 ] ) , path : match [ 2 ] . trim ( ) } ;
178
+ let libRef : ILibRef = { idx : parseInt ( match [ 1 ] ) , path : match [ 2 ] . trim ( ) } ;
174
179
libRef . adjustedPath = this . $fs . isRelativePath ( libRef . path ) ? path . join ( projDir , libRef . path ) : libRef . path ;
175
180
this . parseProjectProperties ( libRef . adjustedPath , destDir ) ;
176
181
}
@@ -179,25 +184,25 @@ class AndroidProjectService implements IPlatformProjectService {
179
184
this . $logger . info ( "Copying %s" , projDir ) ;
180
185
shell . cp ( "-Rf" , projDir , destDir ) ;
181
186
182
- var targetDir = path . join ( destDir , path . basename ( projDir ) ) ;
187
+ let targetDir = path . join ( destDir , path . basename ( projDir ) ) ;
183
188
// TODO: parametrize targetSdk
184
- var targetSdk = "android-17" ;
189
+ let targetSdk = "android-17" ;
185
190
this . $logger . info ( "Generate build.xml for %s" , targetDir ) ;
186
191
this . runAndroidUpdate ( targetDir , targetSdk ) . wait ( ) ;
187
192
}
188
193
189
194
private getProjectReferences ( projDir : string ) : ILibRef [ ] {
190
- var projProp = path . join ( projDir , "project.properties" ) ;
195
+ let projProp = path . join ( projDir , "project.properties" ) ;
191
196
192
- var lines = this . $fs . readText ( projProp , "utf-8" ) . wait ( ) . split ( os . EOL ) ;
197
+ let lines = this . $fs . readText ( projProp , "utf-8" ) . wait ( ) . split ( os . EOL ) ;
193
198
194
- var refs : ILibRef [ ] = [ ] ;
199
+ let refs : ILibRef [ ] = [ ] ;
195
200
196
- var regEx = / a n d r o i d \. l i b r a r y \. r e f e r e n c e \. ( \d + ) = ( .* ) / ;
201
+ let regEx = / a n d r o i d \. l i b r a r y \. r e f e r e n c e \. ( \d + ) = ( .* ) / ;
197
202
lines . forEach ( elem => {
198
- var match = elem . match ( regEx ) ;
203
+ let match = elem . match ( regEx ) ;
199
204
if ( match ) {
200
- var libRef : ILibRef = { idx : parseInt ( match [ 1 ] ) , path : match [ 2 ] } ;
205
+ let libRef : ILibRef = { idx : parseInt ( match [ 1 ] ) , path : match [ 2 ] } ;
201
206
libRef . adjustedPath = path . join ( projDir , libRef . path ) ;
202
207
refs . push ( libRef ) ;
203
208
}
@@ -207,37 +212,37 @@ class AndroidProjectService implements IPlatformProjectService {
207
212
}
208
213
209
214
private updateProjectReferences ( projDir : string , libraryPath : string ) : void {
210
- var refs = this . getProjectReferences ( projDir ) ;
211
- var maxIdx = refs . length > 0 ? _ . max ( refs , r => r . idx ) . idx : 0 ;
215
+ let refs = this . getProjectReferences ( projDir ) ;
216
+ let maxIdx = refs . length > 0 ? _ . max ( refs , r => r . idx ) . idx : 0 ;
212
217
213
- var relLibDir = path . relative ( projDir , libraryPath ) . split ( "\\" ) . join ( "/" ) ;
218
+ let relLibDir = path . relative ( projDir , libraryPath ) . split ( "\\" ) . join ( "/" ) ;
214
219
215
- var libRefExists = _ . any ( refs , r => path . normalize ( r . path ) === path . normalize ( relLibDir ) ) ;
220
+ let libRefExists = _ . any ( refs , r => path . normalize ( r . path ) === path . normalize ( relLibDir ) ) ;
216
221
217
222
if ( ! libRefExists ) {
218
- var projRef = util . format ( "%sandroid.library.reference.%d=%s" , os . EOL , maxIdx + 1 , relLibDir ) ;
219
- var projProp = path . join ( projDir , "project.properties" ) ;
223
+ let projRef = util . format ( "%sandroid.library.reference.%d=%s" , os . EOL , maxIdx + 1 , relLibDir ) ;
224
+ let projProp = path . join ( projDir , "project.properties" ) ;
220
225
fs . appendFileSync ( projProp , projRef , { encoding : "utf-8" } ) ;
221
226
}
222
227
}
223
228
224
229
public addLibrary ( platformData : IPlatformData , libraryPath : string ) : IFuture < void > {
225
230
return ( ( ) => {
226
- var name = path . basename ( libraryPath ) ;
227
- var projDir = this . $projectData . projectDir ;
228
- var targetPath = path . join ( projDir , "lib" , platformData . normalizedPlatformName ) ;
231
+ let name = path . basename ( libraryPath ) ;
232
+ let projDir = this . $projectData . projectDir ;
233
+ let targetPath = path . join ( projDir , "lib" , platformData . normalizedPlatformName ) ;
229
234
this . $fs . ensureDirectoryExists ( targetPath ) . wait ( ) ;
230
235
231
236
this . parseProjectProperties ( libraryPath , targetPath ) ;
232
237
233
238
shell . cp ( "-f" , path . join ( libraryPath , "*.jar" ) , targetPath ) ;
234
- var projectLibsDir = path . join ( platformData . projectRoot , "libs" ) ;
239
+ let projectLibsDir = path . join ( platformData . projectRoot , "libs" ) ;
235
240
this . $fs . ensureDirectoryExists ( projectLibsDir ) . wait ( ) ;
236
241
shell . cp ( "-f" , path . join ( libraryPath , "*.jar" ) , projectLibsDir ) ;
237
242
238
- var targetLibPath = path . join ( targetPath , path . basename ( libraryPath ) ) ;
243
+ let targetLibPath = path . join ( targetPath , path . basename ( libraryPath ) ) ;
239
244
240
- var libProjProp = path . join ( libraryPath , "project.properties" ) ;
245
+ let libProjProp = path . join ( libraryPath , "project.properties" ) ;
241
246
if ( this . $fs . exists ( libProjProp ) . wait ( ) ) {
242
247
this . updateProjectReferences ( platformData . projectRoot , targetLibPath ) ;
243
248
}
@@ -250,7 +255,7 @@ class AndroidProjectService implements IPlatformProjectService {
250
255
251
256
private copy ( projectRoot : string , frameworkDir : string , files : string , cpArg : string ) : IFuture < void > {
252
257
return ( ( ) => {
253
- var paths = files . split ( ' ' ) . map ( p => path . join ( frameworkDir , p ) ) ;
258
+ let paths = files . split ( ' ' ) . map ( p => path . join ( frameworkDir , p ) ) ;
254
259
shell . cp ( cpArg , paths , projectRoot ) ;
255
260
} ) . future < void > ( ) ( ) ;
256
261
}
@@ -265,7 +270,7 @@ class AndroidProjectService implements IPlatformProjectService {
265
270
}
266
271
267
272
private getAntArgs ( configuration : string , projectRoot : string ) : string [ ] {
268
- var args = [ configuration , "-f" , path . join ( projectRoot , "build.xml" ) ] ;
273
+ let args = [ configuration , "-f" , path . join ( projectRoot , "build.xml" ) ] ;
269
274
if ( configuration === "release" ) {
270
275
if ( this . $options . keyStorePath ) {
271
276
args = args . concat ( [ "-Dkey.store" , this . $options . keyStorePath ] ) ;
@@ -291,15 +296,13 @@ class AndroidProjectService implements IPlatformProjectService {
291
296
}
292
297
293
298
private runAndroidUpdate ( projectPath : string , targetApi : string ) : IFuture < void > {
294
- return ( ( ) => {
295
- var args = [
296
- "--path" , projectPath ,
297
- "--target" , targetApi ,
298
- "--name" , this . $projectData . projectName
299
- ] ;
299
+ let args = [
300
+ "--path" , projectPath ,
301
+ "--target" , targetApi ,
302
+ "--name" , this . $projectData . projectName
303
+ ] ;
300
304
301
- this . spawn ( "android" , [ 'update' , 'project' ] . concat ( args ) ) . wait ( ) ;
302
- } ) . future < void > ( ) ( ) ;
305
+ return this . spawn ( "android" , [ 'update' , 'project' ] . concat ( args ) ) ;
303
306
}
304
307
305
308
private validatePackageName ( packageName : string ) : void {
@@ -328,8 +331,8 @@ class AndroidProjectService implements IPlatformProjectService {
328
331
329
332
private getLatestValidAndroidTarget ( frameworkDir : string ) : IFuture < string > {
330
333
return ( ( ) => {
331
- var validTarget = this . getTarget ( frameworkDir ) . wait ( ) ;
332
- var installedTargets = this . getInstalledTargets ( ) . wait ( ) ;
334
+ let validTarget = this . getTarget ( frameworkDir ) . wait ( ) ;
335
+ let installedTargets = this . getInstalledTargets ( ) . wait ( ) ;
333
336
334
337
// adjust to the latest available version
335
338
var newTarget = _ ( this . SUPPORTED_TARGETS ) . sort ( ) . findLast ( supportedTarget => _ . contains ( installedTargets , supportedTarget ) ) ;
@@ -345,10 +348,10 @@ class AndroidProjectService implements IPlatformProjectService {
345
348
346
349
private updateTarget ( projectRoot : string , newTarget : string ) : IFuture < void > {
347
350
return ( ( ) => {
348
- var file = path . join ( projectRoot , "project.properties" ) ;
349
- var editor = this . $propertiesParser . createEditor ( file ) . wait ( ) ;
351
+ let file = path . join ( projectRoot , "project.properties" ) ;
352
+ let editor = this . $propertiesParser . createEditor ( file ) . wait ( ) ;
350
353
editor . set ( "target" , newTarget ) ;
351
- var future = new Future < void > ( ) ;
354
+ let future = new Future < void > ( ) ;
352
355
editor . save ( ( err :any ) => {
353
356
if ( err ) {
354
357
future . throw ( err ) ;
@@ -366,7 +369,7 @@ class AndroidProjectService implements IPlatformProjectService {
366
369
return ( ( ) => {
367
370
if ( ! this . installedTargetsCache ) {
368
371
this . installedTargetsCache = [ ] ;
369
- var output = this . $childProcess . exec ( 'android list targets' ) . wait ( ) ;
372
+ let output = this . $childProcess . exec ( 'android list targets' ) . wait ( ) ;
370
373
output . replace ( / i d : \d + o r " ( .+ ) " / g, ( m :string , p1 :string ) => ( this . installedTargetsCache . push ( p1 ) , m ) ) ;
371
374
}
372
375
return this . installedTargetsCache ;
@@ -376,10 +379,10 @@ class AndroidProjectService implements IPlatformProjectService {
376
379
private getTarget ( projectRoot : string ) : IFuture < string > {
377
380
return ( ( ) => {
378
381
if ( ! this . targetApi ) {
379
- var projectPropertiesFilePath = path . join ( projectRoot , "project.properties" ) ;
382
+ let projectPropertiesFilePath = path . join ( projectRoot , "project.properties" ) ;
380
383
381
384
if ( this . $fs . exists ( projectPropertiesFilePath ) . wait ( ) ) {
382
- var properties = this . $propertiesParser . createEditor ( projectPropertiesFilePath ) . wait ( ) ;
385
+ let properties = this . $propertiesParser . createEditor ( projectPropertiesFilePath ) . wait ( ) ;
383
386
this . targetApi = properties . get ( "target" ) ;
384
387
}
385
388
}
@@ -393,7 +396,7 @@ class AndroidProjectService implements IPlatformProjectService {
393
396
try {
394
397
this . $childProcess . exec ( "ant -version" ) . wait ( ) ;
395
398
} catch ( error ) {
396
- this . $errors . fail ( "Error executing commands 'ant', make sure you have ant installed and added to your PATH." )
399
+ this . $errors . fail ( "Error executing commands 'ant', make sure you have ant installed and added to your PATH." ) ;
397
400
}
398
401
} ) . future < void > ( ) ( ) ;
399
402
}
@@ -415,11 +418,11 @@ class AndroidProjectService implements IPlatformProjectService {
415
418
private symlinkDirectory ( directoryName : string , projectRoot : string , frameworkDir : string ) : IFuture < void > {
416
419
return ( ( ) => {
417
420
this . $fs . createDirectory ( path . join ( projectRoot , directoryName ) ) . wait ( ) ;
418
- var directoryContent = this . $fs . readDirectory ( path . join ( frameworkDir , directoryName ) ) . wait ( ) ;
421
+ let directoryContent = this . $fs . readDirectory ( path . join ( frameworkDir , directoryName ) ) . wait ( ) ;
419
422
420
423
_ . each ( directoryContent , ( file : string ) => {
421
- var sourceFilePath = path . join ( frameworkDir , directoryName , file ) ;
422
- var destinationFilePath = path . join ( projectRoot , directoryName , file ) ;
424
+ let sourceFilePath = path . join ( frameworkDir , directoryName , file ) ;
425
+ let destinationFilePath = path . join ( projectRoot , directoryName , file ) ;
423
426
if ( this . $fs . getFsStats ( sourceFilePath ) . wait ( ) . isFile ( ) ) {
424
427
this . $fs . symlink ( sourceFilePath , destinationFilePath ) . wait ( ) ;
425
428
} else {
0 commit comments