Skip to content

Commit 9f0ccee

Browse files
committed
Added build for Android Play store bundle.
1 parent f0bc821 commit 9f0ccee

File tree

11 files changed

+1229
-308
lines changed

11 files changed

+1229
-308
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ debug/
1414
release/
1515
testresults/
1616
.eslintcache
17+
cordova/bundle.keystore
1718

1819
# OSX
1920
.DS_store

azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ stages:
8686
displayName: 'Install Node.js 10.16.3'
8787
- script: yarn install
8888
displayName: 'Run yarn install'
89-
- script: yarn gulp release --android
89+
- script: yarn gulp debug-release --android
9090
displayName: 'Run yarn release for android'
9191
- task: PublishPipelineArtifact@1
9292
displayName: 'Publish Android release'

cordova/build.json

Lines changed: 0 additions & 10 deletions
This file was deleted.

cordova/build_template.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"android": {
3+
"debug": {
4+
"keystore": "debug.keystore",
5+
"storePassword": "betaflight_debug",
6+
"alias": "betaflight_debug",
7+
"password": "password",
8+
"packageType": "apk"
9+
},
10+
"release": {
11+
"keystore": "bundle.keystore",
12+
"storePassword": "[INJECTED_BY_GULPFILE]",
13+
"alias": "betaflight",
14+
"password": "password",
15+
"packageType": "bundle"
16+
}
17+
}
18+
}

cordova/config_template.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<preference name="SplashMaintainAspectRatio" value="true"/>
3838
<preference name="SplashShowOnlyFirstTime" value="true"/>
3939
<preference name="android-minSdkVersion" value="19"/>
40+
<preference name="android-targetSdkVersion" value="30" />
4041
<config-file parent="/manifest/application/activity" target="AndroidManifest.xml">
4142
<intent-filter>
4243
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>

cordova/debug.keystore

2.4 KB
Binary file not shown.

cordova/release.keystore

-2.19 KB
Binary file not shown.

gulpfile.js

Lines changed: 138 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ const os = require('os');
2727
const git = require('simple-git')();
2828
const source = require('vinyl-source-stream');
2929
const stream = require('stream');
30+
const prompt = require('gulp-prompt');
3031

3132
const cordova = require("cordova-lib").cordova;
33+
3234
const browserify = require('browserify');
3335
const glob = require('glob');
3436

@@ -45,7 +47,6 @@ const NODE_ENV = process.env.NODE_ENV || 'production';
4547

4648
const NAME_REGEX = /-/g;
4749

