diff --git a/.github/workflows/compile.yaml b/.github/workflows/compile.yaml new file mode 100644 index 0000000..91efb38 --- /dev/null +++ b/.github/workflows/compile.yaml @@ -0,0 +1,63 @@ +name: Compile Nexus Tools +on: + workflow_dispatch: + +jobs: + compile_linux: + runs-on: ubuntu-latest + steps: + # Checks-out repository under $GITHUB_WORKSPACE + - uses: actions/checkout@v2 + # Install dependencies + - name: Install Dart SDK + run: | + sudo apt-get update + sudo apt-get install apt-transport-https -y + sudo sh -c 'wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -' + sudo sh -c 'wget -qO- https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list' + sudo apt-get update + sudo apt install dart -y + - name: Compile Dart executable + run: | + cd $GITHUB_WORKSPACE + dart pub get + dart compile exe "./bin/main.dart" -o "./nexustools" + # Upload binary + - name: Upload Dart executable + uses: actions/upload-artifact@v2 + with: + name: nexustools-linux-x64 + path: nexustools + compile_windows: + runs-on: windows-latest + steps: + - name: Install Dart SDK + run: | + choco install dart-sdk + - uses: actions/checkout@v2 + - 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 + with: + name: nexustools-windows-x64 + path: nexustools.exe + compile_macos: + runs-on: macos-latest + steps: + - name: Install Dart SDK + run: | + brew tap dart-lang/dart + brew install dart + - uses: actions/checkout@v2 + - 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 + with: + name: nexustools-macos-x64 + path: nexustools \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0880705 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.packages +.dart_tool +dist/* +.DS_Store \ No newline at end of file diff --git a/DONATE.md b/DONATE.md new file mode 100644 index 0000000..d1f1cb8 --- /dev/null +++ b/DONATE.md @@ -0,0 +1,7 @@ +# Donate + +If you found Nexus Tools useful, please consider donating to support development! It takes a lot of work and testing to ensure Nexus Tools remains compatible with multiple operating systems and hardware platforms. + +**[Donate with PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=4SZVSMJKDS35J&lc=US&item_name=Nexus%20Tools%20Donation¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted)** + +**[Join the Patreon](https://www.patreon.com/corbindavenport)** \ No newline at end of file diff --git a/README.md b/README.md index 92311af..47af3bd 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,57 @@ -![alt text](http://i.imgur.com/shjM51Q.png "Nexus Tools") -=========== +# Nexus Tools -Nexus Tools is an installer for the Android debug/development command-line tools ADB (Android Device Bridge) and Fastboot for Mac OS X, Linux, and Google Chrome/Chromium OS. The script does not need to be downloaded, simply copy and paste this command into the terminal and run it to install Nexus Tools: +Nexus Tools is an installer for the [Android SDK Platform Tools](https://developer.android.com/studio/releases/platform-tools) package, which includes [ADB](https://developer.android.com/studio/command-line/adb.html), Fastboot, and other applications. Nexus Tools is writen in Dart, and can run on Linux, macOS, Windows, Windows Subsystem for Linux, and Chrome OS. + +Nexus Tools downloads the latest Platform tools package directly from Google's servers (so you're always getting the latest version), saves them to `~/.nexustools` (`$Home\NexusTools` on Windows), and adds the directory to your system's path. On Windows, Nexus Tools can optionally install [Koush's Universal ADB Driver](https://github.com/koush/UniversalAdbDriver). + +Once Nexus Tools is finished, you can run `adb`, `fastboot`, and other commands with no problems. **You need to open a new terminal/command line window after installation for changes to take effect.** The SDK Platform Tools can be updated by running `nexustools -i`, or you can uninstall everything by running `nexustools -r`. + +### How to use on Linux, macOS, and Chrome OS + +Paste this command into the Terminal app: + ``` -bash <(curl https://raw.githubusercontent.com/corbindavenport/nexus-tools/master/install.sh) +bash <(curl -s https://raw.githubusercontent.com/corbindavenport/nexus-tools/master/install.sh) ``` -and this command to un-install Nexus Tools: + +You can also download the Mac and Linux versions from the [latest release page](https://github.com/corbindavenport/nexus-tools/releases/), un-zip the file, and run it from the Terminal. + +### How to use on Windows + +Open Windows PowerShell from the Start Menu and paste this command: + ``` -bash <(curl https://raw.githubusercontent.com/corbindavenport/nexus-tools/master/uninstall.sh) +iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/corbindavenport/nexus-tools/master/install.ps1')) ``` -These commands will download the selected script and run it. The script will download the files it needs during runtime, so it requires an internet connection. The script works on both Mac OS X and Linux (as long as the curl package is installed). -Support for Google Chrome OS is experimental at this time, as I was only able to test it on a build of Chromium for x86 PCs. I don't have an actual Chromebook to test it on, but Nexus Tools should work correctly on both x86 and ARM Chromebooks. +You can also download the Windows version from the [latest release page](https://github.com/corbindavenport/nexus-tools/releases/), un-zip the file, and run it from Windows PowerShell or the Command Prompt. -Nexus Tools requires sudo privileges to install/uninstall the adb and fastboot tools to /usr/bin, so they can be run without typing the full directory. +### Compatibility ---------------------------------------- +Nexus Tools is only available for x86_64 macOS, Linux, and Windows, because Google only provides native Platform Tools binaries for those platforms. On Macs with Apple Silicon, Nexus Tools runs in the [Rosetta 2 compatibility layer](https://support.apple.com/en-us/HT211861). -__XDA Thread:__ [http://forum.xda-developers.com/showthread.php?t=2564453](http://forum.xda-developers.com/showthread.php?t=2564453) +### Analytics -__XDA Article:__ [http://www.xda-developers.com/android/set-up-adb-and...](http://www.xda-developers.com/android/set-up-adb-and-fastboot-on-linux-mac-os-x-and-chrome-os-with-a-single-command/) +Nexus Tools uses [Plausible Analytics](https://plausible.io) to transmit your operating system and CPU architecture during the installation process. This data is not sold or shared in any way, it's only for me to know which hardware platforms I should focus my attention on. You can disable analytics reporting by adding the `--no-analytics` parameter to the install command, like this: ---------------------------------------- +``` +bash <(curl -s https://raw.githubusercontent.com/corbindavenport/nexus-tools/master/install.sh) --no-analytics +``` - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. +It also works when running Nexus Tools locally: - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +``` +nexustools --no-analytics +``` - You should have received a copy of the GNU General Public License - along with this program. If not, see . +This analytics data is viewable publicly at [plausible.io/nexustools.corbin.io](https://plausible.io/nexustools.corbin.io). + +### Development info + +Nexus Tools is written in Dart, so you need the [Dart SDK](https://dart.dev/get-dart) to work on it. You can run Nexus Tools from source like this: + +``` +dart ./bin/main.dart +``` + +The `compile.sh` (macOS and Linux) and `compile.ps1` scripts create executables and zip them. You can also use GitHub Actions to compile Nexus Tools, by navigating to Actions > Compile Nexus Tools > Run workflow. \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..18b40b8 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,16 @@ +# Defines a default set of lint rules enforced for projects at Google. For +# details and rationale, see +# https://github.com/dart-lang/pedantic#enabled-lints. + +include: package:pedantic/analysis_options.yaml + +# For lint rules and documentation, see http://dart-lang.github.io/linter/lints. + +# Uncomment to specify additional rules. +# linter: +# rules: +# - camel_case_types + +# analyzer: +# exclude: +# - path/to/excluded/files/** diff --git a/bin/linux-arm-adb b/bin/linux-arm-adb deleted file mode 100755 index e0824f1..0000000 Binary files a/bin/linux-arm-adb and /dev/null differ diff --git a/bin/linux-arm-fastboot b/bin/linux-arm-fastboot deleted file mode 100755 index 1c4e974..0000000 Binary files a/bin/linux-arm-fastboot and /dev/null differ diff --git a/bin/linux-i386-adb b/bin/linux-i386-adb deleted file mode 100755 index aba34a6..0000000 Binary files a/bin/linux-i386-adb and /dev/null differ diff --git a/bin/linux-i386-fastboot b/bin/linux-i386-fastboot deleted file mode 100755 index 4fe6bab..0000000 Binary files a/bin/linux-i386-fastboot and /dev/null differ diff --git a/bin/mac-adb b/bin/mac-adb deleted file mode 100755 index 3b154cb..0000000 Binary files a/bin/mac-adb and /dev/null differ diff --git a/bin/mac-fastboot b/bin/mac-fastboot deleted file mode 100755 index 11a6870..0000000 Binary files a/bin/mac-fastboot and /dev/null differ diff --git a/bin/main.dart b/bin/main.dart new file mode 100644 index 0000000..2c8d520 --- /dev/null +++ b/bin/main.dart @@ -0,0 +1,327 @@ +import 'package:archive/archive_io.dart'; +import 'package:http/http.dart' as http; +import 'dart:io' as io; +import 'package:archive/archive.dart'; +import 'package:uuid/uuid.dart'; +import 'dart:convert'; +import 'package:nexustools/sys.dart' as sys; + +String macZip = + 'https://dl.google.com/android/repository/platform-tools-latest-darwin.zip'; +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'; +List supportedCPUs = ['amd64', 'x86_64', 'AMD64']; +Map envVars = io.Platform.environment; +double appVersion = 5.4; + +// Function for checking for update +Future checkUpdate() async { + var net = Uri.parse( + 'https://api.github.com/repos/corbindavenport/nexus-tools/releases/latest'); + try { + var data = await http.read(net); + var parsedData = json.decode(data); + // Compare versions + if (double.parse(parsedData['tag_name']) > appVersion) { + print( + '[INFO] Nexus Tools update available! Download: https://git.io/JBuTh'); + } else { + print('[INFO] You have the latest version of Nexus Tools.'); + } + } catch (e) { + print('[EROR] Could not check for updates.'); + } +} + +// Function for obtaining Nexus Tools path +// Credit: https://stackoverflow.com/a/25498458 +String nexusToolsDir() { + var home = ''; + if (io.Platform.isMacOS) { + home = envVars['HOME']; + } else if (io.Platform.isLinux) { + home = envVars['HOME']; + } else if (io.Platform.isWindows) { + home = envVars['UserProfile']; + } + if (home.endsWith('/')) { + home = home.substring(0, home.length - 1); + } + if (io.Platform.isWindows) { + return '$home\\NexusTools'; + } else { + return '$home/.nexustools'; + } +} + +// Function for installing Platform Tools package +Future installPlatformTools() async { + var dir = nexusToolsDir(); + // Get the proper ZIP file + var zip = ''; + if (io.Platform.isMacOS) { + zip = macZip; + } else if (io.Platform.isLinux) { + zip = linuxZip; + } else if (io.Platform.isWindows) { + zip = windowsZip; + } + // Download file + print('[....] Downloading Platform Tools package, please wait.'); + var net = Uri.parse(zip); + try { + var data = await http.readBytes(net); + //await zipFile.writeAsBytes(data); + var archive = ZipDecoder().decodeBytes(data); + extractArchiveToDisk(archive, dir); + } catch (e) { + var error = e.toString(); + print('[EROR] There was an error downloading Platform Tools: $error'); + io.exit(1); + } + // Move files out of platform-tools subdirectory and delete the subdirectory + if (io.Platform.isWindows) { + await io.Process.run('move', ['$dir\\platform-tools\\*', '$dir'], + runInShell: true); + await io.Process.run('rmdir', ['/Q', '/S', '$dir\\platform-tools'], + runInShell: true); + } else { + await io.Process.run( + '/bin/sh', ['-c', 'mv -f -v $dir/platform-tools/* $dir/']); + await io.Process.run('/bin/sh', ['-c', 'rm -rf $dir/platform-tools']); + } + // Mark binaries in directory as executable + if (io.Platform.isLinux || io.Platform.isMacOS) { + await io.Process.run('/bin/sh', ['-c', 'chmod -f +x $dir/*']); + } + // Give a progress report + print('[ OK ] Platform Tools now installed in $dir.'); + // Add binaries to path + await sys.addPath(dir); + // Create help link + if (io.Platform.isWindows) { + var file = io.File('$dir\\About Nexus Tools.url'); + await file.writeAsString( + '[InternetShortcut]\nURL=https://github.com/corbindavenport/nexus-tools/blob/master/README.md', + mode: io.FileMode.writeOnly); + } else if (io.Platform.isMacOS) { + var file = io.File('$dir/About Nexus Tools.url'); + await file.writeAsString( + '[InternetShortcut]\nURL=https://github.com/corbindavenport/nexus-tools/blob/master/README.md', + mode: io.FileMode.writeOnly); + } else if (io.Platform.isLinux) { + var file = io.File('$dir/About Nexus Tools.desktop'); + await file.writeAsString( + '[Desktop Entry]\nEncoding=UTF-8\nIcon=text-html\nType=Link\nName=About Nexus Tools\nURL=https://github.com/corbindavenport/nexus-tools/blob/master/README.md', + mode: io.FileMode.writeOnly); + } + // Install drivers on Windows + 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); + } + } + } +} + +// Function for removing Platform Tools package +Future removePlatformTools() async { + // Nexus Tools 3.2+ (August 2016-Present) installs binaries in ~/.nexustools + var dir = nexusToolsDir(); + var installExists = false; + installExists = await io.Directory(dir).exists(); + if (installExists) { + print( + '[WARN] Deleting $dir will delete Android System Tools (ADB, Fastboot, etc.).'); + print('[WARN] This will also delete the Nexus Tools application.'); + io.stdout.write('[WARN] Continue with removal? [Y/N] '); + var input = io.stdin.readLineSync(); + if (input?.toLowerCase() != 'y') { + return; + } + // Proceed with deletion + await io.Directory(dir).delete(recursive: true); + print('[ OK ] Deleted directory at $dir.'); + print('[INFO] Nexus Tools can be re-installed at https://git.io/JBuTh.'); + } else { + print('[EROR] No installation found at $dir.'); + } +} + +// Function for installing Windows Universal ADB drivers +// Drivers provided by ClockWorkMod: https://adb.clockworkmod.com/ +Future installWindowsDrivers(String dir) async { + print('[....] Downloading drivers, please wait.'); + var net = Uri.parse( + 'https://github.com/koush/adb.clockworkmod.com/releases/latest/download/UniversalAdbDriverSetup.msi'); + try { + var data = await http.readBytes(net); + var file = io.File('$dir\\ADB Drivers.msi'); + await file.writeAsBytes(data, mode: io.FileMode.writeOnly); + print('[....] Opening driver installer.'); + await io.Process.run( + 'start', ['/wait', 'msiexec.exe', '/i', '$dir\\ADB Drivers.msi'], + runInShell: true); + } catch (e) { + print( + '[EROR] There was an error downloading drivers, try downloading them from adb.clockworkmod.com.'); + } +} + +// Function for Plausible Analytics reporting +void connectAnalytics() async { + var uuid = Uuid(); + var id = uuid.v4(); + // Get exact operating system + var realOS = ''; + var isWSL = await io.Directory('/mnt/c/Windows').exists(); + var isChromeOS = await io.Directory('/usr/share/themes/CrosAdapta').exists(); + if (isWSL) { + realOS = 'wsl'; + } else if (isChromeOS) { + realOS = 'chromeos'; + } else { + realOS = io.Platform.operatingSystem; + } + var cpu = await sys.getCPUArchitecture(); + // Set data + var net = Uri.parse('https://plausible.io/api/event'); + var netHeaders = { + 'user-agent': 'Nexus Tools', + 'X-Forwarded-For': '127.0.0.1', + '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"}'; + // Send request + try { + await http.post(net, headers: netHeaders, body: netBody); + } catch (_) { + // Do nothing + } +} + +// Pre-installation steps +Future checkInstall() async { + // Check if directory already exists + var dir = nexusToolsDir(); + var installExists = false; + if (io.Platform.isWindows) { + installExists = await io.File('$dir\\adb.exe').exists(); + } else { + installExists = await io.File('$dir/adb').exists(); + } + if (installExists) { + io.stdout.write( + '[WARN] Platform tools already installed in $dir. Continue? [Y/N] '); + var input = io.stdin.readLineSync(); + if (input?.toLowerCase() != 'y') { + io.exit(0); + } + } else { + // Make the directory + await io.Directory(dir).create(recursive: true); + print('[ OK ] Created folder at $dir.'); + } + // Check if ADB is already installed + sys.checkIfInstalled(dir, 'adb', 'ADB'); + // Check if Fastboot is already installed + sys.checkIfInstalled(dir, 'fastboot', 'Fastboot'); + // Check CPU architecture + var cpu = await sys.getCPUArchitecture(); + if (supportedCPUs.contains(cpu)) { + print('[ OK ] Your hardware platform is supported, yay!'); + } else if (io.Platform.isMacOS && (cpu == 'arm64')) { + print( + '[WARN] Google does not provide native Apple Silicon binaries yet, x86_64 binaries will be installed'); + } else { + print( + '[EROR] Your hardware platform is detected as $cpu, but Google only provides Platform Tools for x86-based platforms.'); + io.exit(1); + } + // Display environment-specific warnings + var isWSL = await io.Directory('/mnt/c/Windows').exists(); + var isChromeOS = await io.Directory('/usr/share/themes/CrosAdapta').exists(); + if (isWSL) { + print( + '[WARN] WSL does not support USB devices, you will only be able to use ADB over Wi-Fi.'); + } else if (isChromeOS) { + print('[WARN] Chrome OS 75 or higher is required for USB support.'); + } +} + +void printHelp() { + var helpDoc = ''' +Nexus Tools $appVersion +Downloader/management app for Android SDK Platform Tools + +Usage: nexustools [OPTIONS] + +Example: nexustools -i (this installs Platform Tools) + + -i, --install Install/update Android Platform Tools + -r, --remove Remove Platform Tools + -n, --no-analytics Run Nexus Tools without Plausible Analytics + (analytics is only run on install) + -c, --check Check for Nexus Tools update + -h, --help Display this help message + '''; + print(helpDoc); +} + +void main(List arguments) async { + if (arguments.contains('-i') || arguments.contains('--install')) { + print('[INFO] Nexus Tools $appVersion'); + // Check version unless Nexus Tools is running from web (curl) installer + // The web installer adds the -w parameter + if (!arguments.contains('-w')) { + await checkUpdate(); + } + // Start analytics unless opted out + if (arguments.contains('--no-analytics')) { + print('[ OK ] Plausible Analytics are disabled.'); + } else { + connectAnalytics(); + } + // Start installation + await checkInstall(); + await installPlatformTools(); + // Post-install + var appName = ''; + if (io.Platform.isWindows) { + appName = 'Command Line window (not a new tab!)'; + } else { + appName = 'Terminal window'; + } + print( + '[INFO] Installation complete! Open a new $appName to apply changes.'); + print('[INFO] Run "nexustools --help" at any time for more options.'); + print( + '[INFO] Join the Discord server: https://discord.com/invite/59wfy5cNHw'); + print('[INFO] Donate to support development: https://git.io/J4jct'); + } else if (arguments.contains('-r') || arguments.contains('--remove')) { + print('[INFO] Nexus Tools $appVersion'); + // Start removal + await removePlatformTools(); + } else if (arguments.contains('-h') || arguments.contains('--help')) { + printHelp(); + } else if (arguments.contains('-c') || arguments.contains('--check')) { + await checkUpdate(); + } else { + print('[EROR] Invalid arguments. Run nexustools -h for help!'); + } +} diff --git a/compile.ps1 b/compile.ps1 new file mode 100644 index 0000000..e4f8714 --- /dev/null +++ b/compile.ps1 @@ -0,0 +1,13 @@ +$FileName = "nexustools-windows-x64" + +# Make the new directory +$dirCheck = Test-Path dist +if ($dirCheck) { + # Do nothing +} else { + New-Item -Name "dist" -ItemType Directory +} + +dart compile exe "./bin/main.dart" -o "./dist/nexustools.exe" +Compress-Archive -Path "./dist/nexustools.exe" -DestinationPath "./dist/$FileName.zip" -Force +del "./dist/nexustools.exe" \ No newline at end of file diff --git a/compile.sh b/compile.sh new file mode 100755 index 0000000..8326464 --- /dev/null +++ b/compile.sh @@ -0,0 +1,25 @@ +# This script is for compiling the Dart executable +# The current path needs to be set to the root of the repository first +# You also need the Dart SDK and zip installed + +OS=$(uname) +ARCH=$(uname -m) +FILENAME="" + +if [ "$OS" = "Darwin" ]; then + # This will need to be updated when M1 support is added + FILENAME="nexustools-macos-x64" +elif [ "$OS" = "Linux" ] && [ "$ARCH" = "x86_64" ]; then + FILENAME="nexustools-linux-x64" +elif [ "$OS" = "Linux" ] && [ "$ARCH" = "amd64" ]; then + FILENAME="nexustools-linux-x64" +else + FILENAME="nexustools" +fi + +mkdir -p ./dist +dart compile exe "./bin/main.dart" -o "./dist/nexustools" +cd ./dist +zip "$FILENAME.zip" "nexustools" +rm "nexustools" +cd ../ \ No newline at end of file diff --git a/install.ps1 b/install.ps1 new file mode 100644 index 0000000..0648285 --- /dev/null +++ b/install.ps1 @@ -0,0 +1,21 @@ +# This script is just a wrapper to start the Dart executable from the GitHub releases page. + +$Dir = "$Home\NexusTools" +$Arch = $ENV:Processor_Architecture +$BaseUrl = "https://github.com/corbindavenport/nexus-tools" +$Download = "$BaseUrl/releases/latest/download/nexustools-windows-x64.zip" + +# Make the new directory +$dirCheck = Test-Path "$Dir" +if ($dirCheck) { + # Do nothing +} else { + # Create folder and hide output + New-Item "$Dir" -ItemType Directory -ea 0 | Out-Null +} + +# Start Dart executable +Invoke-WebRequest -Uri "$Download" -OutFile "$Dir\temp.zip" +Expand-Archive -LiteralPath "$Dir\temp.zip" -DestinationPath "$Dir" -Force +del "$Dir\temp.zip" +& "$Dir\nexustools.exe" -i -w diff --git a/install.sh b/install.sh old file mode 100644 new file mode 100755 index 08b28bc..2c151b4 100755 --- a/install.sh +++ b/install.sh @@ -1,173 +1,56 @@ -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - #!/bin/bash -ADB="/usr/bin/adb" -FASTBOOT="/usr/bin/fastboot" -UDEV="/etc/udev/rules.d/51-android.rules" +# This script is just a wrapper to start the Dart executable from the GitHub releases page. + +DIR="$HOME/.nexustools" OS=$(uname) -ARCH=$(arch) +ARCH=$(uname -m) +BASEURL="https://github.com/corbindavenport/nexus-tools" +DOWNLOAD='' +PARAMS="$@" -# get sudo +_run_executable() { + cd $DIR + curl -Lfs --progress-bar -o ./temp.zip $DOWNLOAD|| { echo "[EROR] Download failed."; exit; } + unzip -q -o ./temp.zip + rm ./temp.zip + chmod +x ./nexustools* + # Run Nexus Tools and pass parameters to the executable + ./nexustools* -i -w "$PARAMS" +} -echo "[INFO] Nexus Tools 2.3" -echo "[INFO] Please enter sudo password for install." -sudo echo "[ OK ] Sudo access granted." - -# check if already installed - -if [ -f $ADB ]; then - read -p "[WARN] ADB is already present, press ENTER to overwrite or exit to cancel." - sudo rm $ADB +# Check that required applications are installed +if ! [ -x "$(command -v curl)" ]; then + echo "[EROR] The 'curl' command is not installed. Please install it and run Nexus Tools again." + exit fi -if [ -f $FASTBOOT ]; then - read -p "[WARN] Fastboot is already present, press ENTER to overwrite or exit to cancel." - sudo rm $FASTBOOT +if ! [ -x "$(command -v unzip)" ]; then + echo "[EROR] The 'unzip' command is not installed. Please install it and run Nexus Tools again." + exit fi -# detect operating system and install +# Make the new directory +mkdir -p $DIR -if [ -x "/usr/bin/crossystem" ]; then # Chrome OS - sudo mount -o remount,rw / 2>/dev/null - if [ "$?" -ne "0" ]; then - if [ -x /usr/local/bin ]; then - ADB=/usr/local/bin/adb - FASTBOOT=/usr/local/bin/fastboot - UDEV= - fi - /usr/bin/crossystem 'mainfw_type?developer' - fi - if [ "$?" -ne "0" ]; then - - echo "[INFO] It appears your Chromium/Chrome OS device is not in developer mode." - echo "[INFO] Developer mode is needed to install ADB and Fastboot." - echo "[INFO] Make sure your device is booted in developer mode." - echo "[INFO] To set up developer tools, use this command: sudo dev_install" - echo " " - exit 1 - fi - case "$(arch)" in - i*86|amd64|x86_64) - echo "[INFO] Downloading ADB for Chrome OS [Intel CPU]..." - sudo curl -s -o $ADB "http://github.com/corbindavenport/nexus-tools/raw/master/bin/linux-i386-adb" -LOk - echo "[INFO] Downloading Fastboot for Chrome [Intel CPU]..." - sudo curl -s -o $FASTBOOT "http://github.com/corbindavenport/nexus-tools/raw/master/bin/linux-i386-fastboot" -LOk - ;; - arm|armv*) - echo "[WARN] The ADB binaries for ARM are out of date, and do not work on Android 4.2.2+" - echo "[INFO] Downloading ADB for Chrome OS [ARM CPU]..." - sudo curl -s -o $ADB "http://github.com/corbindavenport/nexus-tools/raw/master/bin/linux-arm-adb" -LOk - echo "[INFO] Downloading Fastboot for Chrome OS [ARM CPU]..." - sudo curl -s -o $FASTBOOT "http://github.com/corbindavenport/nexus-tools/raw/master/bin/linux-arm-fastboot" -LOk - ;; - *) - echo "[EROR] Your CPU platform could not be detected." - echo " " - exit 1 - esac - echo "[INFO] Downloading udev list..." - if [ -n "$UDEV" ]; then - if [ ! -d /etc/udev/ ]; then - sudo mkdir /etc/udev/ - fi - if [ ! -d /etc/udev/rules.d/ ]; then - sudo mkdir /etc/udev/rules.d/ - fi - sudo curl -s -o $UDEV "http://github.com/corbindavenport/nexus-tools/raw/master/udev.txt" -LOk - sudo chmod 644 $UDEV - sudo chown root. $UDEV 2>/dev/null - sudo service udev restart 2>/dev/null - sudo killall adb 2>/dev/null - fi - echo "[INFO] Making ADB and Fastboot executable..." - sudo chmod +x $ADB - sudo chmod +x $FASTBOOT - echo "[ OK ] Done!" - echo "[INFO] Type adb or fastboot to run." - echo " " - exit 0 -elif [ "$(uname)" == "Darwin" ]; then # Mac OS X - echo "[INFO] Downloading ADB for Mac OS X..." - sudo curl -s -o $ADB "http://github.com/corbindavenport/nexus-tools/raw/master/bin/mac-adb" -LOk - echo "[INFO] Downloading Fastboot for Mac OS X..." - sudo curl -s -o $FASTBOOT "http://github.com/corbindavenport/nexus-tools/raw/master/bin/mac-fastboot" -LOk - echo "[INFO] Making ADB and Fastboot executable..." - echo "[INFO] Downloading udev list..." - if [ -n "$UDEV" ]; then - if [ ! -d /etc/udev/ ]; then - sudo mkdir /etc/udev/ - fi - if [ ! -d /etc/udev/rules.d/ ]; then - sudo mkdir /etc/udev/rules.d/ - fi - sudo curl -s -o $UDEV "http://github.com/corbindavenport/nexus-tools/raw/master/udev.txt" -LOk - sudo chmod 644 $UDEV - sudo chown root. $UDEV 2>/dev/null - sudo service udev restart 2>/dev/null - sudo killall adb 2>/dev/null - fi - echo "[INFO] Making ADB and Fastboot executable..." - sudo chmod +x $ADB - sudo chmod +x $FASTBOOT - echo "[ OK ] Done!" - echo "[INFO] Type adb or fastboot to run." - echo " " - exit 0 -elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then # Generic Linux - if [ "$(arch)" == "i386" ] || [ "$(arch)" == "i486" ] || [ "$(arch)" == "i586" ] || [ "$(arch)" == "amd64" ] || [ "$(arch)" == "x86_64" ] || [ "$(arch)" == "i686" ]; then # Linux on Intel x86/x86_64 CPU - echo "[INFO] Downloading ADB for Linux [Intel CPU]..." - sudo curl -s -o $ADB "http://github.com/corbindavenport/nexus-tools/raw/master/bin/linux-i386-adb" -LOk - echo "[INFO] Downloading Fastboot for Linux [Intel CPU]..." - sudo curl -s -o $FASTBOOT "http://github.com/corbindavenport/nexus-tools/raw/master/bin/linux-i386-fastboot" -LOk - elif [ "$(arch)" == "arm" ] || [ "$(arch)" == "armv6l" ]; then # Linux on ARM CPU - echo "[WARN] The ADB binaries for ARM are out of date, and do not work on Android 4.2.2+" - echo "[INFO] Downloading ADB for Linux [ARM CPU]..." - sudo curl -s -o $ADB "http://github.com/corbindavenport/nexus-tools/raw/master/bin/linux-arm-adb" -LOk - echo "[INFO] Downloading Fastboot for Linux [ARM CPU]..." - sudo curl -s -o $FASTBOOT "http://github.com/corbindavenport/nexus-tools/raw/master/bin/linux-arm-fastboot" -LOk - else - echo "[EROR] Your CPU platform could not be detected." - echo " " - exit 1 - fi - echo "[INFO] Downloading udev list..." - if [ -n "$UDEV" ]; then - if [ ! -d /etc/udev/ ]; then - sudo mkdir /etc/udev/ - fi - if [ ! -d /etc/udev/rules.d/ ]; then - sudo mkdir /etc/udev/rules.d/ - fi - sudo curl -s -o $UDEV "http://github.com/corbindavenport/nexus-tools/raw/master/udev.txt" -LOk - sudo chmod 644 $UDEV - sudo chown root. $UDEV 2>/dev/null - sudo service udev restart 2>/dev/null - sudo killall adb 2>/dev/null - fi - echo "[INFO] Making ADB and Fastboot executable..." - sudo chmod +x $ADB - sudo chmod +x $FASTBOOT - echo "[ OK ] Done!" - echo "[INFO] Type adb or fastboot to run." - echo " " - exit 0 +# Start Dart executable +if [ "$OS" = "Darwin" ]; then # macOS + # Install Rosetta x86 emulation layer if needed + if [ "$ARCH" = "arm64" ]; then + echo "[WARN] Apple Rosetta compatibility layer will be enabled, if it has not been already. Press ENTER to install or X to cancel." + read -sn1 input + [ "$input" = "" ] && /usr/sbin/softwareupdate --install-rosetta --agree-to-license || exit + fi + DOWNLOAD="$BASEURL/releases/latest/download/nexustools-macos-x64.zip" + _run_executable +elif [ "$OS" = "Linux" ] && [ "$ARCH" = "x86_64" ]; then # Generic Linux + DOWNLOAD="$BASEURL/releases/latest/download/nexustools-linux-x64.zip" + _run_executable +elif [ "$OS" = "Linux" ] && [ "$ARCH" = "amd64" ]; then # Generic Linux + DOWNLOAD="$BASEURL/releases/latest/download/nexustools-linux-x64.zip" + _run_executable else - echo "[EROR] Your operating system or architecture could not be detected." - echo "[EROR] Report bugs at: github.com/corbindavenport/nexus-tools/issues" - echo "[EROR] Report the following information in the bug report:" - echo "[EROR] OS: $OS" - echo "[EROR] ARCH: $ARCH" - echo " " - exit 1 + echo "[EROR] Your OS or CPU architecture doesn't seem to be supported." + echo "[EROR] Detected OS: $OS" + echo "[EROR] Detected arch: $ARCH" + exit fi diff --git a/lib/sys.dart b/lib/sys.dart new file mode 100644 index 0000000..a68b1b8 --- /dev/null +++ b/lib/sys.dart @@ -0,0 +1,79 @@ +import 'dart:io' as io; + +Map envVars = io.Platform.environment; + +// Function for checking if an executable is already installed +void checkIfInstalled(String dir, String command, String commandName) async { + var info = ''; + if (io.Platform.isWindows) { + var cmd = await io.Process.run('where', [command]); + info = cmd.stdout.toString(); + } else { + var cmd = await io.Process.run('which', [command]); + info = cmd.stdout.toString(); + } + if (info.contains(dir)) { + // Executable is installed in the Nexus Tools directory + return; + } else if (info.isEmpty) { + // Executable isn't installed at all + } else { + // Executable is installed but not inside the Nexus Tools directory + var location = info.replaceAll('\n', ''); + print('[EROR] $commandName is already installed at $location. Please uninstall $commandName and try again.'); + io.exit(1); + } +} + +// Function get current CPU architecture +Future getCPUArchitecture() async { + if (io.Platform.isWindows) { + 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'; + } + } + return cpu; + } else { + var info = await io.Process.run('uname', ['-m']); + var cpu = info.stdout.toString().replaceAll('\n', ''); + return cpu; + } +} + +// Function for adding a directory to the system/shell $PATH +Future addPath(String path) async { + if (envVars['PATH'].toString().contains(path)) { + // Directory is already in $PATH + print('[ OK ] $path is already in PATH.'); + } else { + // Directory needs to be added to $PATH + if (io.Platform.isWindows) { + var newPath = envVars['PATH'].toString() + ';$path'; + await io.Process.run('setx', ['path', '$newPath'], runInShell: true); + print('[ OK ] Added $path to user %PATH.'); + } else if (envVars['SHELL'].toString().contains('zsh')) { + // Z Shell + var file = io.File(envVars['HOME'] + '/.zshrc'); + await file.writeAsString('\nexport PATH=\$PATH:$path', mode: io.FileMode.append); + print('[ OK ] Z Shell detected, added $path to ' + file.path); + } else if (envVars['SHELL'].toString().contains('bash')) { + // Bash + var file = io.File(envVars['HOME'] + '/.bash_profile'); + await file.writeAsString('\nexport PATH=\$PATH:$path', mode: io.FileMode.append); + print('[ OK ] Bash Shell detected, added $path to ' + file.path); + } else { + print('[WARN] Shell could not be detected, you will need to manually add $path to your PATH.'); + } + } +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..2e75660 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,131 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: "direct dev" + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.2" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.1" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + console: + dependency: "direct dev" + description: + name: console + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + http: + dependency: "direct dev" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.3" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + io: + dependency: "direct dev" + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + pedantic: + dependency: "direct dev" + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.11.1" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + uuid: + dependency: "direct dev" + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.4" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" +sdks: + dart: ">=2.12.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..24d3200 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,18 @@ +name: nexustools +description: Installer for ADB, Fastboot, and other Android tools. +version: 5.0.0 +homepage: https://github.com/corbindavenport/nexus-tools/ + +environment: + sdk: '>=2.12.0 <3.0.0' + +# dependencies: +# path: ^1.8.0 + +dev_dependencies: + pedantic: ^1.10.0 + http: + io: + uuid: + archive: ^3.1.2 + console: \ No newline at end of file diff --git a/udev.txt b/udev.txt deleted file mode 100644 index 08d6b9a..0000000 --- a/udev.txt +++ /dev/null @@ -1,31 +0,0 @@ -SUBSYSTEM=="usb", ATTRS{idVendor}=="0bb4", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0e79", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0502", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0b05", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="413c", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0489", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="091e", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="18d1", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0bb4", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="12d1", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="24e3", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="2116", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0482", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="17ef", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="1004", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="22b8", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0409", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="2080", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0955", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="2257", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="10a9", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="1d4d", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0471", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="04da", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="05c6", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="1f53", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="04e8", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="04dd", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0fce", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="0930", MODE="0666" -SUBSYSTEM=="usb", ATTRS{idVendor}=="19d2", MODE="0666" \ No newline at end of file diff --git a/uninstall.sh b/uninstall.sh index 49bbe26..12efb07 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,69 +1,15 @@ -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - #!/bin/bash -ADB="/usr/bin/adb" -FASTBOOT="/usr/bin/fastboot" -UDEV="/etc/udev/rules.d/51-android.rules" +# This script only exists to maintain compatibility with guides and tutorials that mention Nexus Tools. Nexus Tools can be uninstalled by running nexustools -r in the Terminal, or by deleting ~/.nexustools manually. -# get sudo +OS=$(uname) +ARCH=$(uname -m) -echo "[INFO] Nexus Tools 2.3" -echo "[INFO] Please enter sudo password for uninstall." -sudo echo "[ OK ] Sudo access granted." - -# check for chrome os - -if [ -x "/usr/bin/crossystem" ]; then # Chrome OS - sudo mount -o remount,rw / 2>/dev/null - if [ "$?" -ne "0" ]; then - if [ -x /usr/local/bin ]; then - ADB=/usr/local/bin/adb - FASTBOOT=/usr/local/bin/fastboot - UDEV= - fi - /usr/bin/crossystem 'mainfw_type?developer' - fi - if [ "$?" -ne "0" ]; then - echo "[INFO] It appears your Chromium/Chrome OS device is not in developer mode." - echo "[INFO] Developer mode is needed to install ADB and Fastboot." - echo "[INFO] Make sure your device is booted in developer mode." - echo "[INFO] To set up developer tools, use this command: sudo dev_install" - echo " " - exit 1 - fi -fi - -# remove files - -if [ -f $ADB ]; then - sudo rm $ADB - echo "[ OK ] ADB removed." +# Nexus Tools 3.2+ (August 2016-Now) installs binaries in ~/.nexustools +if [ -d $HOME/.nexustools ]; then + echo "[WARN] Nexus Tools folder found in $HOME/.nexustools. Press ENTER to delete or X to skip." + read -sn1 input + [ "$input" = "" ] && rm -rf $HOME/.nexustools else - echo "[EROR] ADB not found in /usr/bin, skipping uninstall." -fi -if [ -f $FASTBOOT ]; then - sudo rm $FASTBOOT - echo "[ OK ] Fastboot removed." -else - echo "[EROR] Fastboot not found in /usr/bin, skipping uninstall." -fi -if [ -f $UDEV ]; then - sudo rm $UDEV - echo "[ OK ] Udev list removed." -else - echo "[EROR] Udev list not found in /etc/udev/rules.d/, skipping uninstall." -fi -echo "[ OK ] Done uninstalling." -echo " " + echo "[ OK ] No installation found." +fi \ No newline at end of file