Skip to content

Commit 86e051e

Browse files
committed
Merge pull request #513 from NativeScript/totev/mnc
Support for android MNC
2 parents 44d70bb + 17b3acb commit 86e051e

File tree

2 files changed

+73
-70
lines changed

2 files changed

+73
-70
lines changed

lib/services/android-project-service.ts

Lines changed: 72 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import fs = require("fs");
1010
import os = require("os");
1111

1212
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"];
1514
private static RES_DIRNAME = "res";
1615
private static VALUES_DIRNAME = "values";
1716
private static VALUES_VERSION_DIRNAME_PREFIX = AndroidProjectService.VALUES_DIRNAME + "-v";
@@ -32,7 +31,7 @@ class AndroidProjectService implements IPlatformProjectService {
3231
private _platformData: IPlatformData = null;
3332
public get platformData(): IPlatformData {
3433
if (!this._platformData) {
35-
var projectRoot = path.join(this.$projectData.platformsDir, "android");
34+
let projectRoot = path.join(this.$projectData.platformsDir, "android");
3635

3736
this._platformData = {
3837
frameworkPackageName: "tns-android",
@@ -66,8 +65,8 @@ class AndroidProjectService implements IPlatformProjectService {
6665
public createProject(projectRoot: string, frameworkDir: string): IFuture<void> {
6766
return (() => {
6867
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("-"));
7170
if(this.$options.symlink) {
7271
this.copyResValues(projectRoot, frameworkDir, versionNumber).wait();
7372
this.copy(projectRoot, frameworkDir, ".project AndroidManifest.xml project.properties custom_rules.xml", "-f").wait();
@@ -85,21 +84,21 @@ class AndroidProjectService implements IPlatformProjectService {
8584
}
8685

8786
// 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);
9190
this.$fs.createDirectory(activityDir).wait();
9291

9392
}).future<any>()();
9493
}
9594

9695
private copyResValues(projectRoot: string, frameworkDir: string, versionNumber: string): IFuture<void> {
9796
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);
10099
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];
103102
if(this.$fs.exists(path.join(resSourceDir, versionDirName)).wait()) {
104103
directoriesToCopy.push(versionDirName);
105104
}
@@ -111,27 +110,35 @@ class AndroidProjectService implements IPlatformProjectService {
111110
public interpolateData(projectRoot: string): IFuture<void> {
112111
return (() => {
113112
// 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, '');
116115
shell.sed('-i', /__PACKAGE__/, this.$projectData.projectId, manifestPath);
117116
shell.sed('-i', /__APILEVEL__/, this.getTarget(projectRoot).wait().split('-')[1], manifestPath);
118117

119-
var stringsFilePath = path.join(projectRoot, 'res', 'values', 'strings.xml');
118+
let stringsFilePath = path.join(projectRoot, 'res', 'values', 'strings.xml');
120119
shell.sed('-i', /__NAME__/, this.$projectData.projectName, stringsFilePath);
121120
shell.sed('-i', /__TITLE_ACTIVITY__/, this.$projectData.projectName, stringsFilePath);
122121
shell.sed('-i', /__NAME__/, this.$projectData.projectName, path.join(projectRoot, '.project'));
123-
124122
}).future<void>()();
125123
}
126124

127125
public afterCreateProject(projectRoot: string): IFuture<void> {
128126
return (() => {
129-
var targetApi = this.getTarget(projectRoot).wait();
127+
let targetApi = this.getTarget(projectRoot).wait();
130128
this.$logger.trace("Android target: %s", targetApi);
131129
this.runAndroidUpdate(projectRoot, targetApi).wait();
130+
this.adjustMinSdk(projectRoot);
132131
}).future<void>()();
133132
}
134133

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', /android:minSdkVersion=".*?"/, `android:minSdkVersion="${apiLevel}"`, manifestPath);
139+
}
140+
}
141+
135142
public getDebugOnDeviceSetup(): Mobile.IDebugOnDeviceSetup {
136143
return { };
137144
}
@@ -145,32 +152,30 @@ class AndroidProjectService implements IPlatformProjectService {
145152
}
146153

147154
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);
153158
}
154159

155160
public isPlatformPrepared(projectRoot: string): IFuture<boolean> {
156161
return this.$fs.exists(path.join(projectRoot, "assets", constants.APP_FOLDER_NAME));
157162
}
158163

159164
private parseProjectProperties(projDir: string, destDir: string): void {
160-
var projProp = path.join(projDir, "project.properties");
165+
let projProp = path.join(projDir, "project.properties");
161166

162167
if (!this.$fs.exists(projProp).wait()) {
163168
this.$logger.warn("Warning: File %s does not exist", projProp);
164169
return;
165170
}
166171

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);
168173

169-
var regEx = /android\.library\.reference\.(\d+)=(.*)/;
174+
let regEx = /android\.library\.reference\.(\d+)=(.*)/;
170175
lines.forEach(elem => {
171-
var match = elem.match(regEx);
176+
let match = elem.match(regEx);
172177
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() };
174179
libRef.adjustedPath = this.$fs.isRelativePath(libRef.path) ? path.join(projDir, libRef.path) : libRef.path;
175180
this.parseProjectProperties(libRef.adjustedPath, destDir);
176181
}
@@ -179,25 +184,25 @@ class AndroidProjectService implements IPlatformProjectService {
179184
this.$logger.info("Copying %s", projDir);
180185
shell.cp("-Rf", projDir, destDir);
181186

182-
var targetDir = path.join(destDir, path.basename(projDir));
187+
let targetDir = path.join(destDir, path.basename(projDir));
183188
// TODO: parametrize targetSdk
184-
var targetSdk = "android-17";
189+
let targetSdk = "android-17";
185190
this.$logger.info("Generate build.xml for %s", targetDir);
186191
this.runAndroidUpdate(targetDir, targetSdk).wait();
187192
}
188193

189194
private getProjectReferences(projDir: string): ILibRef[]{
190-
var projProp = path.join(projDir, "project.properties");
195+
let projProp = path.join(projDir, "project.properties");
191196

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);
193198

194-
var refs: ILibRef[] = [];
199+
let refs: ILibRef[] = [];
195200

196-
var regEx = /android\.library\.reference\.(\d+)=(.*)/;
201+
let regEx = /android\.library\.reference\.(\d+)=(.*)/;
197202
lines.forEach(elem => {
198-
var match = elem.match(regEx);
203+
let match = elem.match(regEx);
199204
if (match) {
200-
var libRef: ILibRef = { idx: parseInt(match[1]), path: match[2] };
205+
let libRef: ILibRef = { idx: parseInt(match[1]), path: match[2] };
201206
libRef.adjustedPath = path.join(projDir, libRef.path);
202207
refs.push(libRef);
203208
}
@@ -207,37 +212,37 @@ class AndroidProjectService implements IPlatformProjectService {
207212
}
208213

209214
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;
212217

213-
var relLibDir = path.relative(projDir, libraryPath).split("\\").join("/");
218+
let relLibDir = path.relative(projDir, libraryPath).split("\\").join("/");
214219

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));
216221

217222
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");
220225
fs.appendFileSync(projProp, projRef, { encoding: "utf-8" });
221226
}
222227
}
223228

