diff --git a/.github/workflows/compile.yaml b/.github/workflows/compile.yaml index 91efb38..246eeff 100644 --- a/.github/workflows/compile.yaml +++ b/.github/workflows/compile.yaml @@ -3,11 +3,11 @@ on: workflow_dispatch: jobs: - compile_linux: + build_linux_x64: runs-on: ubuntu-latest steps: # Checks-out repository under $GITHUB_WORKSPACE - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Install dependencies - name: Install Dart SDK run: | @@ -24,40 +24,57 @@ jobs: dart compile exe "./bin/main.dart" -o "./nexustools" # Upload binary - name: Upload Dart executable - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: nexustools-linux-x64 path: nexustools - compile_windows: + build_windows_x64: runs-on: windows-latest steps: - name: Install Dart SDK run: | choco install dart-sdk - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Compile Dart executable run: | C:\tools\dart-sdk\bin\dart pub get C:\tools\dart-sdk\bin\dart compile exe "bin\main.dart" -o "nexustools.exe" - name: Upload Dart executable - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: nexustools-windows-x64 path: nexustools.exe - compile_macos: - runs-on: macos-latest + build_macos_x64: + runs-on: macos-12 steps: - name: Install Dart SDK run: | brew tap dart-lang/dart brew install dart - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Compile Dart executable run: | dart pub get dart compile exe "./bin/main.dart" -o "./nexustools" - name: Upload Dart executable - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: nexustools-macos-x64 + path: nexustools + build_macos_arm: + runs-on: macos-latest + steps: + - name: Install Dart SDK + run: | + brew tap dart-lang/dart + brew install dart + - uses: actions/checkout@v4 + - name: Compile Dart executable + run: | + dart pub get + dart compile exe "./bin/main.dart" -o "./nexustools" + - name: Upload Dart executable + uses: actions/upload-artifact@v4 + with: + name: nexustools-macos-arm64 path: nexustools \ No newline at end of file diff --git a/bin/main.dart b/bin/main.dart index 541c2b3..7f1158e 100644 --- a/bin/main.dart +++ b/bin/main.dart @@ -10,7 +10,7 @@ String macZip = 'https://dl.google.com/android/repository/platform-tools-latest- String linuxZip = 'https://dl.google.com/android/repository/platform-tools-latest-linux.zip'; String windowsZip = 'https://dl.google.com/android/repository/platform-tools-latest-windows.zip'; Map envVars = io.Platform.environment; -double appVersion = 5.6; +double appVersion = 5.7; String baseRepo = 'corbindavenport/nexus-tools'; // Function for checking for update @@ -50,7 +50,7 @@ String nexusToolsDir() { } // Function for installing Platform Tools package -Future installPlatformTools() async { +Future installPlatformTools(cpuArch) async { print('[INFO] You agree to the Terms & Conditions by installing this software: https://developer.android.com/studio/terms'); var dir = nexusToolsDir(); // Get the proper ZIP file @@ -68,7 +68,7 @@ Future installPlatformTools() async { try { var data = await http.readBytes(net); var archive = ZipDecoder().decodeBytes(data); - extractArchiveToDisk(archive, dir); + await extractArchiveToDisk(archive, dir); } catch (e) { print('[EROR] There was an error downloading Platform Tools: ' + e.toString()); io.exit(1); @@ -102,19 +102,23 @@ Future installPlatformTools() async { } // Windows-specific functions if (io.Platform.isWindows) { - // Check if Universal Adb Driver package is already installed - var info = await io.Process.run('wmic', ['product', 'get', 'Name']); - var parsedInfo = info.stdout.toString(); - if (parsedInfo.contains('Universal Adb Driver')) { - print('[ OK ] Universal ADB Drivers already installed.'); - } else { - // Prompt to install drivers - print('[WARN] Drivers may be required for ADB if they are not already installed.'); - io.stdout.write('[WARN] Install drivers from adb.clockworkmod.com? [Y/N] '); - var input = io.stdin.readLineSync(); - if (input?.toLowerCase() == 'y') { - await installWindowsDrivers(dir); + // Install Universal Adb Driver package on x86_64 Windows + if (cpuArch == 'AMD64') { + var info = await io.Process.run('PowerShell', ['-Command', 'Get-WmiObject -Class Win32_Product | Select-Object -Property Name']); + var parsedInfo = info.stdout.toString(); + if (parsedInfo.contains('Universal Adb Driver')) { + print('[ OK ] Universal ADB Drivers already installed.'); + } else { + // Prompt to install drivers + print('[WARN] Drivers may be required for ADB if they are not already installed.'); + io.stdout.write('[WARN] Install drivers from adb.clockworkmod.com? [Y/N] '); + var input = io.stdin.readLineSync(); + if (input?.toLowerCase() == 'y') { + await installWindowsDrivers(dir); + } } + } else { + print('[WARN] Universal ADB Driver package cannot be installed on $cpuArch, some devices might not work.'); } // Check if old Nexus Tools directory needs to be deleted var oldFolder = envVars['UserProfile'] + r'\NexusTools'; @@ -207,7 +211,7 @@ Future installWindowsDrivers(String dir) async { } // Function for Plausible Analytics reporting -void connectAnalytics() async { +void connectAnalytics(String cpuArch) async { var uuid = Uuid(); var id = uuid.v4(); // Get exact operating system @@ -221,12 +225,11 @@ void connectAnalytics() async { } else { realOS = io.Platform.operatingSystem; } - var cpu = await sys.getCPUArchitecture(); // Set data var net = Uri.parse('https://plausible.io/api/event'); final ipv4 = await Ipify.ipv4(); var netHeaders = {'user-agent': 'Nexus Tools', 'X-Forwarded-For': ipv4, 'Content-Type': 'application/json', 'User-Agent': 'Mozilla/5.0 ($realOS) AppleWebKit/500 (KHTML, like Gecko) Chrome/$appVersion $id'}; - var netBody = '{"name":"pageview","url":"app://localhost/$realOS/$cpu","domain":"nexustools.corbin.io"}'; + var netBody = '{"name":"pageview","url":"app://localhost/$realOS/$cpuArch","domain":"nexustools.corbin.io"}'; // Send request try { await http.post(net, headers: netHeaders, body: netBody); @@ -236,7 +239,7 @@ void connectAnalytics() async { } // Pre-installation steps -Future checkInstall() async { +Future checkInstall(String cpuArch) async { // Check if directory already exists var dir = nexusToolsDir(); var installExists = false; @@ -270,9 +273,9 @@ Future checkInstall() async { } } -void printHelp() { +void printHelp(cpuArch) { var helpDoc = ''' -Nexus Tools $appVersion +Nexus Tools $appVersion on $cpuArch Downloader/management app for Android SDK Platform Tools Usage: nexustools [OPTIONS] @@ -290,8 +293,9 @@ Example: nexustools -i (this installs Platform Tools) } void main(List arguments) async { + var cpuArch = await sys.getCPUArchitecture(); if (arguments.contains('-i') || arguments.contains('--install')) { - print('[INFO] Nexus Tools $appVersion'); + print('[INFO] Nexus Tools $appVersion on $cpuArch'); // Check version unless Nexus Tools is running from web (curl) installer // The web installer adds the -w parameter if (!arguments.contains('-w')) { @@ -301,11 +305,11 @@ void main(List arguments) async { if (arguments.contains('--no-analytics')) { print('[ OK ] Plausible Analytics are disabled.'); } else { - connectAnalytics(); + connectAnalytics(cpuArch); } // Start installation - await checkInstall(); - await installPlatformTools(); + await checkInstall(cpuArch); + await installPlatformTools(cpuArch); // Post-install var appName = ''; if (io.Platform.isWindows) { @@ -322,7 +326,7 @@ void main(List arguments) async { // Start removal await removePlatformTools(); } else if (arguments.contains('-h') || arguments.contains('--help')) { - printHelp(); + printHelp(cpuArch); } else if (arguments.contains('-c') || arguments.contains('--check')) { await checkUpdate(); } else { diff --git a/install.sh b/install.sh index 5a4b3bb..67f152c 100755 --- a/install.sh +++ b/install.sh @@ -33,11 +33,10 @@ fi mkdir -p $DIR # Start Dart executable -if [ "$OS" = "Darwin" ]; then # macOS - # Install Rosetta x86 emulation layer if needed - if [ "$ARCH" = "arm64" ]; then - echo "[WARN] Rosetta 2 compatibility layer is required. If installation fails, run Nexus Tools again after running this command: /usr/sbin/softwareupdate --install-rosetta" - fi +if [ "$OS" = "Darwin" ] && [ "$ARCH" = "arm64" ]; then # Apple Silicon Mac + DOWNLOAD="$BASEURL/releases/latest/download/nexustools-macos-arm64.zip" + _run_executable +elif [ "$OS" = "Darwin" ] && [ "$ARCH" = "x86_64" ]; then # Intel Mac DOWNLOAD="$BASEURL/releases/latest/download/nexustools-macos-x64.zip" _run_executable elif [ "$OS" = "Linux" ] && [ "$ARCH" = "x86_64" ]; then # Generic Linux diff --git a/lib/sys.dart b/lib/sys.dart index 7daf3d6..6b11281 100644 --- a/lib/sys.dart +++ b/lib/sys.dart @@ -25,26 +25,24 @@ void checkIfInstalled(String dir, String command, String commandName) async { } } -// Function get current CPU architecture +// Function to get the current CPU architecture Future getCPUArchitecture() async { if (io.Platform.isWindows) { + // Possible values: AMD64, ARM64 var cpu = envVars['PROCESSOR_ARCHITECTURE']; - return cpu; - } else if (io.Platform.isMacOS) { - // Get architecture reported by the system - var info = await io.Process.run('uname', ['-m']); - var cpu = info.stdout.toString().replaceAll('\n', ''); - if (cpu == 'x86_64') { - // Check if running under Rosetta 2 - var rosetta = await io.Process.run('sysctl', ['-in', 'sysctl.proc_translated']); - var rosettaStr = rosetta.stdout.toString().replaceAll('\n', ''); - // This command will run '1' if we're running under Rosetta 2 - if (rosettaStr == '1') { - cpu = 'arm64'; + // Check if being emulated in ARM and return true architecture + try { + var buildArch = await io.Process.run('reg', ['query', r'HKEY_LOCAL_MACHINE\SYSTEM\Software\Microsoft\BuildLayers\DesktopEditions', '/v', 'BuildArch']); + if (buildArch.stdout.toString().toLowerCase().contains('arm64')) { + cpu = 'ARM64'; } + } catch (e) { + // Fail silently } return cpu; } else { + // Possible values: x86_64, arm64 + // This doesn't check for Rosetta emulation on macOS var info = await io.Process.run('uname', ['-m']); var cpu = info.stdout.toString().replaceAll('\n', ''); return cpu; diff --git a/pubspec.lock b/pubspec.lock index 9a9d5cc..6c47ed9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: "direct dev" description: name: archive - sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d url: "https://pub.dev" source: hosted - version: "3.3.7" + version: "3.6.1" async: dependency: transitive description: @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.19.0" console: dependency: "direct dev" description: @@ -33,22 +33,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" - convert: - dependency: transitive - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" crypto: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" dart_ipify: dependency: "direct dev" description: @@ -57,22 +49,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" http: dependency: "direct dev" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.2.1" http_parser: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + sha256: "40f592dd352890c3b60fec1b68e786cefb9603e05ff303dbc4dda49b304ecdf4" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.0" io: dependency: "direct dev" description: @@ -81,38 +81,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.15.0" path: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" - url: "https://pub.dev" - source: hosted - version: "3.7.3" + version: "1.9.0" source_span: dependency: transitive description: @@ -121,6 +105,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" string_scanner: dependency: transitive description: @@ -141,18 +133,18 @@ packages: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" uuid: dependency: "direct dev" description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "4.4.0" vector_math: dependency: transitive description: @@ -161,5 +153,13 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" sdks: - dart: ">=3.3.1 <4.0.0" + dart: ">=3.4.2 <4.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index df2eef3..b5a0648 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ version: 5.0.0 homepage: https://github.com/corbindavenport/nexus-tools/ environment: - sdk: '>=3.3.1' + sdk: '>=3.4.2' # dependencies: # path: ^1.8.0 @@ -13,6 +13,6 @@ dev_dependencies: http: io: uuid: - archive: ^3.2.2 + archive: ^3.6.1 console: dart_ipify: ^1.1.1 \ No newline at end of file