const fs = require('fs'); const path = require('path'); 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'; if (this.version.indexOf('.') === -1) { return `https://dl.google.com/android/repository/tools_r${this.version}-${system}.zip`; } else { return `https://dl.google.com/android/repository/sdk-tools-${system}-${this.version}.zip`; } } get android_home() { return this.path; } get ndk_home() { return path.join(this.path, 'ndk-bundle') } prepare() { return super.prepare(0); } sdkmanager(packages) { const androidBin = path.join(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.android_home); Env.set('ANDROID_NDK_HOME', this.ndk_home); Env.set('NDK_HOME', this.ndk_home); } adb(args) { const adbBin = path.join(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(path.join(this.path, 'build-tools')).forEach(file => { buildToolsVersion = file; }); const aaptBin = path.join(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_3859397; module.exports = Android;