224229
public addLibrary(platformData: IPlatformData, libraryPath: string): IFuture<void> {
225230
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);
229234
this.$fs.ensureDirectoryExists(targetPath).wait();
230235

231236
this.parseProjectProperties(libraryPath, targetPath);
232237

233238
shell.cp("-f", path.join(libraryPath, "*.jar"), targetPath);
234-
var projectLibsDir = path.join(platformData.projectRoot, "libs");
239+
let projectLibsDir = path.join(platformData.projectRoot, "libs");
235240
this.$fs.ensureDirectoryExists(projectLibsDir).wait();
236241
shell.cp("-f", path.join(libraryPath, "*.jar"), projectLibsDir);
237242

238-
var targetLibPath = path.join(targetPath, path.basename(libraryPath));
243+
let targetLibPath = path.join(targetPath, path.basename(libraryPath));
239244

240-
var libProjProp = path.join(libraryPath, "project.properties");
245+
let libProjProp = path.join(libraryPath, "project.properties");
241246
if (this.$fs.exists(libProjProp).wait()) {
242247
this.updateProjectReferences(platformData.projectRoot, targetLibPath);
243248
}
@@ -250,7 +255,7 @@ class AndroidProjectService implements IPlatformProjectService {
250255

251256
private copy(projectRoot: string, frameworkDir: string, files: string, cpArg: string): IFuture<void> {
252257
return (() => {
253-
var paths = files.split(' ').map(p => path.join(frameworkDir, p));
258+
let paths = files.split(' ').map(p => path.join(frameworkDir, p));
254259
shell.cp(cpArg, paths, projectRoot);
255260
}).future<void>()();
256261
}
@@ -265,7 +270,7 @@ class AndroidProjectService implements IPlatformProjectService {
265270
}
266271

267272
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")];
269274
if(configuration === "release") {
270275
if(this.$options.keyStorePath) {
271276
args = args.concat(["-Dkey.store", this.$options.keyStorePath]);
@@ -291,15 +296,13 @@ class AndroidProjectService implements IPlatformProjectService {
291296
}
292297

293298
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+
];
300304

301-
this.spawn("android", ['update', 'project'].concat(args)).wait();
302-
}).future<void>()();
305+
return this.spawn("android", ['update', 'project'].concat(args));
303306
}
304307