48-
4950
const nwBuilderOptions = {
5051
version: '0.54.1',
5152
files: `${DIST_DIR}**/*`,
@@ -110,18 +111,18 @@ const debugDistBuild = gulp.series(process_package_debug, dist_src, dist_changel
110111
const distRebuild = gulp.series(clean_dist, distBuild);
111112
gulp.task('dist', distRebuild);
112113

113-
const appsBuild = gulp.series(gulp.parallel(clean_apps, distRebuild), apps, gulp.series(cordova_apps()), gulp.parallel(listPostBuildTasks(APPS_DIR)));
114+
const appsBuild = gulp.series(gulp.parallel(clean_apps, distRebuild), apps, gulp.series(cordova_apps(true)), gulp.parallel(listPostBuildTasks(APPS_DIR)));
114115
gulp.task('apps', appsBuild);
115116

116-
const debugAppsBuild = gulp.series(gulp.parallel(clean_debug, gulp.series(clean_dist, debugDistBuild)), debug, gulp.series(cordova_apps()), gulp.parallel(listPostBuildTasks(DEBUG_DIR)));
117+
const debugAppsBuild = gulp.series(gulp.parallel(clean_debug, gulp.series(clean_dist, debugDistBuild)), debug, gulp.series(cordova_apps(false)), gulp.parallel(listPostBuildTasks(DEBUG_DIR)));
117118

118119
const debugBuild = gulp.series(debugDistBuild, debug, gulp.parallel(listPostBuildTasks(DEBUG_DIR)), start_debug);
119120
gulp.task('debug', debugBuild);
120121

121-
const releaseBuild = gulp.series(gulp.parallel(clean_release, appsBuild), gulp.parallel(listReleaseTasks(APPS_DIR)));
122+
const releaseBuild = gulp.series(gulp.parallel(clean_release, appsBuild), gulp.parallel(listReleaseTasks(true, APPS_DIR)));
122123
gulp.task('release', releaseBuild);
123124

124-
const debugReleaseBuild = gulp.series(gulp.parallel(clean_release, debugAppsBuild), gulp.parallel(listReleaseTasks(DEBUG_DIR)));
125+
const debugReleaseBuild = gulp.series(gulp.parallel(clean_release, debugAppsBuild), gulp.parallel(listReleaseTasks(false, DEBUG_DIR)));
125126
gulp.task('debug-release', debugReleaseBuild);
126127

127128
gulp.task('default', debugBuild);
@@ -292,21 +293,48 @@ function processPackage(done, gitRevision, isReleaseBuild) {
292293
metadata.packageId = pkg.name;
293294
}
294295

295-
const packageJson = new stream.Readable;
296-
packageJson.push(JSON.stringify(pkg, undefined, 2));
297-
packageJson.push(null);
296+
function version_prompt() {
297+
return gulp.src('.')
298+
.pipe(prompt.prompt([{
299+
type: 'input',
300+
name: 'version',
301+
message: `Package version (default: ${pkg.version}):`,
302+
}, {
303+
type: 'input',
304+
name: 'storeVersion',
305+
message: 'Google Play store version (<x.y.z>, default: package version):',
306+
}], function(res) {
307+
if (res.version) {
308+
pkg.version = res.version;
309+
}
310+
if (res.storeVersion) {
311+
metadata.storeVersion = res.storeVersion;
312+
}
313+
}));
314+
}
298315

299-
Object.keys(pkg)
300-
.filter(key => metadataKeys.includes(key))
301-
.forEach((key) => {
302-
metadata[key] = pkg[key];
303-
});
316+
function write_package_file() {
317+
Object.keys(pkg)
318+
.filter(key => metadataKeys.includes(key))
319+
.forEach((key) => {
320+
metadata[key] = pkg[key];
321+
});
304322

305-
packageJson
306-
.pipe(source('package.json'))
307-
.pipe(gulp.dest(DIST_DIR));
323+
const packageJson = new stream.Readable;
324+
packageJson.push(JSON.stringify(pkg, undefined, 2));
325+
packageJson.push(null);
308326

309-
done();
327+
return packageJson
328+
.pipe(source('package.json'))
329+
.pipe(gulp.dest(DIST_DIR));
330+
}
331+
332+
const platforms = getPlatforms();
333+
if (platforms.indexOf('android') !== -1 && isReleaseBuild) {
334+
gulp.series(version_prompt, write_package_file)(done);
335+
} else {
336+
gulp.series(write_package_file)(done);
337+
}
310338
}
311339

312340
function dist_src() {
@@ -465,7 +493,7 @@ function debug(done) {
465493
buildNWAppsWrapper(platforms, 'sdk', DEBUG_DIR, done);
466494
}
467495

468-
function injectARMCache(flavor, callback) {
496+
function injectARMCache(flavor, done) {
469497
const flavorPostfix = `-${flavor}`;
470498
const flavorDownloadPostfix = flavor !== 'normal' ? `-${flavor}` : '';
471499
clean_cache().then(function() {
@@ -528,7 +556,7 @@ function injectARMCache(flavor, callback) {
528556
clean_debug();
529557
process.exit(1);
530558
}
531-
callback();
559+
done();
532560
}
533561
);
534562
}
@@ -592,10 +620,10 @@ function buildNWApps(platforms, flavor, dir, done) {
592620

593621
function getGitRevision(done, callback, isReleaseBuild) {
594622
let gitRevision = 'norevision';
595-
git.diff([ '--shortstat' ], function (err, diff) {
596-
if (!err && !diff) {
597-
git.log([ '-1', '--pretty=format:%h' ], function (err, rev) {
598-
if (!err) {
623+
git.diff([ '--shortstat' ], function (err1, diff) {
624+
if (!err1 && !diff) {
625+
git.log([ '-1', '--pretty=format:%h' ], function (err2, rev) {
626+
if (!err2) {
599627
gitRevision = rev.latest.hash;
600628
}
601629

@@ -608,7 +636,6 @@ function getGitRevision(done, callback, isReleaseBuild) {
608636
}
609637

610638
function start_debug(done) {
611-
612639
const platforms = getPlatforms();
613640

614641
if (platforms.length === 1) {
@@ -813,7 +840,7 @@ function createDirIfNotExists(dir) {
813840
}
814841

815842
// Create a list of the gulp tasks to execute for release
816-
function listReleaseTasks(appDirectory) {
843+
function listReleaseTasks(isReleaseBuild, appDirectory) {
817844

818845
const platforms = getPlatforms();
819846

@@ -869,7 +896,11 @@ function listReleaseTasks(appDirectory) {
869896

870897
if (platforms.indexOf('android') !== -1) {
871898
releaseTasks.push(function release_android() {
872-
return cordova_release();
899+
if (isReleaseBuild) {
900+
return cordova_release();
901+
} else {
902+
return cordova_debug_release();
903+
}
873904
});
874905
}
875906

@@ -891,6 +922,7 @@ function cordova_dist() {
891922
distTasks.push(cordova_packagejson);
892923
distTasks.push(cordova_manifestjson);
893924
distTasks.push(cordova_configxml);
925+
distTasks.push(cordova_rename_build_json);
894926
distTasks.push(cordova_browserify);
895927
distTasks.push(cordova_depedencies);
896928
if (cordovaDependencies) {
@@ -903,11 +935,16 @@ function cordova_dist() {
903935
}
904936
return distTasks;
905937
}
906-
function cordova_apps() {
938+
939+
function cordova_apps(isReleaseBuild) {
907940
const appsTasks = [];
908941
const platforms = getPlatforms();
909942
if (platforms.indexOf('android') !== -1) {
910-
appsTasks.push(cordova_build);
943+
if (isReleaseBuild) {
944+
appsTasks.push(cordova_build);
945+
} else {
946+
appsTasks.push(cordova_debug_build);
947+
}
911948
} else {
912949
appsTasks.push(function cordova_dist_none(done) {
913950
done();
@@ -933,7 +970,6 @@ function cordova_copy_www() {
933970
}
934971

935972
function cordova_resources() {
936-
937973
return gulp.src('assets/android/**')
938974
.pipe(gulp.dest(`${CORDOVA_DIST_DIR}resources/android/`));
939975
}
@@ -947,7 +983,7 @@ function cordova_include_www() {
947983
}
948984

949985
function cordova_copy_src() {
950-
return gulp.src([`${CORDOVA_DIR}**`, `!${CORDOVA_DIR}config_template.xml`, `!${CORDOVA_DIR}package_template.json`])
986+
return gulp.src([`${CORDOVA_DIR}**`, `!${CORDOVA_DIR}config_template.xml`, `!${CORDOVA_DIR}package_template.json`, `!${CORDOVA_DIR}build_template.json`])
951987
.pipe(gulp.dest(`${CORDOVA_DIST_DIR}`));
952988
}
953989

@@ -972,6 +1008,8 @@ function cordova_packagejson() {
9721008
'author': metadata.author,
9731009
'license': metadata.license,
9741010
}))
1011+
.pipe(gulp.dest(CORDOVA_DIST_DIR))
1012+
.pipe(rename('manifest.json'))
9751013
.pipe(gulp.dest(CORDOVA_DIST_DIR));
9761014
}
9771015

@@ -984,7 +1022,7 @@ function cordova_manifestjson() {
9841022
}
9851023

9861024
function cordova_configxml() {
987-
let androidName = metadata.packageId.replace(NAME_REGEX, '_');
1025+
const androidName = metadata.packageId.replace(NAME_REGEX, '_');
9881026

9891027
return gulp.src([`${CORDOVA_DIST_DIR}config.xml`])
9901028
.pipe(xmlTransformer([
@@ -994,12 +1032,18 @@ function cordova_configxml() {
9941032
], 'http://www.w3.org/ns/widgets'))
9951033
.pipe(xmlTransformer([
9961034
{ path: '.', attr: { 'id': `com.betaflight.${androidName}` } },
997-
{ path: '.', attr: { 'version': metadata.version } },
1035+
{ path: '.', attr: { 'version': metadata.storeVersion ? metadata.storeVersion : metadata.version } },
9981036
]))
9991037
.pipe(gulp.dest(CORDOVA_DIST_DIR));
10001038
}
10011039

1002-
function cordova_browserify(callback) {
1040+
function cordova_rename_build_json() {
1041+
return gulp.src(`${CORDOVA_DIR}build_template.json`)
1042+
.pipe(rename('build.json'))
1043+
.pipe(gulp.dest(CORDOVA_DIST_DIR));
1044+
}
1045+
1046+
function cordova_browserify(done) {
10031047
const readFile = function(file) {
10041048
return new Promise(function(resolve) {
10051049
if (!file.includes("node_modules")) {
@@ -1017,7 +1061,7 @@ function cordova_browserify(callback) {
10171061
glob(`${CORDOVA_DIST_DIR}www/**/*.js`, {}, function (err, files) {
10181062
const readLoop = function() {
10191063
if (files.length === 0) {
1020-
callback();
1064+
done();
10211065
} else {
10221066
const file = files.pop();
10231067
readFile(file).then(function() {
@@ -1056,24 +1100,77 @@ function cordova_debug() {
10561100
cordova.run();
10571101
}
10581102

1059-
function cordova_build(cb) {
1103+
function cordova_debug_build(done) {
10601104
cordova.build({
10611105
'platforms': ['android'],
10621106
'options': {
1063-
release: true,
1107+
release: false,
10641108
buildConfig: 'build.json',
10651109
},
10661110
}).then(function() {
10671111
process.chdir('../');
1068-
cb();
1112+
1113+
console.log(`APK has been generated at ${CORDOVA_DIST_DIR}platforms/android/app/build/outputs/apk/release/app-release.apk`);
1114+
1115+
done();
10691116
});
1070-
console.log(`APK will be generated at ${CORDOVA_DIST_DIR}platforms/android/app/build/outputs/apk/release/app-release.apk`);
10711117
}
10721118

1073-
async function cordova_release() {
1074-
const filename = await getReleaseFilename('android', 'apk');
1119+
function cordova_build(done) {
1120+
let storePassword = '';
1121+
return gulp.series(function password_prompt() {
1122+
return gulp.src('.')
1123+
.pipe(prompt.prompt({
1124+
type: 'password',
1125+
name: 'storePassword',
1126+
message: 'Please enter the keystore password:',
1127+
}, function(res) {
1128+
storePassword = res.storePassword;
1129+
}));
1130+
}, function set_password() {
1131+
return gulp.src(`build.json`)
1132+
.pipe(jeditor({
1133+
'android': {
1134+
'release' : {
1135+
'storePassword': storePassword,
1136+
},
1137+
},
1138+
}))
1139+
.pipe(gulp.dest('./'));
1140+
}, function build(done2) {
1141+
return cordova.build({
1142+
'platforms': ['android'],
1143+
'options': {
1144+
release: true,
1145+
buildConfig: 'build.json',
1146+
},
1147+
}).then(function() {
1148+
// Delete the file containing the store password
1149+
del(['build.json'], { force: true });
1150+
process.chdir('../');
1151+
1152+
console.log('AAB has been generated at dist_cordova/platforms/android/app/build/outputs/bundle/release/app.aab');
1153+
done2();
1154+
});
1155+
})(done);
1156+
}
1157+
1158+
async function cordova_debug_release() {
1159+
const filename = getReleaseFilename('android', 'apk');
1160+
10751161
console.log(`Release APK : release/${filename}`);
1076-
return gulp.src(`${CORDOVA_DIST_DIR}platforms/android/app/build/outputs/apk/release/app-release.apk`)
1162+
1163+
return gulp.src(`${CORDOVA_DIST_DIR}platforms/android/app/build/outputs/apk/debug/app-debug.apk`)
1164+
.pipe(rename(filename))
1165+
.pipe(gulp.dest(RELEASE_DIR));
1166+
}
1167+
1168+
async function cordova_release() {
1169+
const filename = getReleaseFilename('android', 'aab');
1170+
1171+
console.log(`Release AAB : release/${filename}`);
1172+
1173+
return gulp.src(`${CORDOVA_DIST_DIR}platforms/android/app/build/outputs/bundle/release/app.aab`)
10771174
.pipe(rename(filename))
10781175
.pipe(gulp.dest(RELEASE_DIR));
10791176
}

0 commit comments

Comments
 (0)