[android] added module
This commit is contained in:
127
haxetool/android.js
Normal file
127
haxetool/android.js
Normal file
@@ -0,0 +1,127 @@
|
||||
const fs = require('fs');
|
||||
const exec = require('./exec');
|
||||
const through = require('through2');
|
||||
const Sdk = require('./sdk');
|
||||
const Env = require('./env');
|
||||
|
||||
|
||||
class Android extends Sdk {
|
||||
|
||||
constructor(version) {
|
||||
super(Android.ID, version || Android.VERSION);
|
||||
}
|
||||
|
||||
get prepared() {
|
||||
try {
|
||||
return fs.existsSync(`${this.path}/platform-tools/adb`);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
get link() {
|
||||
const system = Sdk.System.isWindows ? 'windows' : Sdk.System.isLinux ? 'linux' : null;
|
||||
if (!system) throw 'Unsupported system';
|
||||
//return `https://dl.google.com/android/repository/sdk-tools-${system}-${this.version}.zip`;
|
||||
return `https://dl.google.com/android/repository/tools_r${this.version}-${system}.zip`;
|
||||
}
|
||||
|
||||
prepare() {
|
||||
return this.prepared ? Promise.resolve() : super.prepare(0).then(() => {
|
||||
return this.sdkmanager([
|
||||
'ndk-bundle',
|
||||
'tools',
|
||||
'platform-tools',
|
||||
'build-tools;27.0.3',
|
||||
'platforms;android-27',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
sdkmanager(packages) {
|
||||
const androidBin = `${this.path}/tools/bin/sdkmanager`;
|
||||
if (fs.existsSync(androidBin)) {
|
||||
fs.chmodSync(androidBin, 0o755);
|
||||
}
|
||||
const yes = '(while sleep 3; do echo "y"; done)';
|
||||
return exec('.', [yes, '|', androidBin].concat(packages.map(name => `"${name}"`)).join(' '));
|
||||
}
|
||||
|
||||
activate() {
|
||||
Env.set('ANDROID_HOME', this.path);
|
||||
}
|
||||
|
||||
adb(args) {
|
||||
const adbBin = `${this.path}/platform-tools/adb`;
|
||||
return exec('.', [adbBin].concat(args).join(' ')).then(data => {
|
||||
for (let line of data.stderr.split('\n')) {
|
||||
if (line.indexOf('Error') > -1) {
|
||||
throw line;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
aapt(args) {
|
||||
let buildToolsVersion = null;
|
||||
fs.readdirSync(`${this.path}/build-tools`).forEach(file => {
|
||||
buildToolsVersion = file;
|
||||
});
|
||||
const aaptBin = `${this.path}/build-tools/${buildToolsVersion}/aapt`;
|
||||
return exec('.', [aaptBin].concat(args).join(' '));
|
||||
}
|
||||
|
||||
apk() {
|
||||
const self = this;
|
||||
return through.obj(function(file, enc, callback) {
|
||||
self.aapt(['l', '-a', file.path]).then(data => {
|
||||
let activity = false;
|
||||
for (let line of data.stdout.split('\n')) {
|
||||
if (line.indexOf('package') > -1) {
|
||||
const value = /"(.*?)"/.exec(line);
|
||||
if (value) file.package = value[1]
|
||||
}
|
||||
if (line.indexOf('activity') > -1) {
|
||||
activity = true;
|
||||
}
|
||||
if (activity && line.indexOf('name') > -1) {
|
||||
const value = /"(.*?)"/.exec(line);
|
||||
if (value) {
|
||||
file.activity = value[1];
|
||||
activity = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.push(file);
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
install() {
|
||||
const self = this;
|
||||
return through.obj(function(file, enc, callback) {
|
||||
self.adb(['install', '-r', file.path]).then(() => {
|
||||
this.push(file);
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
start() {
|
||||
const self = this;
|
||||
return through.obj((file, enc, callback) => {
|
||||
const name = `${file.package}/${file.activity}`;
|
||||
self.adb(['shell', 'am', 'start', '-n', name]).then(() => callback());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Android.ID = 'android';
|
||||
|
||||
Android.VERSION_25_2_3 = '25.2.3';
|
||||
Android.VERSION_3859397 = '3859397';
|
||||
|
||||
Android.VERSION = Android.VERSION_25_2_3;
|
||||
|
||||
module.exports = Android;
|
||||
@@ -92,7 +92,11 @@ class Haxe extends Sdk {
|
||||
}
|
||||
const target = path.resolve(buildDir, platform, 'bin');
|
||||
fse.emptyDirSync(target);
|
||||
return this.haxelib(args).then(() => vfs.src(`${target}/**/*`));
|
||||
const result = {
|
||||
'android': 'app/build/outputs/apk/*.apk',
|
||||
'flash': '*.swf',
|
||||
}[platform] || '**/*';
|
||||
return this.haxelib(args).then(() => vfs.src(`${target}/${result}`));
|
||||
}
|
||||
|
||||
build(platform, config, debug=false) {
|
||||
@@ -121,7 +125,7 @@ class Haxe extends Sdk {
|
||||
args.push('-debug');
|
||||
}
|
||||
const target = path.resolve(buildDir, platform, 'bin');
|
||||
fse.emptyDirSync(target)
|
||||
fse.emptyDirSync(target);
|
||||
for (const asset of config.assets) {
|
||||
fse.copySync(asset, path.join(target, asset.split(path.sep).pop()));
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ const fs = require('fs');
|
||||
const fse = require('fs-extra');
|
||||
const Haxe = require('./haxe');
|
||||
const FlashPlayer = require('./flashplayer');
|
||||
const Android = require('./android');
|
||||
const Neko = require('./neko');
|
||||
const debug = require('./debug');
|
||||
const webserver = require('gulp-webserver');
|
||||
const run = require('../run/index');
|
||||
const tail = require('./tail');
|
||||
const exec = require('./exec');
|
||||
const deb = require('gulp-debian');
|
||||
const {BuildSystem, Platform, Config} = require('./core');
|
||||
const vfs = require('vinyl-fs');
|
||||
@@ -36,6 +38,14 @@ class Target {
|
||||
this.target = 'target';
|
||||
}
|
||||
|
||||
prepare() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
call() {
|
||||
throw 'Not Implemented';
|
||||
}
|
||||
|
||||
get targetPath() {
|
||||
return path.resolve(this.target, this.config.name, this.platform);
|
||||
}
|
||||
@@ -52,14 +62,6 @@ class Builder extends Target {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
prepare() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
call() {
|
||||
throw 'Not Implemented';
|
||||
}
|
||||
|
||||
static register(buildSystem, builder) {
|
||||
Builder.factory[buildSystem] = builder;
|
||||
}
|
||||
@@ -79,15 +81,26 @@ class HaxeBuilder extends Builder {
|
||||
constructor(config, platform, buildSystem, debug) {
|
||||
super(config, platform, buildSystem, debug);
|
||||
this.haxe = new Haxe();
|
||||
this.android = new Android();
|
||||
}
|
||||
|
||||
prepare() {
|
||||
let result = this.haxe.prepare().then(() => this.haxe.install(this.config.libs));
|
||||
/*if (this.buildSystem === BuildSystem.OPENFL) {
|
||||
if (this.buildSystem === BuildSystem.OPENFL) {
|
||||
if (this.platform === Platform.ANDROID) {
|
||||
result = result.then(() => this.android.prepare()).then(() => this.android.activate());
|
||||
}
|
||||
result = result.then(() => {
|
||||
return this.haxe.haxelib(['run', 'openfl', 'setup', this.platform]);
|
||||
return exec('.', [
|
||||
'echo',
|
||||
`"${this.android.path}"`,
|
||||
`"${this.android.path + '/ndk-bundle'}"`,
|
||||
'|',
|
||||
this.haxe.haxelibBin, 'run', 'openfl', 'setup', this.platform,
|
||||
].join(' '));
|
||||
//return this.haxe.haxelib(['echo'].concat(answers.map(item => `"${item}"`)).concat(['|', 'run', 'openfl', 'setup', this.platform]));
|
||||
});
|
||||
}*/
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -112,20 +125,17 @@ Builder.register(BuildSystem.OPENFL, HaxeBuilder);
|
||||
*/
|
||||
class Packer extends Target {
|
||||
|
||||
prepare() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
call() {
|
||||
throw 'Not Implemented';
|
||||
}
|
||||
|
||||
static register(platform, packer) {
|
||||
Packer.factory[platform] = packer;
|
||||
static register(platform, name, packer) {
|
||||
if (!Packer.factory[platform]) Packer.factory[platform] = {};
|
||||
Packer.factory[platform][name] = packer;
|
||||
}
|
||||
|
||||
static new(config, platform) {
|
||||
return new Packer.factory[platform](config);
|
||||
static new(config, platform, name) {
|
||||
return new Packer.factory[platform][name](config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +144,7 @@ Packer.factory = {};
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class FlashPacker extends Packer {
|
||||
class FlashHTMLPacker extends Packer {
|
||||
|
||||
constructor(config) {
|
||||
super(config, Platform.FLASH);
|
||||
@@ -150,12 +160,14 @@ class FlashPacker extends Packer {
|
||||
}
|
||||
}
|
||||
|
||||
Packer.register(Platform.FLASH, FlashPacker);
|
||||
FlashHTMLPacker.NAME = 'html';
|
||||
|
||||
Packer.register(Platform.FLASH, FlashHTMLPacker.NAME, FlashHTMLPacker);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class LinuxPacker extends Packer {
|
||||
class LinuxDEBPacker extends Packer {
|
||||
|
||||
constructor(config) {
|
||||
super(config, Platform.LINUX);
|
||||
@@ -192,7 +204,9 @@ class LinuxPacker extends Packer {
|
||||
}
|
||||
}
|
||||
|
||||
Packer.register(Platform.LINUX, LinuxPacker);
|
||||
LinuxDEBPacker.NAME = 'deb';
|
||||
|
||||
Packer.register(Platform.LINUX, LinuxDEBPacker.NAME, LinuxDEBPacker);
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -204,14 +218,6 @@ class Runner extends Target {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
prepare() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
call() {
|
||||
throw 'Not Implemented';
|
||||
}
|
||||
|
||||
log(stream) {
|
||||
return stream
|
||||
.pipe(tail(debug.log))
|
||||
@@ -319,6 +325,33 @@ class NekoRunner extends Runner {
|
||||
|
||||
Runner.register(Platform.NEKO, NekoRunner);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class AndroidRunner extends Runner {
|
||||
|
||||
constructor(config, debug) {
|
||||
super(config, Platform.ANDROID, debug);
|
||||
this.android = new Android();
|
||||
}
|
||||
|
||||
prepare() {
|
||||
return this.android.prepare();
|
||||
}
|
||||
|
||||
call() {
|
||||
const target = this.targetPath;
|
||||
const filename = path.resolve(target, this.config.meta.filename+'-debug.apk');
|
||||
console.log(filename);
|
||||
return gulp.src(filename)
|
||||
.pipe(this.android.apk())
|
||||
.pipe(this.android.install())
|
||||
.pipe(this.android.start());
|
||||
}
|
||||
}
|
||||
|
||||
Runner.register(Platform.ANDROID, AndroidRunner);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -340,16 +373,20 @@ class Project {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
run(platform) {
|
||||
run(platform, debug) {
|
||||
const runner = Runner.new(this.config, platform, debug);
|
||||
return this.build(platform, debug).concat([
|
||||
return [
|
||||
runner.prepare.bind(runner),
|
||||
runner.call.bind(runner),
|
||||
]);
|
||||
];
|
||||
}
|
||||
|
||||
pack(platform) {
|
||||
const packer = Packer.new(this.config, platform);
|
||||
test(platform) {
|
||||
return this.build(platform, debug).concat(this.run(platform, debug));
|
||||
}
|
||||
|
||||
pack(platform, name) {
|
||||
const packer = Packer.new(this.config, platform, name);
|
||||
return [
|
||||
packer.prepare.bind(packer),
|
||||
packer.call.bind(packer),
|
||||
@@ -360,9 +397,14 @@ class Project {
|
||||
const _gulp = (external_gulp || gulp);
|
||||
for (const platform of this.platforms) {
|
||||
module.exports[`${this.config.name}:${platform}:build`] = _gulp.series(this.build(platform));
|
||||
module.exports[`${this.config.name}:${platform}:run`] = _gulp.series(this.run(platform));
|
||||
if (Runner.factory[platform]) {
|
||||
module.exports[`${this.config.name}:${platform}:run`] = _gulp.series(this.run(platform));
|
||||
module.exports[`${this.config.name}:${platform}:test`] = _gulp.series(this.test(platform));
|
||||
}
|
||||
if (Packer.factory[platform]) {
|
||||
module.exports[`${this.config.name}:${platform}:pack`] = _gulp.series(this.pack(platform));
|
||||
for (const name of Object.keys(Packer.factory[platform])) {
|
||||
module.exports[`${this.config.name}:${platform}:${name}`] = _gulp.series(this.pack(platform, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
||||
@@ -85,7 +85,7 @@ class Sdk {
|
||||
stream = stream.on('downloadProgress', (p) => bar.update(p.percent));
|
||||
if (this.link.endsWith('.zip')) {
|
||||
stream = stream.pipe(unzip.Parse()).on('entry', (entry) => {
|
||||
const filePath = entry.path.split('/').slice(1).join(path.sep);
|
||||
const filePath = entry.path.split('/').slice(strip).join(path.sep);
|
||||
if (filePath.length > 0) {
|
||||
if (entry.type === 'Directory') {
|
||||
fse.ensureDirSync(path.join(this.path, path.normalize(filePath)));
|
||||
|
||||
Reference in New Issue
Block a user