305308
private validatePackageName(packageName: string): void {
@@ -328,8 +331,8 @@ class AndroidProjectService implements IPlatformProjectService {
328331

329332
private getLatestValidAndroidTarget(frameworkDir: string): IFuture<string> {
330333
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();
333336

334337
// adjust to the latest available version
335338
var newTarget = _(this.SUPPORTED_TARGETS).sort().findLast(supportedTarget => _.contains(installedTargets, supportedTarget));
@@ -345,10 +348,10 @@ class AndroidProjectService implements IPlatformProjectService {
345348

346349
private updateTarget(projectRoot: string, newTarget: string): IFuture<void> {
347350
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();
350353
editor.set("target", newTarget);
351-
var future = new Future<void>();
354+
let future = new Future<void>();
352355
editor.save((err:any) => {
353356
if (err) {
354357
future.throw(err);
@@ -366,7 +369,7 @@ class AndroidProjectService implements IPlatformProjectService {
366369
return (() => {
367370
if (!this.installedTargetsCache) {
368371
this.installedTargetsCache = [];
369-
var output = this.$childProcess.exec('android list targets').wait();
372+
let output = this.$childProcess.exec('android list targets').wait();
370373
output.replace(/id: \d+ or "(.+)"/g, (m:string, p1:string) => (this.installedTargetsCache.push(p1), m));
371374
}
372375
return this.installedTargetsCache;
@@ -376,10 +379,10 @@ class AndroidProjectService implements IPlatformProjectService {
376379
private getTarget(projectRoot: string): IFuture<string> {
377380
return (() => {
378381
if(!this.targetApi) {
379-
var projectPropertiesFilePath = path.join(projectRoot, "project.properties");
382+
let projectPropertiesFilePath = path.join(projectRoot, "project.properties");
380383

381384
if (this.$fs.exists(projectPropertiesFilePath).wait()) {
382-
var properties = this.$propertiesParser.createEditor(projectPropertiesFilePath).wait();
385+
let properties = this.$propertiesParser.createEditor(projectPropertiesFilePath).wait();
383386
this.targetApi = properties.get("target");
384387
}
385388
}
@@ -393,7 +396,7 @@ class AndroidProjectService implements IPlatformProjectService {
393396
try {
394397
this.$childProcess.exec("ant -version").wait();
395398
} 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.");
397400
}
398401
}).future<void>()();
399402
}
@@ -415,11 +418,11 @@ class AndroidProjectService implements IPlatformProjectService {
415418
private symlinkDirectory(directoryName: string, projectRoot: string, frameworkDir: string): IFuture<void> {
416419
return (() => {
417420
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();
419422

420423
_.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);
423426
if(this.$fs.getFsStats(sourceFilePath).wait().isFile()) {
424427
this.$fs.symlink(sourceFilePath, destinationFilePath).wait();
425428
} else {

0 commit comments

Comments
 (0)