Repository: IGPenguin/mobile-toolkit
Branch: master
Commit: 491c778f676e
Files: 56
Total size: 94.1 KB
Directory structure:
gitextract_fh0eifjr/
├── .github/
│ ├── CONTRIBUTING.md
│ ├── ISSUE_TEMPLATE.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── count_lines.yml
│ └── shellcheck.yml
├── .gitignore
├── LICENCE.md
├── README.md
├── android/
│ ├── aanimationspeed
│ ├── aappinfo
│ ├── abounds
│ ├── abuildproject
│ ├── acamera
│ ├── acheckdevice
│ ├── acontrol
│ ├── adarkmode
│ ├── aemulator
│ ├── aerase
│ ├── afontscale
│ ├── agoogleplay
│ ├── ainstall
│ ├── akill
│ ├── alaunch
│ ├── alog
│ ├── aoptions
│ ├── apaste
│ ├── apermissionreset
│ ├── apowerbutton
│ ├── areboot
│ ├── arecord
│ ├── ascreenshot
│ ├── aservices
│ ├── atalkback
│ ├── atestmonkey
│ ├── atestmonkeykill
│ ├── auninstall
│ ├── aurl
│ ├── awipe
│ └── awireless
├── changelog.txt
├── common_tools
├── data/
│ └── .gitignore
└── ios/
├── icheckdevice
├── iconsole
├── iinstall
├── ikill
├── ilang
├── ilaunch
├── ilog
├── ioptions
├── iquicktime
├── ireboot
├── irecord
├── iscreenshot
├── isimulator
└── iuninstall
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/CONTRIBUTING.md
================================================
## 💬 Contributing
If you consider contributing to this repository, please first discuss the desired changes via issue, email, or any other method
### 🕵️ Pull request requirements
1. Implement all functions thoroughly and remove any unused or non-working code
2. Format all terminal output in a similar way as the existing
3. Ensure every code change and usage variant is tested
4. Update the README.md and changelog.txt with details of changes to the commands
### ✏️ Right to make changes
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
### 🐞 Whats wrong
~Describe requested functionality or existing bug~
### 🌈 Desired state
~Describe desired code and functional changes~
### 📏 Challenges
~Hint any special or complicated tasks~
### 📂 Sources
~Recommend related code samples or documentation~
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## ⚠️ Progress checklist
- [ ] 🏗 **Features fully completed**
- [ ] 🔬 **Shellcheck issues resolved**
- [ ] 🔨 **All changes tested**
- [ ] 💬 **Terminal output satisfactory**
- [ ] 👀 **Diff examined thoroughly**
- [ ] 📝 **API changes included in `README.md`**
- [ ] 📣 **Major changes listed in `changelog.txt`**
================================================
FILE: .github/workflows/count_lines.yml
================================================
name: Count lines
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Count lines of text in this repository
run: git ls-files *[^.png] | xargs wc -l | grep total | awk '{print $1}' > count.txt
- uses: pCYSl5EDgo/cat@master
id: count
with:
path: count.txt
- run: echo $TEXT
env:
TEXT: ${{ steps.count.outputs.text }}
================================================
FILE: .github/workflows/shellcheck.yml
================================================
name: 'Shellcheck'
on: push
jobs:
shellcheck:
name: Shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Shellcheck
uses: ludeeus/action-shellcheck@master
env:
SHELLCHECK_OPTS: -e SC1090 -e SC2207 -e SC2001 -e SC1091
# SC1090 - non-constant source
# SC2207 - no arrays like this ($())
# SC2001 - replace sed with ${variable//search/replace}
# SC1091 - common_tools was not specified as input (see shellcheck -x)
================================================
FILE: .gitignore
================================================
*DS_Store
ios/go-ios
ios/nohup.out
ios/selfidentity.plist
================================================
FILE: LICENCE.md
================================================
MIT License
Copyright (c) 2019 IntergalacticPenguin - Adam Svoboda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
urnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================

<div id='section-id-2'/>
## What is its purpose?
🛠 **Control Android & iOS devices:** Capture screen, manage apps, simulate input, examine system logs etc.<br>
⚡️ **Speed++** Are you an app developer or a tester? Boost your effectivity, discover new tools!
<div id='section-id-8'/>
## All features
📲 **Control Android and iOS devices** or Emulators/Simulators using terminal commands<br>
🛠 **Take screeshots, change device settings**, gather app & device information<br>
⚙️ **Manage mobile applications** - install, restart, wipe data and much more<br>
📋 **Handle multiple devices effortlessly** - select from list or target all connected devices<br>
⏳ **Save your precious time** - stop doing repetitive tasks manually<br>
🔄 **Automatic update** - get new features and fixes ASAP<br>
## Table of contents
🔩 Maybe you just want to skip to [Installation](#section-id-22)?<br>
<br>
<bold>[🤖 Android Commands](#section-id-52)</bold>
- [Capture screen](#section-id-54)
- [📸 ascreenshot](#section-id-56)
- [🎥 arecord](#section-id-60)
- [Control device](#section-id-66)
- [✏️ apaste](#section-id-68)
- [🌐 aurl](#section-id-78)
- [🏴 adarkmode](#section-id-82)
- [🔊 atalkback](#section-id-85)
- [📐 abounds](#section-id-88)
- [🚗 aanimationspeed](#section-id-92)
- [🔠 afontscale](#section-id-96)
- [🎹 acontrol](#section-id-100)
- [📷 acamera](#section-id-104)
- [⚡️ awireless](#section-id-107)
- [👋 apowerbutton](#section-id-108)
- [Manage packages](#section-id-111)
- [🚀 alaunch](#section-id-113)
- [🕵️ aappinfo](#section-id-118)
- [🔪 akill](#section-id-128)
- [🧽 aerase](#section-id-132)
- [🚚 ainstall](#section-id-136)
- [🗑 auninstall](#section-id-140)
- [🔥 awipe](#section-id-146)
- [🐁 apermissionreset](#section-id-149)
- [🛍 agoogleplay](#section-id-153)
- [🏭 abuildproject](#section-id-157)
- [Manage device](#section-id-161)
- [⚙️ aoptions](#section-id-163)
- [📜 alog](#section-id-176)
- [📋 acheckdevice](#section-id-180)
- [😎 aservices](#section-id-192)
- [♻ areboot](#section-id-196)
- [📱 aemulator](#section-id-199)
- [🐒 atestmonkey](#section-id-215)
<strong>[🍎 iOS Commands](#section-id-233)</strong><br>
- [Capture screen](#section-id-235)
- [📸 iscreenshot](#section-id-237)
- [🎥 irecord](#section-id-241)
- [📹 iquicktime](#section-id-250)
- [Manage applications](#section-id-255)
- [🚚 iinstall](#section-id-256)
- [🗑 iuninstall](#section-id-260)
- [🚀 ilaunch](#section-id-266)
- [🔪 ikill](#section-id-271)
- [Manage device](#section-id-276)
- [⚙️ ioptions](#section-id-278)
- [💬 ilang](#section-id-281)
- [📜 ilog](#section-id-285)
- [📋 icheckdevice](#section-id-288)
- [♻ ireboot](#section-id-292)
- [📱 isimulator](#section-id-295)
- [🖥 iconsole](#section-id-309)
💭 Do you want to share [Feedback or Contribute](#section-id-312)?
<div id='section-id-22'/>
# 💻 Installation
<details>
<summary>Click here to reveal step by step guide ↓</summary>
_Note: This tool targets macOS for compatibility, but most interactions should work on any Unix system._
<br>
1. **Open terminal**
2. **Clone this repository** `git clone https://github.com/IntergalacticPenguin/mobile-toolkit.git`
3. **Setup Android tools**
* **[Download](https://developer.android.com/studio/ "Android Studio") and install Android Studio** and **Android command line tools** (using Android Studio SDK manager)
* **Edit .zshrc** (or .bash_profile if you have bash shell) `open -e ~/.zshrc`
* **Insert this line at the end** `PATH=$PATH:/Users/dummyuser/Library/Android/sdk/platform-tools export PATH`
* **Don't forget to replace "dummyuser" with your account username**
* **Use full path to the "platform-tools" directory**
* **[Allow USB debugging](https://developer.android.com/studio/debug/dev-options) on your device, connect it and authorize your computer** (click OK on the device screen)
4. **Setup iOS tools**
* **Install latest Xcode and iOS command line tools** using [App Store](https://apps.apple.com/cz/app/xcode/id497799835?mt=12)
* **Install [Homebrew](https://brew.sh/ "Homberew") package manager**
* **Run Xcode, connect iOS device to USB and authorize your computer** (click "Trust" on the device screen)
* **Run any script i.e. `iscreenshot`, installation of all required tools will be initiated automatically** ([jq](https://stedolan.github.io/jq/) and [go-ios](https://github.com/danielpaulus/go-ios "go-ios"))
5. **Add Mobile Toolkit to $PATH**, it is mandatory for iOS scripts and it will let you run scripts in any directory
* **Edit .zshrc** (or .bash_profile if you have bash shell) `open -e ~/.zshrc`
* **Insert the following lines at the end** <br> `PATH=$PATH:/Users/dummyuser/mobile-toolkit/android` <br>
`PATH=$PATH:/Users/dummyuser/mobile-toolkit/ios`
* **Don't forget to replace "dummyuser" with your account username**
* **Use full path to the "mobile-toolkit" directory** (where you cloned this repository)
* **Add** `export PATH` **to the end of the file**
</details>
<div id='section-id-52'/>
# 🤖 Android Commands
<div id='section-id-54'/>
## Capture screen
<div id='section-id-56'/>
### 📸 ascreenshot
* `ascreenshot` Save screenshot to ~/Desktop
* `ascreenshot -a` Take screenshot on all connected devices
<div id='section-id-60'/>
### 🎥 arecord
1. `arecord` Record screen
2. End recording using `ctrl + c`
3. Save screen video footage to ~/Desktop
4. Records audio by default on devices running Android 12 and up (when using Scrcpy version 2.0.0 or higher)
* `arecord <custom-name>` Specify your own filename by passing it as argument
* `arecord -l` Use legacy `-l` option to record using ADB instead of Scrcpy
<div id='section-id-66'/>
## Control device
<div id='section-id-68'/>
### ✏️ apaste
`apaste "john.doe@fakemail.com" password1 "5005 1002 3332 1112" "2/19" 5004`
* `apaste <text>` Insert text into currently focused field
* `apaste "john.doe@fakemail.com" password1 ` Every additional argument will be inserted into subsequent field
* `apaste "This is sample multi-word text."` use "" to insert multi-word text into one field
* `apaste -l` Insert "Lorem Ipsum paragraph"
* `apaste -a <input-text>` Insert any text input (options displayed above) on all connected devices
* `apaste -a -l` Insert "Lorem Ipsum paragraph" on all connected devices
<div id='section-id-78'/>
### 🌐 aurl
* `aurl "google.com"` Open link in web browser or corresponding application
* `aurl -a "google.com"` Open link in web browser or corresponding application on all connected devices
<div id='section-id-82'/>
### 🏴 adarkmode
* `adarkmode` Toggle system dark mode
<div id='section-id-85'/>
### 🔊 atalkback
* `atalkback` Toggle TalkBack screen reader accessiblity option
<div id='section-id-88'/>
### 📐 abounds
* `abounds` Toggle UI layout bounds
* App restart may be necessary on lower APIs
<div id='section-id-92'/>
### 🚗 aanimationspeed
* `aanimationspeed` set slower animation speed or restore default
* `aanimationspeed <speed>` set animation speed multiplier
<div id='section-id-96'/>
### 🔠 afontscale
* `afontscale` set large font scale (1.3x bigger than default) or restore default
* `afontscale <scale>` set font scale multiplier
<div id='section-id-100'/>
### 🎹 acontrol
* `acontrol` start [scrcpy](https://github.com/Genymobile/scrcpy "scrcpy") session
* Provides realtime device screen mirroring and keyboard+mouse control
<div id='section-id-104'/>
### 📷 acamera
* Start the default camera application
<div id='section-id-107'/>
### ⚡️ awireless
* Enable or disable wireless ADB connection
* Use ADB and toolkit without having USB cable attached
<div id='section-id-108'/>
### 👋 apowerbutton
* Lock/Unlock the device (send Power button key event)
* Useful to unlock the device after the screen is locked automatically
<div id='section-id-111'/>
## Manage packages
<div id='section-id-113'/>
### 🚀 alaunch
* `alaunch` List third-party apps and choose one to run it
* `alaunch -s` List all available apps (including os pre-installed) and choose one to run it
* `alaunch com.dummy.package.name.app` Run app by package name
<div id='section-id-118'/>
### 🕵️ aappinfo
* `aappinfo` List foreground app information
* Package name
* Version
* Last update
* minSdk and targetSdk
* Permissions
* (Optional) Open application settings
* `aappinfo com.dummy.package.name.app` Target specific app by passing package name as argument
<div id='section-id-128'/>
### 🔪 akill
* `akill` Restart the foreground app
* `akill com.dummy.package.name.app` Target specific app by passing package name as argument
<div id='section-id-132'/>
### 🧽 aerase
* `aerase` Delete all local data of the foreground app and restart it
* `aerase com.dummy.package.name.app` Target specific app by passing package name as argument
<div id='section-id-136'/>
### 🚚 ainstall
* `ainstall some-app-file.apk` Install and run .apk
* `ainstall -a some-app-file.apk` Install and run .apk on all connected devices
<div id='section-id-140'/>
### 🗑 auninstall
* `auninstall` Uninstall third-party app, choose from the list
* `auninstall com.dummy.package.name.app` pass package name as argument
* `auninstall -w` Uninstall all-third party packages
* Skips some essential apps, edit IGNORED_PACKAGES in this script to customize the list to your needs
<div id='section-id-146'/>
### 🔥 awipe
* Wipe internal storage and delete all third-party apps
<div id='section-id-149'/>
### 🐁 apermissionreset
* Revoke ALL GRANTED runtime permissions for ALL apps
* You'll have to handle permission requests upon opening almost any app
<div id='section-id-153'/>
### 🛍 agoogleplay
* `agoogleplay "Dummy App"` Search for "Dummy App" on Google Play
* `agoogleplay` Search for currently foreground app on Google Play
<div id='section-id-157'/>
### 🏭 abuildproject
* `abuildproject` Build, install and run Android project located in current directory
* `abuildproject <relative-path>` Build, install and run Android project located in \<relative-path>
<div id='section-id-161'/>
## Manage device
<div id='section-id-163'/>
### ⚙️ aoptions
* `aoptions` Open system settings on a specific activity
* You can choose from quick presets
* Developer settings
* Locale settings
* Date & time
* Wifi settings
* Storage management
* Power usage
* Root settings activity
* `aoptions A` Choose from exhaustive list of all available options
* `aoptions 1,2,3... | dev | locale | date | wifi | storage | power` Use a preset, choose one
<div id='section-id-176'/>
### 📜 alog
* `alog` Print system log output
* `alog -f <package-name>` Filter log by package name
<div id='section-id-180'/>
### 📋 acheckdevice
* Print genereal device information
* Perform basic safety-checks and toggle "testing firendly" settings
* 10 minutes screen timeout
* Highest brightness
* Automatic date
* Disabled notification sounds
* Internet connectivity and WIFI name
* Font scale
* enUS locale
* (Optional) Search for the device on [GSMArena](https://www.gsmarena.com/ "GSMArena")
<div id='section-id-192'/>
### 😎 aservices
* Print running background services
* Search for more information via Google
<div id='section-id-196'/>
### ♻ areboot
* Reboot the device
<div id='section-id-199'/>
### 📱 aemulator
**Required**: Make terminal use Android Studio Java
* **Edit .bash_profile** (or .zshrc if you have zsh shell) `open -e ~/.bash_profile` or `open -e ~/.zshrc`
* **Add the following line at the end of the file** `export JAVA_HOME='/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home'`
* Android emulator supports all listed scripts by default + extra actions listed below
* `aemulator <option>` Handle various Android emulator activites
* `start` - choose and launch installed emulator
* `gprs | edge | 3g` - simulate network latency, choose one
* `call <number>` - receive fake call
* `sms <number> <text>` - receive fake sms
* `gps <lat> <long>` - set manual GPS location
* `battery <0-100>` - set battery level
* `telnet <command>` - call command via telnet
* example commands `event | redir | sensor | physics | finger | rotate | fold | unfold...` see [Android emulator documentation](https://developer.android.com/studio/run/emulator-console#console-session) for more information
<div id='section-id-215'/>
### 🐒 atestmonkey
* `atestmonkey` Default test with random seed and 15000 input events
* `atestmonkey <event-count>` Test with random seed and custom input event count
* `atestmonkey <event-count> <seed>` Test with custom seed and custom event count
* Perform automated stress test using [Application Excersciser Monkey](https://developer.android.com/studio/test/monkey)
* You can end test prematurely using ctrl^c or `atestmonkeykill` in case something goes wrong
* App under test needs to be pinned to fullscreen mode to prevent unwanted interactions elsewhere
* Screen pinning button location is directly tied to OS version and device manufacturer skin.
* It may be tricky to turn on, see examples below:<br><br>
* <details>
<summary>Google Nexus 5 (Android 6)</summary>
<br><em>You need to bring the app window to foreground, the button is located in bottom right corner.</em><br><br>
<img src="/media/Pinning_Nexus_v4.png" width="420"></details>
* <details>
<summary>Google Pixel 3 (Android 11)</summary>
<br><em>You need to click on the app icon, the button is located in popup menu.</em><br><br>
<img src="/media/Pinning_Pixel_v2.png" width="420"></details>
<div id='section-id-233'/>
# 🍎 iOS Commands
<div id='section-id-235'/>
## Capture screen
<div id='section-id-237'/>
### 📸 iscreenshot
* `iscreenshot` Save screenshot to ~/Desktop
* `iscreenshot -a` Take screenshot on all connected devices
<div id='section-id-241'/>
### 🎥 irecord
**Required**: Install [videosnap](https://github.com/matthutchinson/videosnap/releases "videosnap") -> download and install `videosnap-0.0.8.pkg`<br>
**Required**: Install [ffmpeg](https://www.ffmpeg.org/ "ffmpeg") `brew install ffmpeg`
1. `irecord` Record screen
2. End recording using `ctrl + c`
3. Video footage is saved to ~/Desktop
4. File is compressed using ffmpeg
<div id='section-id-250'/>
### 📹 iquicktime
* Run QuickTime and open video source picker (so you can choose a device right away)
* You may have to allow security system permission, so the script can access QuickTime application
* This is a fallback script for `irecord` on M1 macs as it is currently not working
<div id='section-id-255'/>
## Manage applications
<div id='section-id-256'/>
### 🚚 iinstall
* `iinstall some-app-file.ipa` Install .ipa (make sure to use properly signed build)
* `iinstall -a some-app-file.ipa` Install .ipa to all connected devices
<div id='section-id-260'/>
### 🗑 iuninstall
* `iuninstall` Uninstall third-party app, choose from the list
* `iuninstall com.dummy.package.name.app` pass bundle name as argument
* `iuninstall -w` Uninstall all third-party packages
* Skips some essential apps, edit IGNORED_PACKAGES in this script to customize the list to your needs
<div id='section-id-266'/>
### 🚀 ilaunch
* `ilaunch` List third-party apps and choose one to run it
* `ilaunch -s` List os pre-installed apps and choose one to run it
* `ilaunch com.dummy.bundle.id.app` Run app by bundle id
<div id='section-id-271'/>
### 🔪 ikill
* `ikill` List third-party apps and choose one to restart
* `ikill -s` List os pre-installed apps and choose one to restart
* `ikill com.dummy.bundle.id.app` Target specific app by passing bundle id as argument
<div id='section-id-276'/>
## Manage device
<div id='section-id-278'/>
### ⚙️ ioptions
* `ioptions` Open system settings application
<div id='section-id-281'/>
### 💬 ilang
* `ilang <lang>` Change the device language to different one, according to ISO-639 (i.e. "cs")
* `ilang` Change the device language to different one, choose from a list of all supported
<div id='section-id-285'/>
### 📜 ilog
* `ilog` Print system log output
<div id='section-id-288'/>
### 📋 icheckdevice
* Print device information
* (Optional) Search for the device on [GSMArena](https://www.gsmarena.com/ "GSMArena")
<div id='section-id-292'/>
### ♻ ireboot
* Reboot the device
<div id='section-id-295'/>
### 📱 isimulator
* Simulator has limited functionality (no camera, biometrics, Appstore...), but **offers some extra options, unavailable on physical iOS devices**
* `isimulator <option>` Handle various simulator related activites
* `start` - choose and launch installed simulator
* `screenshot` - save screenshot to ~/Desktop
* `record` - save screen recording to ~/Desktop (full resolution and frame rate, without QuickTime hassle)
* `paste <text>` - insert text into pasteboard
* `import <file>` - import image or video to simulator gallery app
* `log` - print simulator log
* `url <url>` - open link in web browser or corresponding application
* `wipe` - wipe all simulator data
* `battery <0-100>` - set battery level displayed in status bar (no functional impact)
* `time <hh:mm>` - set time displayed in status bar (no functional impact)
<div id='section-id-309'/>
### 🖥 iconsole
* `iconsole` Examine iOS or macOS system logs using Console application
<div id='section-id-312'/>
----
<strong>Feedback & Contribution</strong><br>
<sup>⁉️ [Submit an issue](https://github.com/IntergalacticPenguin/mobile-toolkit/issues/new/choose) to report any bugs, request a feature or ask questions.</sup><br>
<sup>🤝 [Pull requests](https://github.com/IntergalacticPenguin/mobile-toolkit/blob/master/.github/CONTRIBUTING.md "contribution rules") are highly **appreciated**, see the [issue board](https://github.com/IntergalacticPenguin/mobile-toolkit/projects/3).</sup><br>
<sup>💬 Also <strong>visit my [NoMo](https://github.com/IGPenguin/nomo)</strong> project and leave a star.</sup><br>
<sup>🔗 Find me on [LinkedIn](https://www.linkedin.com/in/intergalacticpenguin/) or [Twitter](https://twitter.com/IGPenguin).</sup><br>
================================================
FILE: android/aanimationspeed
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
set_animation_speed(){
adb -s "$SELECTED_DEVICE" shell settings put global animator_duration_scale "$1"
adb -s "$SELECTED_DEVICE" shell settings put global transition_animation_scale "$1"
adb -s "$SELECTED_DEVICE" shell settings put global window_animation_scale "$1"
}
restore_animation_speed(){
set_animation_speed 1
echo "🔄 Animation speed restored to default \"1\""
}
android_choose_device
if [ -n "$1" ] 2> /dev/null ;then
echo "🎬 Setting animation speed to \"$1\" (bigger is slower)..."
set_animation_speed "$1"
else
if [ "$(adb -s "$SELECTED_DEVICE" shell settings get global animator_duration_scale)" != "1" ] || [ "$(adb -s "$SELECTED_DEVICE" shell settings get global transition_animation_scale)" != "1" ] || [ "$(adb -s "$SELECTED_DEVICE" shell settings get global window_animation_scale)" != "1" ] ; then
restore_animation_speed
else
echo "🎬 Setting animation speed to \"5\" (bigger is slower)..."
set_animation_speed 5
fi
fi
================================================
FILE: android/aappinfo
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
if [ -n "$1" ];
then
PACKAGE_NAME=$1
android_is_package_installed "$PACKAGE_NAME"
else
PACKAGE_NAME=$(android_get_foreground_package)
fi
VERSION=$(adb -s "$SELECTED_DEVICE" shell dumpsys package "$PACKAGE_NAME" | grep versionName | sed 's/versionName=//')
VERSION=$(echo "$VERSION" | awk '{print $1}') # Remove ghost whitespaces
LAST_UPDATE=$(adb -s "$SELECTED_DEVICE" shell dumpsys package "$PACKAGE_NAME" | grep lastUpdateTime | sed 's/lastUpdateTime=//')
LAST_UPDATE=$(echo "$LAST_UPDATE" | awk '{print $1}') # Remove ghost whitespaces
SDK=$(adb -s "$SELECTED_DEVICE" shell dumpsys package "$PACKAGE_NAME" | grep versionCode | grep -o 'minSdk.*')
echo "Package name: $PACKAGE_NAME"
echo "Version: $VERSION"
echo "Last update: $LAST_UPDATE"
echo "SDK: $SDK"
adb -s "$SELECTED_DEVICE" shell dumpsys package "$PACKAGE_NAME" | grep -v "):\\|perm=\\|installPermissionsFixed=true" | grep -i -e permission
should_proceed "🔨 Do you want to open $PACKAGE_NAME settings?"
adb -s "$SELECTED_DEVICE" shell am start -a "android.settings.APPLICATION_DETAILS_SETTINGS" -d "package:$PACKAGE_NAME" &> /dev/null
================================================
FILE: android/abounds
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
redraw_screen(){
adb -s "$1" shell service check SurfaceFlinger &> /dev/null
adb -s "$1" shell service call activity 1599295570 &> /dev/null
}
turn_off_bounds(){
echo "👋 Turning off layout bounds ..."
adb -s "$1" shell setprop debug.layout false &> /dev/null
redraw_screen "$1"
}
turn_on_bounds(){
echo "📐 Turning on layout bounds..."
adb -s "$1" shell setprop debug.layout true &> /dev/null
redraw_screen "$1"
}
BOUNDS_STATE=$(adb -s "$SELECTED_DEVICE" shell getprop debug.layout | tr -cd '[[:alnum:]]._-')
if [ -z "$BOUNDS_STATE" ] || [ "$BOUNDS_STATE" == "false" ]; then
turn_on_bounds "$SELECTED_DEVICE"
else
turn_off_bounds "$SELECTED_DEVICE"
fi
================================================
FILE: android/abuildproject
================================================
#!/bin/bash
# shellcheck disable=SC2181
#ignore indirect exit code check at line 54
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
trap 'cleanup $@' 1 2 3 6 15
cleanup()
{
if [ -n "$OLD_PWD" ]; then
cd "$OLD_PWD" || exit
fi
rm -f "$TASK_LIST"
exit
}
list_build_variants(){
if [ -n "$1" ];
then
OLD_PWD=$PWD
cd "$1" || exit
fi
if ! [ -f "gradlew" ];
then
echo "🤷 No Android project found in current directory"
exit
fi
TASK_LIST="toolkit_task_list.txt"
echo "⏳ Detecting build variants, this may take a while..."
./gradlew tasks | grep '^install' > $TASK_LIST
if [ "$(nl "$TASK_LIST")" == "" ]; then
echo "🤷 No Android project build variants available! Aborting..."
exit
else
echo "🔨 Available:"
nl $TASK_LIST
fi
}
build_project_variant(){
read -r -p "📝 Choose build variant: " VARIANT_INDEX
TASK=$(sed "$VARIANT_INDEX"!d $TASK_LIST | awk '{ print $1 }' )
if [[ $VARIANT_INDEX == "" || $TASK == "" ]]; then
delete_lastline
build_project_variant
else
echo "🚀 Triggering new build..."
ANDROID_SERIAL=$SELECTED_DEVICE ./gradlew "$TASK"
fi
if [ $? == "0" ];
then
VARIANT=${TASK#"install"}
echo "✅ $VARIANT build variant installed successfully"
else
echo "❌ $VARIANT build variant installation failed"
fi
}
find_apk_path(){
rm -rf "./outputs/apk/*"
APK_PATH=$(find . -iname "*.apk" | sort | tail -1)
}
launch(){
android_detect_package_info "$1"
echo "🚀 Launching $APP_NAME..."
adb -s "$SELECTED_DEVICE" shell monkey -p "$PACKAGE_NAME" -c android.intent.category.LAUNCHER 1 &> /dev/null
}
copy_apk_to_desktop(){
FILENAME=$(echo "$PACKAGE_NAME" | tr . _)
FILENAME="$FILENAME.apk"
cp "$APK_PATH" "$HOME/Desktop/$FILENAME"
echo "💾 \"$FILENAME\" saved to ~/Desktop"
}
android_choose_device
list_build_variants "$@"
build_project_variant
find_apk_path
launch "$APK_PATH"
copy_apk_to_desktop
cleanup
================================================
FILE: android/acamera
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
echo "📷 Opening camera application..."
adb -s "$SELECTED_DEVICE" shell am start -a android.media.action.IMAGE_CAPTURE &> /dev/null
================================================
FILE: android/acheckdevice
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
GSM_URL='https://www.gsmarena.com/res.php3?sSearch='
echo_info(){
MANUFACTURER=$(adb -s "$SELECTED_DEVICE" shell getprop ro.product.manufacturer | tr -cd '[[:alnum:]]._-')
MODEL=$(adb -s "$SELECTED_DEVICE" shell getprop ro.product.model | tr -cd '[[:alnum:]]._-')
VERSION=$(adb -s "$SELECTED_DEVICE" shell getprop ro.build.version.release | tr -cd '[[:alnum:]]._-')
SDK=$(adb -s "$SELECTED_DEVICE" shell getprop ro.build.version.sdk | tr -cd '[[:alnum:]]._-')
INFO=$(printf "%s %s %s (API %s)" "$MANUFACTURER" "$MODEL" "$VERSION" "$SDK")
echo "📱 $INFO"
echo " • ID: $SELECTED_DEVICE"
echo " • CPU: $(adb -s "$SELECTED_DEVICE" shell getprop ro.product.cpu.abi | tr -cd '[[:alnum:]]._-')"
echo " • Display density: $(adb -s "$SELECTED_DEVICE" shell getprop ro.sf.lcd_density | tr -cd '[[:alnum:]]._-')"
}
check_screen_timeout(){
echo -n "🕑 Checking screen timeout"
TIMEOUT=$(adb -s "$SELECTED_DEVICE" shell settings get system screen_off_timeout)
TIMEOUT=${TIMEOUT%$'\r'} # remove trailing carriage return
if [ "$TIMEOUT" != "600000" ]; then
yes_or_no " - 🕤 Timeout is $TIMEOUT miliseconds, set to 10 minutes?"; if ! [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]]; then return; fi
adb -s "$SELECTED_DEVICE" shell settings put system screen_off_timeout 600000
else
echo " - ✅ 10 minutes"
fi
}
check_screen_brightness(){
echo -n "🔆 Checking screen brightness"
BRIGHTNESS=$(adb -s "$SELECTED_DEVICE" shell settings get system screen_brightness)
BRIGHTNESS=${BRIGHTNESS%$'\r'} # remove trailing carriage return
if [ "$BRIGHTNESS" != "255" ]; then
yes_or_no " - 🔥 Brightness is $BRIGHTNESS, set manual max brightness?"; if ! [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]]; then return; fi
adb -s "$SELECTED_DEVICE" shell settings put system screen_brightness_mode 0
adb -s "$SELECTED_DEVICE" shell settings put system screen_brightness 255
else
echo " - ✅ MAX"
fi
}
check_notification_volume(){
echo -n "📢 Checking notification volume"
RINGER_MODE=$(adb -s "$SELECTED_DEVICE" shell settings get global mode_ringer)
RINGER_MODE=${RINGER_MODE%$'\r'} # remove trailing carriage return
if [ "$RINGER_MODE" != "1" ]; then
yes_or_no " - 🔕 Ringer mode is not 1 (~silent), try to set silent mode?"; if ! [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]]; then return; fi
adb -s "$SELECTED_DEVICE" shell input keyevent 164
else
echo " - ✅ Muted"
fi
}
check_network_name_contains(){
echo -n "🌐 Checking WIFI network"
NET_STATS=$(adb -s "$SELECTED_DEVICE" shell dumpsys netstats | grep -E 'iface=wlan.*networkId' )
if echo "$NET_STATS" | grep -i "$1" &> /dev/null; then
yes_or_no " - ❗️ $1 network detected, open wifi settings?"; if [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]]; then adb -s "$SELECTED_DEVICE" shell am start -a android.net.wifi.PICK_WIFI_NETWORK &> /dev/null; fi
fi
if ! echo "$NET_STATS" | grep -E 'iface=wlan.*networkId' &> /dev/null; then
yes_or_no " - ❌ Disconnected, open wifi settings?"; if [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]]; then adb -s "$SELECTED_DEVICE" shell am start -a android.net.wifi.PICK_WIFI_NETWORK &> /dev/null; fi
else
echo " - ✅ Connected"
fi
}
check_automatic_date(){
echo -n "📆 Checking date"
AUTO_TIME=$(adb -s "$SELECTED_DEVICE" shell settings get global auto_time)
AUTO_TIME=${AUTO_TIME%$'\r'} # remove trailing carriage return
if [ "$AUTO_TIME" == "0" ]; then
yes_or_no " - ❗️ Date is set manually, open date settings?"
if [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]]; then
adb -s "$SELECTED_DEVICE" shell am start -a android.settings.DATE_SETTINGS &> /dev/null
fi
else
echo " - ✅ Automatic"
fi
}
check_locale(){
DEFAULT_LOCALE="en-US"
echo -n "👄 Checking locale"
CURRENT_LOCALE=$(adb -s "$SELECTED_DEVICE" shell getprop persist.sys.locale)
CURRENT_LOCALE=${CURRENT_LOCALE%$'\r'} # remove trailing carriage return
if [ "$CURRENT_LOCALE" != "$DEFAULT_LOCALE" ]; then
yes_or_no " - ❗️ Current locale is $CURRENT_LOCALE, open locale settings?"
if [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]]; then
adb -s "$SELECTED_DEVICE" shell am start -a android.settings.LOCALE_SETTINGS &> /dev/null
fi
else
echo " - ✅ $CURRENT_LOCALE"
fi
}
check_font_scale(){
DEFAULT_SCALE="1.0"
echo -n "🔠 Checking font scale"
SCALE=$(adb -s "$SELECTED_DEVICE" shell settings get system font_scale)
SCALE=${SCALE%$'\r'} # remove trailing carriage return
if [ "$SCALE" != "$DEFAULT_SCALE" ]; then
yes_or_no " - 🔍 Current scale is $SCALE, change to $DEFAULT_SCALE"
if [ "$RESPONSE" == "y" ] || [ "$RESPONSE" != "Y" ]; then
adb -s "$SELECTED_DEVICE" shell settings put system font_scale "$DEFAULT_SCALE"
fi
else
echo " - ✅ $SCALE"
fi
}
open_gsmarena(){
should_proceed "🔍 Search for the device on GSMArena?"
PHONE_URL=$GSM_URL$MODEL
open "$PHONE_URL"
}
android_choose_device
echo_info
check_screen_timeout
check_screen_brightness
check_notification_volume
check_automatic_date
check_locale
check_network_name_contains edge
check_font_scale
open_gsmarena
# More settings available at https://developer.android.com/reference/android/provider/Settings.System.html#SCREEN_OFF_TIMEOUT
================================================
FILE: android/acontrol
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
check_dependency "scrcpy"
check_adb_dependency
android_choose_device
android_device_info "$SELECTED_DEVICE"
echo "🔌 Connecting to $MANUFACTURER $MODEL (API $SDK)..."
scrcpy -s "$SELECTED_DEVICE" &> /dev/null &
================================================
FILE: android/adarkmode
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
turn_off_darkmode(){
echo "⚪️ Turning off dark mode..."
#adb -s "$SELECTED_DEVICE" shell settings put secure ui_night_mode 1 &> /dev/null #Not working without a reboot
adb -s "$1" shell cmd uimode night no &> /dev/null
}
turn_on_darkmode(){
echo "⚫️ Turning on dark mode..."
#adb -s "$1" shell settings put secure ui_night_mode 2 &> /dev/null
adb -s "$1" shell cmd uimode night yes &> /dev/null
}
DARKMODE_STATE=$(adb -s "$SELECTED_DEVICE" shell cmd uimode night)
if [ "$DARKMODE_STATE" != "Night mode: yes" ]; then
turn_on_darkmode "$SELECTED_DEVICE"
else
turn_off_darkmode "$SELECTED_DEVICE"
fi
================================================
FILE: android/aemulator
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
LOCAL_EMULATOR_LIST=$LOCATION/../data/toolkit_emulator_list.txt
NET_CHANGED=false
trap 'ctrlc $@' 1 2 3 6 15
ctrlc(){
if $NET_CHANGED ; then
disable_network_delay
fi
exit
}
help(){
if [[ $1 != "" ]]; then
echo "🤷 Unknown option: $1"
else
echo "🤷 Option missing"
fi
echo -e "Use one of the following options:\\n start - choose and launch installed emulator\\n gprs | edge | 3g - set network latency\\n call <number> - receive fake call\\n sms <number> <text> - recieve fake sms\\n gps <lat> <long> - set manual gps location\\n battery <0-100> - set manual battery level\\n telnet <command> - call telnet command (see README.md)"
}
check_java_dependency(){
if ! java -version &> /dev/null; then
echo "❌ Java not available, edit your .bash_profile or .zshrc to use Android Studio version"
echo "📝 Add the following line: export JAVA_HOME='/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home'"
echo "🔌 Restart terminal afterwards"
exit 1
fi
}
check_running_emulator(){
if ! adb devices | grep emulator &> /dev/null; then
echo "❌ No running emulators"
yes_or_no "❓ Do you want to start one?"
if [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]];
then
launch_emulator
android_wait_for_device
get_token
fi
exit
fi
}
get_emulator_list(){
echo "⏳ Getting Android emulator list..."
rm -f "$LOCAL_EMULATOR_LIST"
"$ANDROID_HOME"/cmdline-tools/latest/bin/avdmanager list avd | grep Name | awk '{print $2}' >> "$LOCAL_EMULATOR_LIST"
if [ "$(nl "$LOCAL_EMULATOR_LIST")" == "" ]; then
should_proceed "🤷 No emulators installed, install via Android Studio?"
echo "⏳ Opening Android Studio..."
open -a /Applications/Android\ Studio.app
exit
else
echo "📱 Available:"
nl "$LOCAL_EMULATOR_LIST"
fi
}
launch_emulator(){
get_emulator_list
if [ -z "$1" ]; then
read -r -p "📝 Choose: " EMULATOR_INDEX
else
EMULATOR_INDEX=$1
fi
EMULATOR_NAME=$(sed "$EMULATOR_INDEX"!d "$LOCAL_EMULATOR_LIST")
if [[ $EMULATOR_INDEX == "" || $EMULATOR_NAME == "" ]]; then
delete_lastline
launch_emulator
else
echo "🚀 Launching emulator..."
nohup "$ANDROID_HOME"/emulator/emulator -avd "$EMULATOR_NAME" -no-snapshot &> /dev/null &
rm "$LOCAL_EMULATOR_LIST"
fi
}
get_token(){
check_dependency "telnet"
[ -f ./emulator_console_auth_token ] || echo "localhost 5554" | telnet &> /dev/null
TOKEN=$(cat "$HOME"/.emulator_console_auth_token)
}
telnet_command() {
get_token
if [ -z "$1" ];then
read -r -p "📝 Insert telnet command: " COMMAND
else
COMMAND=$1
fi
{ echo "o localhost 5554"; sleep 1; echo "auth $TOKEN"; sleep 1; echo "$COMMAND"; } | telnet &> /dev/null
}
call(){
if [ -z "$1" ];then
read -r -p "📝 Insert caller number: " NUMBER
else
NUMBER=$1
fi
echo "📞 Making a call..."
telnet_command "gsm call $NUMBER"
echo "🔔 Ringing..."
}
send_sms(){
if [ -z "$1" ];then
read -r -p "📝 Insert sender number: " NUMBER
else
NUMBER=$1
fi
if [ -z "$2" ];then
read -r -p "📝 Insert text: " TEXT
else
TEXT=$2
fi
echo "📝 Sending fake SMS..."
telnet_command "sms send $NUMBER $TEXT"
echo "✅ Done"
}
set_gps(){
if [ -z "$1" ];then
read -r -p "📝 Insert latitude: " LAT
else
LAT=$1
fi
if [ -z "$2" ];then
read -r -p "📝 Insert longtitude: " LONG
else
LONG=$2
fi
echo "🌎 Setting manual GPS location..."
telnet_command "geo fix $LONG $LAT"
echo "✅ Done"
}
set_battery_level(){
if [ -z "$1" ];then
read -r -p "📝 Insert battery level: " LEVEL
else
LEVEL=$1
fi
echo "🔋 Setting manual battery level..."
{ echo "o localhost 5554"; sleep 1; echo "auth $TOKEN"; sleep 1; echo "power ac off"; echo "power status discharging"; echo "power capacity $LEVEL"; } | telnet &> /dev/null
echo "✅ Done"
}
set_network_delay(){
DELAY=$1
if [[ "$DELAY" == "3g" ]]; then
DELAY="umts"
fi
NET_CHANGED=true
echo "🌐 Simulating network limit..."
{ echo "o localhost 5554"; sleep 1; echo "auth $TOKEN"; sleep 1; echo "network delay $DELAY"; echo "network speed $DELAY"; } | telnet &> /dev/null
read -r -n 1 -p "⚡️ Press ENTER to stop..."
disable_network_delay
echo "✅ Done"
}
disable_network_delay(){
echo "🔄 Disabling network limits..."
{ echo "o localhost 5554"; sleep 1; echo "auth $TOKEN"; sleep 1; echo "network delay none"; echo "network speed full"; } | telnet &> /dev/null
NET_CHANGED=false
}
check_for_update
check_java_dependency
case $1 in
'start')
launch_emulator "$2"
;;
'gprs' | 'edge' | '3g')
check_running_emulator
set_network_delay "$1"
;;
'call')
check_running_emulator
call "$2"
;;
'sms')
check_running_emulator
send_sms "$2" "$3"
;;
'gps')
check_running_emulator
set_gps "$2" "$3"
;;
'battery')
check_running_emulator
set_battery_level "$2"
;;
'telnet')
check_running_emulator
telnet_command "$2"
;;
*)
help "$1"
check_running_emulator
;;
esac
================================================
FILE: android/aerase
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
if [[ "$1" != "" ]];
then
APP=$1
android_is_package_installed "$APP"
else
APP=$(android_get_foreground_package)
fi
should_proceed "🧽 Do you really want to erase $APP data?"
adb -s "$SELECTED_DEVICE" shell pm clear "$APP" &> /dev/null
echo "🚀 Launching..."
adb -s "$SELECTED_DEVICE" shell monkey -p "$APP" -c android.intent.category.LAUNCHER 1 &> /dev/null
================================================
FILE: android/afontscale
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
set_font_scale(){
adb -s "$SELECTED_DEVICE" shell settings put system font_scale "$1"
}
android_choose_device
if [ -z "$1" ] 2> /dev/null
then
CURRENT_FONT_SIZE=$(adb -s "$SELECTED_DEVICE" shell settings get system font_scale)
if [ "$CURRENT_FONT_SIZE" != "1.0" ]; then
echo "🔄 Font scale restored to default \"1.0\""
set_font_scale "1.0"
else
echo "🔍 Setting bigger font scale to \"1.3\"..."
set_font_scale "1.3"
fi
else
echo "🔍 Setting font scale to \"$1\"..."
set_font_scale "$1"
fi
================================================
FILE: android/agoogleplay
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
search_gp(){
APP_NAME="$1"
echo "🛒 Searching for $APP_NAME in Google Play..."
APP_NAME=$(echo "$APP_NAME" | sed -e 's/ /\%20/g')
GOOGLE_PLAY_URL="http://play.google.com/store/search\\?q\\=$APP_NAME\\&c\\=apps"
adb -s "$SELECTED_DEVICE" shell am start -a android.intent.action.VIEW -d "$GOOGLE_PLAY_URL" &> /dev/null
}
if [ -z "$1" ] ; then
search_gp "$(android_get_foreground_package)"
exit
else
APP_NAME="'$*'"
search_gp "$APP_NAME"
fi
================================================
FILE: android/ainstall
================================================
#!/bin/bash
trap "kill 0" SIGINT # Kill all spawned subprocesses on ctrl^c
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
install_app(){
echo "⌛️ Installing \"$PACKAGE_NAME\" to $1..."
TEMPORARY_FILE="$TEMPORARY_FILE-$(date +%s)"
adb -s "$1" install -t -r "$2" &> "$TEMPORARY_FILE"
if grep -q Failure "$TEMPORARY_FILE" ; then
echo "❌ Installation to $1 failed!"
echo "🤕 Uninstall existing version or troubleshoot the package"
echo "🔥 Error details: $(grep 'Failure' "$TEMPORARY_FILE" | sed 's/^.*: //')"
exit 1
fi
echo "🚀 Launching $APP_NAME on $1..."
adb -s "$1" shell monkey -p "$PACKAGE_NAME" -c android.intent.category.LAUNCHER 1 &> /dev/null
}
check_args_valid(){
if [[ "$1" != "-a" ]]; then
FILE=$1
else
FILE=$2
fi
if [ ! -f "$PWD/$FILE" ] && [ ! -f "$FILE" ]; then
abort "🤷 Installation file not found!"
fi
if [[ "$FILE" != *".apk" ]]; then
abort "🤷 Unsupported file!"
fi
}
run()
{
if [[ $1 == "-a" ]]; then
check_for_update
android_check_connected
android_get_devices_auth_dump
android_detect_package_info "$2"
for line in $(adb devices | grep -v "List" | awk '{print $1}')
do
DEVICE=$(echo "$line" | awk '{print $1}')
install_app "$DEVICE" "$2" &
done
wait
else
android_choose_device
android_detect_package_info "$1"
install_app "$SELECTED_DEVICE" "$1"
fi
}
# "$@" - pass all arguments
check_args_valid "$@"
run "$@"
================================================
FILE: android/akill
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
if [[ "$1" != "" ]];
then
PACKAGE_NAME=$1
android_is_package_installed "$PACKAGE_NAME"
else
PACKAGE_NAME=$(android_get_foreground_package)
fi
echo "🔪 Package \"$PACKAGE_NAME\" process killed"
adb -s "$SELECTED_DEVICE" shell am force-stop "$PACKAGE_NAME"
echo "🚀 Relaunching the app..."
adb -s "$SELECTED_DEVICE" shell monkey -p "$PACKAGE_NAME" -c android.intent.category.LAUNCHER 1 &> /dev/null
================================================
FILE: android/alaunch
================================================
#!/bin/bash
source "$(dirname "$0")"/../common_tools
android_choose_device
if [[ "$1" == "-s" ]]; then
PACKAGES=($(adb -s "$SELECTED_DEVICE" shell pm list packages -f | sed -e 's/.*=//' | sort))
elif [[ -n "$1" ]]; then
PACKAGE="$1"
android_is_package_installed "$PACKAGE"
else
PACKAGES=($(adb -s "$SELECTED_DEVICE" shell pm list packages -f -3 | sed -e 's/.*=//' | sort))
fi
if [ -z "$PACKAGE" ]; then
PACKAGES_LISTED=()
for P in "${PACKAGES[@]}" #removes trailing \r
do
P=${P%$'\r'}
PACKAGES_LISTED+=("$P")
done
if [ ${#PACKAGES_LISTED[@]} -eq 0 ]; then
echo "🤷 No third-party apps installed, use \"alaunch -s\" to list system packages"
exit
fi
echo "📋 Choose package to launch:"
select OPTION in "${PACKAGES_LISTED[@]}"
do
case $OPTION in
*) PACKAGE=$OPTION;break; ;;
esac
done
fi
echo "🚀 Launching $PACKAGE..."
adb -s "$SELECTED_DEVICE" shell monkey -p "$PACKAGE" -c android.intent.category.LAUNCHER 1 &> /dev/null
================================================
FILE: android/alog
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
filter_by_package(){
android_is_package_installed "$1"
echo "🔍 Filtering by package name: $1"
PID=$(adb -s "$SELECTED_DEVICE" shell ps | grep -i "$1" | cut -c10-15)
adb -s "$SELECTED_DEVICE" logcat | grep "$PID"
}
raw_log(){
echo "📜 Device log:"
adb -s "$SELECTED_DEVICE" logcat
}
if [ "$1" == "-f" ]; then
if [ -z "$2" ]; then
read -r -p "🔬 Insert package name (Android 7+) or leave empty to proceed: " PACKAGE
else
PACKAGE=$2
fi
filter_by_package "$PACKAGE"
else
raw_log
fi
================================================
FILE: android/aoptions
================================================
#!/bin/bash
TOOLKIT_LOCATION=$(dirname "$0")
source "$TOOLKIT_LOCATION"/../common_tools
android_choose_device
LOCAL_SETTINGS_LIST_PATH=$TOOLKIT_LOCATION/../data/toolkit_intent_list.txt
import_intents(){
echo "⏳ Importing settings activity list..."
ANDROID_TOOLS_SETTINGS_INTENT_LIST_PATH=$(find ~/Library/Android/sdk -name 'activity_actions.txt' | sort | tail -1)
{
grep -i "android.settings" "$ANDROID_TOOLS_SETTINGS_INTENT_LIST_PATH" # List settings intents
grep -i -e "android.net.wifi.PICK_WIFI_NETWORK" -e "android.os.storage.action.MANAGE_STORAGE" -e "android.intent.action.MANAGE_PERMISSIONS" -e "android.intent.action.SET_WALLPAPER" -e "android.intent.action.VIEW_DOWNLOADS" "$ANDROID_TOOLS_SETTINGS_INTENT_LIST_PATH" # List alternate settings intents
grep -i "android.media.action" "$ANDROID_TOOLS_SETTINGS_INTENT_LIST_PATH" # List media intents
} >> "$LOCAL_SETTINGS_LIST_PATH"
wc -l "$LOCAL_SETTINGS_LIST_PATH" | awk '{print $1}' | grep -q 0 && echo "❗️ Imported list is empty, reimporting lower sdk variant..." && rm "$(find ~/Library/Android/sdk -name 'activity_actions.txt' | sort | tail -1)" && import_intents && return
echo "✅ Importing from $ANDROID_TOOLS_SETTINGS_INTENT_LIST_PATH completed successfully"
}
start_settings_intent(){
SETTINGS_INTENT=$(sed "$LINE"!d "$LOCAL_SETTINGS_LIST_PATH")
echo "🚀 Starting $SETTINGS_INTENT"
adb -s "$SELECTED_DEVICE" shell am start -a "$SETTINGS_INTENT" &> /dev/null
}
search_for_intent(){
if nl "$LOCAL_SETTINGS_LIST_PATH" | grep -i -q "$1"; then
if [[ $(grep -c -i "$1" "$LOCAL_SETTINGS_LIST_PATH") -eq 1 ]]; then #If there is only one result
LINE=$(nl "$LOCAL_SETTINGS_LIST_PATH" | grep -i "$1" | awk '{print $1}')
else
nl "$LOCAL_SETTINGS_LIST_PATH" | grep -i "$1"
read -r -p "📝 Choose option number: " LINE
fi
start_settings_intent
else
read -r -p "🤷 No \"$1\" intent found, try again or leave blank: " KEYWORD
search_for_intent "$KEYWORD"
fi
}
handle_preset(){
case "$1" in
"S" | "s")
echo "🚀 Launching system settings app root activity..."
adb -s "$SELECTED_DEVICE" shell am start -a android.settings.SETTINGS &> /dev/null
;;
"1" | "dev" | "developer")
echo "🔨 Opening developer settings..."
adb -s "$SELECTED_DEVICE" shell am start -a android.settings.APPLICATION_DEVELOPMENT_SETTINGS &> /dev/null
;;
"2" | "locale" | "lang" | "language")
echo "🌍 Opening locale settings..."
adb -s "$SELECTED_DEVICE" shell am start -a android.settings.LOCALE_SETTINGS &> /dev/null
;;
"4" | "wifi" | "network")
echo "🌐 Opening WIFI network settings..."
adb -s "$SELECTED_DEVICE" shell am start -a android.net.wifi.PICK_WIFI_NETWORK &> /dev/null
;;
"5" | "storage")
echo "📦 Opening storage management ..."
adb -s "$SELECTED_DEVICE" shell am start -a android.os.storage.action.MANAGE_STORAGE &> /dev/null
;;
"6" | "power")
echo "🔋 Opening power usage statistics..."
adb -s "$SELECTED_DEVICE" shell am start -a android.intent.action.POWER_USAGE_SUMMARY &> /dev/null
;;
"3" | "date" | "time" | "datetime")
echo "📅 Opening date & time settings..."
adb -s "$SELECTED_DEVICE" shell am start -a android.settings.DATE_SETTINGS &> /dev/null
;;
"0" | "all" | "list" | "A" | "a")
echo "📜 Available settings activities:"
nl "$LOCAL_SETTINGS_LIST_PATH"
read -r -p "📝 Choose option number: " LINE
start_settings_intent
;;
"U" | "update" | "u")
rm "$LOCAL_SETTINGS_LIST_PATH"
import_intents
;;
*)
search_for_intent "$1"
;;
esac
}
# Initialize available intent list - inspiration here https://stackoverflow.com/questions/8971160/what-is-the-exhaustive-list-of-all-android-intent-action-actions-available-in
if [ ! -f "$LOCAL_SETTINGS_LIST_PATH" ]; then
echo "✨ Activity list not initialized yet"
import_intents
fi
# If arugment not passed, show preset chooser
if [[ "$1" == "" ]]; then
TOOLKIT_INTENT_COUNT=$(wc -l "$LOCAL_SETTINGS_LIST_PATH")
TOOLKIT_INTENT_COUNT=$(echo "$TOOLKIT_INTENT_COUNT" | awk '{print $1}') # Remove ghost whitespaces 🙃
echo "📋 Available options:"
tput setaf 3; echo "A) Show all $TOOLKIT_INTENT_COUNT settings options"; tput sgr0
echo -e "S) Open system settings application\\n1) Developer\\n2) Locale\\n3) Date & time\\n4) Wifi network\\n5) Storage management\\n6) Power usage\\nU) Update settings list from Android sdk\\nor\\n<text> to search in all settings"
read -r -p "📝 Enter your selection: " PRESET
handle_preset "$PRESET"
exit
else
handle_preset "$1"
fi
================================================
FILE: android/apaste
================================================
#!/bin/bash
# shellcheck disable=SC1001
#ignore regex - sign occurence
trap "kill 0" SIGINT # Kill all spawned subprocesses on ctrl^c
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
LOREM="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
ARGUMENT_COUNT="$#"
check_text(){
if [ -n "$1" ]
then
if ! [[ "$*" =~ [^a-zA-Z0-9\ \-\.\@] ]]; then
TEXT=$1
else
echo "🤷 Only basic alphanumeric characters are supported!"
exit 1
fi
else
echo "🤷 No text to insert!"
exit 1
fi
}
escape_spaces(){
ESCAPED_TEXT=$(echo "$1" | sed -e 's/ /\%s/g')
}
send_text(){
escape_spaces "$1"
android_get_device_sdk "$SELECTED_DEVICE"
if (( SDK > 27 )); then
# Insert only first character
adb -s "$SELECTED_DEVICE" shell "input text '${ESCAPED_TEXT:0:1}'"
# Afterwards the rest - workaround for API 28+ edittext char skip bug
adb -s "$SELECTED_DEVICE" shell "input text '${ESCAPED_TEXT:1:${#ESCAPED_TEXT}}'"
else
adb -s "$SELECTED_DEVICE" shell "input text '$ESCAPED_TEXT'"
fi
}
execute_by_arguments(){
echo "📲 Sending text to $SELECTED_DEVICE..."
# Handle arguments
if [ "$1" == "-l" ];
then
send_text "$LOREM"
elif [ "$ARGUMENT_COUNT" -gt 1 ];
then
for ARGUMENT in "$@"
do
send_text "$ARGUMENT"
sleep 0.5
if ! [ "$ARGUMENT" = "${*: -1}" ]; then #if not last argument, jump to next field
adb -s "$SELECTED_DEVICE" shell input keyevent 61
fi
done
else
send_text "$TEXT"
fi
}
execute_for_all(){
check_for_update
android_get_devices_auth_dump
for DEVICE in $(adb devices | grep -v "List" | awk '{print $1}')
do
(SELECTED_DEVICE=$DEVICE; execute_by_arguments "$@") & # Set var and start command in subshell
done
wait
}
check_text "$@"
if [[ "$1" == "-a" ]]; then
execute_for_all "${@:2}" # All arguments starting from 2nd
else
android_choose_device
execute_by_arguments "$@"
fi
================================================
FILE: android/apermissionreset
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
tput setaf 1
should_proceed "🚫 REVOKE ALL GRANTED PERMISSIONS on $SELECTED_DEVICE?"
tput setaf 0
adb -s "$SELECTED_DEVICE" shell pm reset-permissions
================================================
FILE: android/apowerbutton
================================================
#!/bin/bash
source "$(dirname "$0")"/../common_tools
android_choose_device
# Reference for key events - https://gist.github.com/arjunv/2bbcca9a1a1c127749f8dcb6d36fb0bc
echo "👋 Sending power button key event..."
# Send POWER screen key event (key 26)
adb -s "$SELECTED_DEVICE" shell input keyevent POWER &>/dev/null
================================================
FILE: android/areboot
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
should_proceed "🔌 Do you really want to reboot - $SELECTED_DEVICE?"
echo "🔄 Rebooting the device..."
adb -s "$SELECTED_DEVICE" reboot &> /dev/null
================================================
FILE: android/arecord
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
# Trap signal handling
trap 'ctrlc "$@"' 1 2 3 6 15
USE_LEGACY_RECORDING=false
check_dependency "scrcpy"
ctrlc() {
adb -s "$SELECTED_DEVICE" shell settings put system show_touches 0
if $RECORDING; then
sleep 1
if $USE_LEGACY_RECORDING; then
if [ -z "$2" ]; then
android_device_info "$SELECTED_DEVICE"
FILENAME="$MANUFACTURER-$MODEL-API$SDK-$(date +%Y-%m-%d-%H-%M-%S)"
else
FILENAME="$2"
fi
echo "📁 Copying the video from the device..."
adb -s "$SELECTED_DEVICE" pull "$DEVICE_FILE_PATH"/output.mp4 ~/Desktop/"$FILENAME".mp4 &>/dev/null
adb -s "$SELECTED_DEVICE" shell rm "$DEVICE_FILE_PATH"/output.mp4 &>/dev/null
else
# Do nothing
:
fi
echo "✅ Saved into ~/Desktop/$FILENAME.mp4"
fi
exit
}
RECORDING=false
android_choose_device
android_get_device_sdk "$SELECTED_DEVICE"
android_get_storage_location_per_SDK "$SDK"
RECORDING=true
echo "📹 Recording screen on $SELECTED_DEVICE, stop it using ctrl^c"
adb -s "$SELECTED_DEVICE" shell settings put system show_touches 1
# Parse the flag option
if [ "$1" == "-l" ]; then
USE_LEGACY_RECORDING=true
fi
if [ -z "$2" ]; then
android_device_info "$SELECTED_DEVICE"
FILENAME="$MANUFACTURER-$MODEL-API$SDK-$(date +%Y-%m-%d-%H-%M-%S)"
else
FILENAME="$2"
fi
OUTPUT_PATH=~/Desktop/"$FILENAME".mp4
# Perform actions based on flags
if $USE_LEGACY_RECORDING; then
adb -s "$SELECTED_DEVICE" shell screenrecord "$DEVICE_FILE_PATH"/output.mp4
else
scrcpy -s "$SELECTED_DEVICE" --verbosity=error --no-window --audio-codec=aac --record=file.mp4 --record="$OUTPUT_PATH" &>/dev/null
fi
# Unset the trap
trap - 1 2 3 6 15
================================================
FILE: android/ascreenshot
================================================
#!/bin/bash
trap "kill 0" SIGINT # Kill all spawned subprocesses on ctrl^c
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
screenshot(){
android_device_info "$1"
FILENAME="$MANUFACTURER-$MODEL-API$SDK-$(date +%Y-%m-%d-%H-%M-%S).png"
android_get_storage_location_per_SDK "$SDK"
echo "📸 Saving screenshot into $FILENAME..."
adb -s "$1" shell screencap -p "$DEVICE_FILE_PATH"/output.png
adb -s "$1" pull "$DEVICE_FILE_PATH"/output.png ~/Desktop/"$FILENAME" &>/dev/null
adb -s "$1" shell rm "$DEVICE_FILE_PATH"/output.png
}
screenshot_all(){
check_for_update
android_get_devices_auth_dump
for line in $(adb devices | grep -v "List" | awk '{print $1}')
do
device=$(echo "$line" | awk '{print $1}')
screenshot "$device" &
done
wait
}
if [ "$1" == "-a" ];
then
screenshot_all
else
android_choose_device
screenshot "$SELECTED_DEVICE"
fi
================================================
FILE: android/aservices
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
SERVICE_LIST=$LOCATION/../data/toolkit_android_services.txt
source "$LOCATION"/../common_tools
android_choose_device
echo "🔍 Getting background service list..."
adb -s "$SELECTED_DEVICE" shell service list | tail -n +2 > "$SERVICE_LIST"
cat "$SERVICE_LIST"
SERVICE_COUNT=$(wc -l < "$SERVICE_LIST")
choose_number "$SERVICE_COUNT" "🔍 Find more about specific service - choose number: "
SERVICE_PACKAGE=$(sed "$CHOICE"!d "$SERVICE_LIST" | cut -d "[" -f2 | cut -d "]" -f1) #get string in brackets
QUERY="android service '$SERVICE_PACKAGE'"
echo "🌐 Performing Google search for: $QUERY"
open https://www.google.com/search?q="$QUERY"
# Potential usage: https://stackoverflow.com/questions/17580199/sending-a-sms-on-android-through-adb/30224091
# More: https://resources.infosecinstitute.com/android-hacking-security-part-3-exploiting-broadcast-receivers/#gref
================================================
FILE: android/atalkback
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
turn_off_talkback(){
echo "🔇 Turning off TalkBack..."
adb -s "$1" shell am force-stop com.google.android.marvin.talkback &> /dev/null
}
turn_on_talkback(){
echo "🔊 Turning on TalkBack..."
adb -s "$1" shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService &> /dev/null
}
TALKBACK_STATE=$(adb -s "$SELECTED_DEVICE" shell pidof com.google.android.marvin.talkback)
if [ -z "$TALKBACK_STATE" ] || [ "$TALKBACK_STATE" == "" ]; then
turn_on_talkback "$SELECTED_DEVICE"
else
turn_off_talkback "$SELECTED_DEVICE"
fi
================================================
FILE: android/atestmonkey
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
trap 'ctrlc' 1 2 3 6 15
ctrlc(){
if $RUNNING_TESTS; then
MONKEY_TASK_ID=$(adb -s "$SELECTED_DEVICE" shell pidof "com.android.commands.monkey")
adb -s "$SELECTED_DEVICE" shell kill "$MONKEY_TASK_ID" >/dev/null 2>&1
echo "🔪 Test monkey terminated, the device is safe to use now!"
fi
unlock_app_fullscreen "$SELECTED_DEVICE"
exit 2
}
unlock_app_fullscreen(){
adb -s "$1" shell am task lock stop >/dev/null 2>&1
echo "🔓 App fullscreen pinning disabled"
}
update_package_name(){
APP_PACKAGE_NAME="$(android_get_foreground_package "$1")"
}
check_screen_pinning(){
PINNING_ENABLED=$(adb -s "$1" shell settings get system lock_to_app_enabled)
PINNING_ENABLED=${PINNING_ENABLED%$'\r'} # remove trailing carriage return
if [ "$PINNING_ENABLED" != "1" ]; then
adb -s "$1" shell am start -a android.settings.SECURITY_SETTINGS >/dev/null 2>&1
read -r -p "🔑 Enable \"Screen pinning\" option in security settings, then press enter..."
fi
}
lock_task_fullscreen(){
check_screen_pinning "$1"
adb -s "$1" shell monkey -p "$APP_PACKAGE_NAME" -c android.intent.category.LAUNCHER 1 &> /dev/null
adb -s "$1" shell input keyevent "KEYCODE_APP_SWITCH"
read -r -p "📌 Press the \"Pin\" button in \"$APP_PACKAGE_NAME\" window, then press enter... " #TODO add check if already on
}
run_test(){
SEED="$2"
EVENT_COUNT="$3"
tput setaf 3 && should_proceed "🔥 DANGER ZONE ⊗ Send $EVENT_COUNT monkey test events to \"$APP_PACKAGE_NAME\"? (may take a while)" && tput sgr0 #set red and white text color
echo "🐒 Running monkey stress test... (press ctrl^c to end now)"
RUNNING_TESTS=true
LOG_FILE=~/Desktop/"monkey-test-log-$SEED-$APP_PACKAGE_NAME-$MANUFACTURER-$MODEL-API$SDK-$(date +%Y-%m-%d-%H-%M-%S).txt"
adb -s "$1" shell monkey -p "$APP_PACKAGE_NAME" -s "$SEED" --pct-appswitch 0 --pct-syskeys 0 --pct-anyevent 0 "$EVENT_COUNT" &> "$LOG_FILE"
unlock_app_fullscreen "$@"
grep -q "CRASH" "$LOG_FILE" && tput setaf 1 && echo "❌ Test failed, see crash log for details, seed: $SEED" && tput sgr0 && open "$LOG_FILE" && exit 1
tput setaf 2 && echo "✅ Test passed, successfully executed $EVENT_COUNT events, seed: $SEED" && tput sgr0
}
RUNNING_TESTS=false
EVENT_COUNT=15000 #Converts to $1 if passed
SEED="$RANDOM"
android_choose_device
android_device_info "$SELECTED_DEVICE"
update_package_name "$SELECTED_DEVICE"
lock_task_fullscreen "$SELECTED_DEVICE"
case "$1" in #if $1 not number, LOL
''|*[!0-9]*) ;; #nothing left to do
*) EVENT_COUNT="$1" ;;
esac
case "$2" in #if $2 not number, LOL
''|*[!0-9]*) ;; #nothing left to do
*) SEED="$2" ;;
esac
run_test "$SELECTED_DEVICE" "$SEED" "$EVENT_COUNT"
================================================
FILE: android/atestmonkeykill
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
trap "kill 0" SIGINT # Kill all spawned subprocesses on ctrl^c
android_choose_device
MONKEY_TASK_ID=$(adb -s "$SELECTED_DEVICE" shell pidof "com.android.commands.monkey")
if [ -z "$MONKEY_TASK_ID" ]; then
echo "🙈 No test monkey running, device is safe to use"
else
adb -s "$SELECTED_DEVICE" shell kill "$MONKEY_TASK_ID" >/dev/null 2>&1
echo "🔪 Test monkey terminated, the device is safe to use now!"
fi
================================================
FILE: android/auninstall
================================================
#!/bin/bash
trap "kill 0" SIGINT # Kill all spawned subprocesses on ctrl^c
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
init_uninstalling(){
echo "⏳ Getting third-party package list..."
IGNORED_PACKAGES=( "com.microsoft.hockeyapp.testerapp" "io.crash.air" "de.codenauts.hockeyapp" "ar.core" "com.framerjs.android" "com.figma.mirror" "com.invisionapp.ifa" "com.android.chrome" "com.google.ar.core" "no.nordicsemi.android.mcp" "com.x8bit.bitwarden" )
PACKAGES=($(adb -s "$SELECTED_DEVICE" shell pm list packages -f -3 | sed -e 's/.*=//' | sort))
}
uninstall_all(){
for PKG in "${PACKAGES[@]}"
do
PKG=${PKG%$'\r'} #removes trailing \r
uninstall_package "$PKG" &
done
wait
}
uninstall_package(){
PACKAGE="$1"
echo "${PACKAGES[*]}" | grep -w "$PACKAGE" &> /dev/null || { echo "🤷 Package \"$PACKAGE\" not installed"; return 1; }
echo "${IGNORED_PACKAGES[*]}" | grep -w "$PACKAGE" &> /dev/null && { echo "❌ Package \"$PACKAGE\" is whitelisted"; return 1; }
echo "🔥 Uninstalling \"$PACKAGE\"..."
adb -s "$SELECTED_DEVICE" shell pm uninstall "$PACKAGE" &> /dev/null
}
select_option(){
echo "📋 Choose package number:"
select OPTION in "${PACKAGES_LISTED[@]}"
do
case $OPTION in
*) PACKAGE=$OPTION;break; ;;
esac
done
if [[ -z $PACKAGE ]]; then
echo "❌ Invalid option picked, retry"
select_option
fi
}
filter_packages(){
PACKAGES_LISTED=()
for PKG in "${PACKAGES[@]}" #removes trailing \r
do
PKG=${PKG%$'\r'}
echo "${IGNORED_PACKAGES[@]}" | grep -w "$PKG" &> /dev/null && { echo "⏩ Skipped \"$PKG\""; continue; }
PACKAGES_LISTED+=("$PKG")
done
if [ ${#PACKAGES_LISTED[@]} -eq 0 ]; then
echo "🤷 Nothing to uninstall"
exit
fi
}
handle_arguments(){
if [[ -z "$2" ]]; then
android_choose_device
else
SELECTED_DEVICE=$2
fi
init_uninstalling
if [ -z "$1" ]; then
filter_packages
select_option
uninstall_package "$PACKAGE"
elif [[ "$1" == "-w" ]]; then
if [[ -z "$2" ]]; then
tput setaf 1
should_proceed "💣 Delete all third-party apps on $SELECTED_DEVICE_MODEL - $SELECTED_DEVICE?"
tput sgr0
fi
uninstall_all
elif [[ -n "$1" ]]; then
uninstall_package "$1"
fi
}
handle_arguments "$@"
echo "✅ Done"
================================================
FILE: android/aurl
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
open_url(){
check_url "$2"
echo "🌎 Opening url on $1..."
adb -s "$1" shell am start -a android.intent.action.VIEW -d "$URL" &> /dev/null
}
check_args_valid(){
if [[ "$1" != "-a" ]]; then
URL=$1
else
URL=$2
fi
}
run()
{
if [[ $1 == "-a" ]]; then
check_for_update
android_check_connected
android_get_devices_auth_dump
for line in $(adb devices | grep -v "List" | awk '{print $1}')
do
DEVICE=$(echo "$line" | awk '{print $1}')
open_url "$DEVICE" "$URL" &
done
wait
else
android_choose_device
open_url "$SELECTED_DEVICE" "$URL"
fi
}
check_args_valid "$@"
run "$@"
================================================
FILE: android/awipe
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
android_choose_device
prompt(){
tput setaf 1
yes_or_no "💣 Wipe all data on $SELECTED_DEVICE_MODEL - $SELECTED_DEVICE?"
tput sgr0
if [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]]; then
wipe_apps
wipe_data
fi
}
wipe_data(){
android_device_info "$SELECTED_DEVICE"
android_get_storage_location_per_SDK "$SDK"
echo "🔥 Deleting everything in mnt/sdcard..."
adb -s "$SELECTED_DEVICE" shell rm -rf "$DEVICE_FILE_PATH/*" &>/dev/null
}
wipe_apps(){
echo "🔥 Deleting all third-party apps..."
"$LOCATION"/auninstall "-w" "$SELECTED_DEVICE"
}
prompt
echo "✅ Done"
================================================
FILE: android/awireless
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
get_device_ip(){
android_choose_device
DEVICE_IP=$(adb -s "$SELECTED_DEVICE" shell ip route | awk '{print $9}')
DEVICE_IP=$(echo "$DEVICE_IP" | cut -d' ' -f1)
}
setup_network_connection(){
echo "🌎 Setting up wireless connection..."
adb -s "$SELECTED_DEVICE" tcpip 5555 &> /dev/null
echo "🌎 Getting device IP..."
delete_lastline
echo "🌎 Device IP: $DEVICE_IP"
echo "⏳ Connecting via local network..."
STATUS=$(adb connect "$DEVICE_IP:5555")
echo "$STATUS" | grep "refused" && echo "❌ Connection refused - already connected?" && return
echo "✅ Connected successfully, you can unplug the USB cable"
}
setup_usb_connection(){
echo "🔌 Disabling wireless connection..."
adb disconnect "$DEVICE_IP:5555" &> /dev/null
adb usb &> /dev/null
}
get_device_ip
if [[ "$SELECTED_DEVICE" == "emulator"* ]]; then
echo "🤷 Emulator is wireless by default..."
exit 1
fi
if [ "$SELECTED_DEVICE" == "$DEVICE_IP:5555" ]; then
setup_usb_connection
else
setup_network_connection
fi
================================================
FILE: changelog.txt
================================================
🎉 This is a new (experimental) version 1.4.1!
📹 arecord was fixed to work with latest scrcpy version
If you are experiencing issues, try running "brew upgrade scrcpy"
📷 iscreenshot was fixed to work with iOS 17 or newer
This change is still experimental - please, report back any issues
👋 apowerbutton was added based on a pull request by luispinho
Thanks for your contribution, mate!
⭐️ Special thanks to Lenka and František for proposing compatibility fixes
https://github.com/vrbajiva
https://github.com/franceskoooo
💌 Rate Mobile Toolkit and provide optional feedback using this link
https://forms.gle/nfBHeMSjxEQMs1kv5
================================================
FILE: common_tools
================================================
#!/bin/bash
# shellcheck disable=SC2034
##############################################################################
### VARs
SCRIPT_LOCATION=$(dirname "$0")
LAST_CHECK_DATE_FILE="$SCRIPT_LOCATION/../data/toolkit_last_check_date.txt"
TEMPORARY_FILE="/private/tmp/mobile-toolkit-cache"
REGEX_NUMBER='^[0-9]+$'
##############################################################################
### Android
android_check_connected(){
android_get_devices
#No device connected
if [ ${#DEVICES[@]} -eq 0 ]
then
echo "❌ No Android devices detected"
exit 1
fi
}
android_wait_for_device(){
echo "⏳ Waiting for Android device..."
adb wait-for-any-device
android_get_devices
}
android_get_devices_auth_dump(){
DEVICES_DUMP="$SCRIPT_LOCATION/../data/toolkit_adb_devices_dump.txt"
rm -f $DEVICES_DUMP
adb devices | grep -v "List" >> $DEVICES_DUMP
if cat "$DEVICES_DUMP" | grep -q unauthorized ; then
read -r -p $'🚨 Unauthorized Android device detected!\n🔌 Reconnect it, allow USB debugging and press ENTER...'
android_get_devices_auth_dump
fi
if cat "$DEVICES_DUMP" | grep -q offline ; then
read -r -p $'🚨 Offline Android device detected!\n🔌 Wait until the startup is complete, then press ENTER...'
android_get_devices_auth_dump
fi
}
android_get_devices(){
#Populate array with device ids
DEVICES=()
android_get_devices_auth_dump
for LINE in $(cat $DEVICES_DUMP | awk '{print $1}')
do
DEVICE=$(echo "$LINE" | awk '{print $1}')
DEVICES+=("$DEVICE")
done
}
android_get_device_sdk(){
SDK=$(adb -s "$1" shell getprop ro.build.version.sdk | tr -cd '[[:alnum:]]._-')
}
android_device_info(){
MANUFACTURER=$(adb -s "$1" shell getprop ro.product.manufacturer | tr -cd '[[:alnum:]]._-')
MODEL=$(adb -s "$1" shell getprop ro.product.model | tr -cd '[[:alnum:]]._-')
VERSION=$(adb -s "$1" shell getprop ro.build.version.release | tr -cd '[[:alnum:]]._-')
SDK=$(adb -s "$1" shell getprop ro.build.version.sdk | tr -cd '[[:alnum:]]._-')
INFO=$(printf "%s) %s %s %s (API %s) - %s" "$NUMBER" "$MANUFACTURER" "$MODEL" "$VERSION" "$SDK" "$1")
}
android_choose_device() {
check_for_update
check_adb_dependency
android_check_connected
#Gather device info and choose device
if [ ${#DEVICES[@]} -gt 1 ]
then
NUMBER=1
echo "📱 Available devices:"
for ID in "${DEVICES[@]}"
do
android_device_info "$ID"
echo "$INFO"
((NUMBER++))
done
read -r -p "📝 Select a device: " CHOICE
while :;
do
if [[ ! $CHOICE =~ $REGEX_NUMBER ]] || [ "$CHOICE" -le "0" -o "$CHOICE" -gt "${#DEVICES[@]}" ]; then
echo -en "\033[1A\033[2K" #deletes last echoed line in terminal
read -r -p "🤷 Invalid input, try again: " CHOICE
else
break
fi
done
SELECTED_DEVICE=${DEVICES[(($CHOICE-1))]}
else
SELECTED_DEVICE="${DEVICES[0]}"
fi
SELECTED_DEVICE_MODEL=$(adb -s "$SELECTED_DEVICE" shell getprop ro.product.model | tr -cd '[[:alnum:]]._-')
SELECTED_DEVICE_SDK=$(adb -s "$SELECTED_DEVICE" shell getprop ro.build.version.sdk | tr -cd '[[:alnum:]]._-')
}
android_device_unlocked(){
echo "📱 Checking screen status..."
adb -s "$1" shell dumpsys power | grep "mWakefulness=" | grep "Awake" &> /dev/null
return $?
}
android_get_foreground_package(){
android_get_device_sdk "$SELECTED_DEVICE"
if (( "$SDK" < 21 )); then
android_get_foreground_package_sdk_low
elif (( "$SDK" < 30 )); then
android_get_foreground_package_sdk_21_plus
elif (( "$SDK" < 31 )); then
android_get_foreground_package_sdk_30_plus
else
android_get_foreground_package_sdk_31_plus
fi
}
android_get_foreground_package_sdk_31_plus(){
adb -s "$SELECTED_DEVICE" shell dumpsys activity recents | grep 'Recent #0' | cut -d= -f3 | cut -d ':' -f2 | cut -d ' ' -f1
}
android_get_foreground_package_sdk_30_plus(){
adb -s "$SELECTED_DEVICE" shell dumpsys activity recents | grep 'Recent #0' | cut -d= -f6 | cut -d ':' -f2 | cut -d ' ' -f1
}
android_get_foreground_package_sdk_21_plus(){
adb -s "$SELECTED_DEVICE" shell dumpsys activity recents | grep 'Recent #0' | cut -d= -f2 | sed 's| .*||' | cut -d '/' -f1
}
android_get_foreground_package_sdk_low(){
adb -s "$SELECTED_DEVICE" shell dumpsys window windows | grep mCurrentFocus | cut -d'/' -f1 | rev | cut -d' ' -f1 | rev
}
android_get_storage_location_per_SDK(){
if (( "$1" < 30 )); then
DEVICE_FILE_PATH="/mnt/sdcard"
else
DEVICE_FILE_PATH="/storage/self/primary"
fi
}
android_is_package_installed() {
adb -s "$SELECTED_DEVICE" shell pm list packages -f | sed -e 's/.*=//' | grep -w "$1" &> /dev/null
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "🤷 Package \"$1\" is not installed"
exit 1
fi
}
android_detect_package_info(){
echo "🔍 Detecting package name..."
AAPPT_PATH=$(find ~/Library/Android/sdk -name 'aapt' | sort | tail -1)
PACKAGE_INFO=$($AAPPT_PATH dump badging "$1" > $TEMPORARY_FILE)
PACKAGE_NAME=$(cat $TEMPORARY_FILE | grep package:\ name);
PACKAGE_NAME=$(echo "$PACKAGE_NAME" | sed 's/^[^'\'']*'\''//');
PACKAGE_NAME=$(echo "$PACKAGE_NAME" | sed 's/'\''.*//');
APP_NAME=$(cat $TEMPORARY_FILE | grep application-label:)
APP_NAME=${APP_NAME#"application-label:"}
}
android_unlock_device(){
# arg1 = DEVICE_ID
# arg2 = MAX_RETRIES
MAX_RETRIES="$2"
UNLOCK_RETRIES=1
until android_device_unlocked "$1";
do
if [ "$UNLOCK_RETRIES" -le "$MAX_RETRIES" ]; then
echo "🔆 Screen on attempt $UNLOCK_RETRIES..."
((UNLOCK_RETRIES++));
adb -s "$1" shell input keyevent KEYCODE_POWER
adb -s "$1" shell input keyevent 82
sleep 1;
else
read -r -p "❌ Screen-wake failed, press ANY KEY after manual unlock..."
break
fi
done
delete_lastline
echo "📱 Screen unlocked..."
}
##############################################################################
### iOS
check_go_ios_version(){
if ! [ -x "$(command -v "go-ios")" ]; then
install_go_ios
else
#Here it complains about the missing agent/tunnel
GO_IOS_VERSION=$(go-ios --version)
#echo "Version of go-ios is: $GO_IOS_VERSION"
fi
}
install_go_ios(){
echo "⏳ Installing https://github.com/danielpaulus/go-ios..."
check_dependency "go"
CURRENT_DIR="$PWD"
TOOLKIT_IOS_LOCATION=$(dirname "$0")
git clone "https://github.com/danielpaulus/go-ios.git" "$TOOLKIT_IOS_LOCATION/go-ios" &> /dev/null
cd "$TOOLKIT_IOS_LOCATION/go-ios"
go build .
chmod +x "go-ios"
mv "go-ios" "go-ios-temp"
mv "go-ios-temp" ..
cd ..
rm -rf "$TOOLKIT_IOS_LOCATION/go-ios"
mv "go-ios-temp" "go-ios"
cd "$CURRENT_DIR"
}
prompt_xcode_launch(){
echo "❌ Developer image is not mounted and/or device screen is locked"
should_proceed "❓ Do you want to open Xcode to fix it? (make sure you have the latest version)"
open -a Xcode
echo "⏳ Waiting for Xcode to launch..."
while true ; do
sleep 2
if [[ $(ps aux | grep -v grep | grep -c Xcode) -ne 0 ]]; then
break
fi
done
sleep 4
osascript -e 'quit app "Xcode"'
}
ios_get_devices(){
check_go_ios_version
check_dependency "jq"
if [[ $(ps S | grep -c "go-ios tunnel") -ne 2 ]]; then
echo "♻️ Launching go-ios tunnel for maximum iOS compatibility (17+)"
nohup go-ios tunnel start --userspace --nojson >/dev/null 2>&1 &
GO_IOS_TUNNEL_PID=$!
#TODO save tunnel port and use it to avoid delays when trying various ports
disown $GO_IOS_TUNNEL_PID
sleep 1
fi
IOS_USB_DEVICES=( $(go-ios list --nojson | sort -u) )
}
ios_pair_device(){
go-ios pair --udid="$1" --nojson &> /dev/null
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
read -p "❌ Device is not paired - reconnect it, unlock screen, tap \"Trust\" and press ENTER..."
ios_pair_device "$1"
fi
}
ios_check_pairing(){
go-ios info --udid="$1" &> "$TEMPORARY_FILE"
if cat "$TEMPORARY_FILE" | grep -q 'UntrustedHostBUID' ; then
read -r -p "❌ Device is not paired - reconnect it, unlock screen, tap \"Trust\" and press ENTER..."
ios_pair_device "$1"
fi
if cat "$TEMPORARY_FILE" | grep -q 'could not retrieve PairRecord' ; then
read -r -p "❌ Device is not paired - reconnect it, unlock screen, tap \"Trust\" and press ENTER..."
ios_pair_device "$1"
fi
}
ios_check_developer_image(){
IS_MOUNTED=$((go-ios image list --udid="$1" --nojson) 2>&1)
if [[ $IS_MOUNTED == *"none"* ]]; then
prompt_xcode_launch
ios_check_developer_image "$1"
fi
}
ios_check_developer_image_and_pairing(){
ios_check_pairing "$1"
ios_check_developer_image "$1"
}
ios_device_info(){
ios_check_developer_image_and_pairing "$1"
MANUFACTURER="Apple"
go-ios info --udid="$1" > "$TEMPORARY_FILE"
MODEL=$(ios_translate_name "$(cat "$TEMPORARY_FILE" | jq -r '.HardwareModel')")
VERSION=$(cat "$TEMPORARY_FILE" | jq -r '.ProductVersion')
INFO=$(printf "%s) %s %s %s - %s" "$NUMBER" "$MANUFACTURER" "$MODEL" "$VERSION" "$ID")
}
ios_choose_device(){
check_for_update
ios_get_devices
if [ ${#IOS_USB_DEVICES[@]} -eq 0 ] #No device connected
then
echo "❌ No iOS devices detected"
exit 1
fi
if [ ${#IOS_USB_DEVICES[@]} -gt 1 ]
then
NUMBER=1
echo "📱 Available devices:"
for ID in "${IOS_USB_DEVICES[@]}"
do
ios_device_info "$ID"
echo "$INFO"
((NUMBER++))
done
read -r -p "📝 Select a device: " CHOICE
while :;
do
if [[ ! $CHOICE =~ $REGEX_NUMBER ]] || [ "$CHOICE" -le "0" -o "$CHOICE" -gt "${#IOS_USB_DEVICES[@]}" ]; then
echo -en "\033[1A\033[2K" #deletes last echoed line in terminal
read -r -p "🤷 Invalid input, try again: " CHOICE
else
break
fi
done
SELECTED_DEVICE=${IOS_USB_DEVICES[(($CHOICE-1))]}
else
SELECTED_DEVICE="${IOS_USB_DEVICES[0]}"
fi
}
ios_get_installed_package_list(){
echo "⏳ Getting third-party package list..."
INSTALLED_PACKAGES=($(go-ios apps --udid="$1" | jq -r '.[] | .CFBundleIdentifier'))
}
ios_get_all_package_list(){
echo "⏳ Getting all package list..."
INSTALLED_PACKAGES=($(go-ios apps --udid="$1" | jq -r '.[] | .CFBundleIdentifier'))
SYSTEM_PACKAGES=($(go-ios apps --udid="$1" --system | jq -r '.[] | .CFBundleIdentifier'))
ALL_PACKAGES=("${INSTALLED_PACKAGES[@]}" "${SYSTEM_PACKAGES[@]}")
}
ios_is_package_installed(){
ios_get_all_package_list "$SELECTED_DEVICE"
echo "${ALL_PACKAGES[*]}" | grep -w "$1" &> /dev/null
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "🤷 Package \"$1\" is not installed"
exit 1
fi
}
ios_translate_name(){
# Translations here https://www.theiphonewiki.com/wiki/Models
NAME=$1
case $NAME in
"Purple"*|"purple"*)
NAME="iPhone"
;;
"M68"*)
NAME="iPhone"
;;
"N90"*|"N92"*)
NAME="iPhone4"
;;
"N94"*)
NAME="iPhone4S"
;;
"N88"*)
NAME="iPhone3GS"
;;
"N82"*)
NAME="iPhone3G"
;;
"N71"*)
NAME="iPhone6S"
;;
"N66"*)
NAME="iPhone6SPlus"
;;
"N61"*)
NAME="iPhone6"
;;
"N56"*)
NAME="iPhone6Plus"
;;
"N51"*|"N53"*)
NAME="iPhone5S"
;;
"N48"*)
NAME="iPhone5C"
;;
"N41"*|"N42"*)
NAME="iPhone5"
;;
"D10"*)
NAME="iPhone7"
;;
"D11"*)
NAME="iPhone7Plus"
;;
"D20"*)
NAME="iPhone8"
;;
"D21"*)
NAME="iPhone8Plus"
;;
"D22"*|"Ferrari"*|"ferrari"*)
NAME="iPhoneX"
;;
"D32"*)
NAME="iPhoneXS"
;;
"D33"*)
NAME="iPhoneXSMax"
;;
"N104"*)
NAME="iPhone11"
;;
"D421"*)
NAME="iPhone11Pro"
;;
"D431"*)
NAME="iPhone11ProMax"
;;
"D52"*)
NAME="iPhone12Mini"
;;
"D53g"*)
NAME="iPhone12"
;;
"D53p"*)
NAME="iPhone12Pro"
;;
"D54"*)
NAME="iPhone12ProMax"
;;
"N84"*)
NAME="iPhoneXR"
;;
"N69"*)
NAME="iPhoneSEgen1"
;;
"D79"*)
NAME="iPhoneSEgen2"
;;
"D17"*)
NAME="iPhone13"
;;
"D16"*)
NAME="iPhone13Mini"
;;
"D63"*)
NAME="iPhone13Pro"
;;
"D64"*)
NAME="iPhone13ProMax"
;;
"J1"*)
NAME="iPad3gen"
;;
"J2"*)
NAME="iPad3gen"
;;
"J72"*)
NAME="iPadAir"
;;
"J82"*)
NAME="iPadAir2"
;;
"J217"*|"J218"*)
NAME="iPadAir3gen"
;;
"J307"*|"J308"*)
NAME="iPadAir4gen"
;;
"J85"*)
NAME="iPadMiniRetina"
;;
"J96"*)
NAME="iPadMini4"
;;
"J210"*|"J211"*)
NAME="iPadMini5gen"
;;
"J310"*|"J311"*)
NAME="iPadMini6gen"
;;
"J98"*|"J99"*|"J31"*|"J127"*|"J128"*|"J318"*|"J317"*|"J207"*|"J208"*)
NAME="iPadPro"
;;
"J120"*|"J121"*|"J417"*|"J418"*)
NAME="iPadPro2gen"
;;
"J320"*|"J321"*|"J517"*|"J518"*)
NAME="iPadPro3gen"
;;
"J420"*|"J421"*)
NAME="iPadPro4gen"
;;
"J522"*|"J523"*)
NAME="iPadPro5gen"
;;
"K48"*)
NAME="iPad"
;;
"K93"*|"K94"*|"K95"*)
NAME="iPad2"
;;
"P101"*|"P103"*)
NAME="iPad4gen"
;;
"P105"*|"P107"*)
NAME="iPadMini"
;;
"J71s"*|"J71t"*|"J72s"*|"J72t"*)
NAME="iPad5gen"
;;
"J71b"*|"J72b"*)
NAME="iPad6gen"
;;
"J171AP"*|"J172AP"*)
NAME="iPad7gen"
;;
"J171aAP"*|"J172aAP"*)
NAME="iPad8gen"
;;
"J181"*|"J182"*)
NAME="iPad9gen"
;;
esac
echo $NAME
}
##############################################################################
### Commons
check_adb_dependency(){
if ! [ -x "$(command -v "adb")" ]; then
echo "🤷 Android Debug Bridge required!"
should_proceed "🔄 Install via homebrew? (this may take a while)"
brew install --cask "android-platform-tools"
fi
}
check_dependency(){
if ! [ -x "$(command -v "$1")" ]; then
echo "💥 \"$1\" command required!"
should_proceed "🛒 Install via homebrew? (this may take a while)"
brew install "$1"
fi
}
check_for_update(){
TODAY=$(date +%Y-%m-%d)
if [ -f "$LAST_CHECK_DATE_FILE" ]; then
LAST_CHECK_DATE=$(cat "$LAST_CHECK_DATE_FILE")
else
echo "$TODAY" > "$LAST_CHECK_DATE_FILE"
fi
CURRENT_DIR="$PWD"
cd "$SCRIPT_LOCATION/.." || exit
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [[ "$CURRENT_BRANCH" == "master" && "$LAST_CHECK_DATE" != "$TODAY" ]]; then
echo "🔄 Checking for Mobile Toolkit update..."
echo "$TODAY" > "$LAST_CHECK_DATE_FILE"
git fetch origin &> /dev/null
git status -uno | grep "up to date" &> /dev/null
if [ $? -ne 0 ]; then
yes_or_no "🆕 Update available, download now?";
if [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]]; then
echo "⏬ Updating..."
git pull &> /dev/null
echo "✨ New features:"
cat "$SCRIPT_LOCATION"/../changelog.txt
echo
echo "✅ Update complete"
exit 0
fi
fi
fi
cd "$CURRENT_DIR" || exit
}
delete_lastline(){
echo -en "\033[1A\033[2K"
}
yes_or_no(){
read -r -n 1 -p "$1 [y/n] " RESPONSE
case "$RESPONSE" in
[yY])
;;
[nN])
;;
*)
echo
echo "🤷 Invalid option"
yes_or_no "$1"
;;
esac
echo
}
should_proceed(){
read -r -n 1 -p "$1 [y/n] " RESPONSE
case "$RESPONSE" in
[yY])
;;
*)
exit
;;
esac
echo
}
choose_number(){
MAX=$1
if [ -n "$2" ]; then
read -r -p "$2" CHOICE
else
read -r -p "📝 Choose number: " CHOICE
fi
while :;
do
if [[ -z $CHOICE || $CHOICE -le 0 || $CHOICE -gt $MAX ]]; then
delete_lastline
read -r -p "🤷 Invalid choice, try again: " CHOICE
else
((++CHOICE))
break
fi
done
}
check_url(){
URL=$1
if [[ $URL == "" ]]; then
read -r -p "📝 Insert web url: " URL
check_url "$URL"
else
case $1 in
'http://'*)
;;
'https://'*)
;;
*'://'*)
;;
*)
URL='http://'$URL
;;
esac
fi
}
abort(){
echo "$1"
exit 1
}
================================================
FILE: data/.gitignore
================================================
toolkit*
================================================
FILE: ios/icheckdevice
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
ios_choose_device
ios_device_info "$SELECTED_DEVICE"
GSM_URL='https://www.gsmarena.com/res.php3?sSearch='
MANUFACTURER=Apple
INFO=$(printf "%s %s - iOS %s" "$MANUFACTURER" "$MODEL" "$VERSION")
PHONE_URL=$GSM_URL$MODEL
echo "📱 $INFO - ID: $SELECTED_DEVICE"
should_proceed "🌐 Search for the device on GSMArena?"
open "$PHONE_URL"
================================================
FILE: ios/iconsole
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
echo "📋 Opening Console app..."
open -a Console
================================================
FILE: ios/iinstall
================================================
#!/bin/bash
trap "kill 0" SIGINT # Kill all spawned subprocesses on ctrl^c
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
install_app(){
echo "⌛️ Installing \"$2\" to $1..."
TEMPORARY_FILE="$TEMPORARY_FILE-$(date +%s)"
go-ios install --udid="$1" --path="$PWD/$2" &> "$TEMPORARY_FILE"
if grep -q 'err' "$TEMPORARY_FILE" ; then
echo "❌ Installation to $1 failed!"
echo "🤕 Uninstall existing version or troubleshoot the package"
echo "🔥 Error details: $(grep 'err' "$TEMPORARY_FILE" | jq -r '.err')"
exit 1
fi
echo "✅ Successfully installed to $1"
run_app "$1" "$PWD/$2"
}
run_app(){
echo "🚀 Launching \"$BUNDLE_ID\" on $1..."
TEMPORARY_FILE="$TEMPORARY_FILE-$(date +%s)"
go-ios launch "$BUNDLE_ID" --udid="$1" &> "$TEMPORARY_FILE"
if grep -q 'err' "$TEMPORARY_FILE" ; then
echo "❌ App launch failed!"
echo "🤕 Check if developer certificate is trusted in Settings"
echo "🔥 Error details: $(grep 'error' "$TEMPORARY_FILE" | jq -r '.error')"
exit 1
fi
}
check_args_valid(){
if [[ "$1" != "-a" ]]; then
FILE=$1
else
FILE=$2
fi
if [ ! -f "$PWD/$FILE" ] && [ ! -f "$FILE" ]; then
abort "🤷 Installation file not found!"
fi
if [[ "$FILE" != *".ipa" ]]; then
abort "🤷 Unsupported file!"
fi
}
get_bundle_id(){
echo "🔍 Detecting bundle ID..."
unzip "$1" &> /dev/null
APP_FILENAME=$(ls "$PWD"/Payload)
BUNDLE_ID=$(grep "$PWD/Payload/$APP_FILENAME/embedded.mobileprovision" -a -e "[.]com[.]" | sed 's/.[^.]*\.//' | sed 's/\<.*$//')
if [[ "$BUNDLE_ID" == "" ]]; then # Fallback for bundle identifiers containing "app" instead of "com"
BUNDLE_ID=$(grep "$PWD/Payload/$APP_FILENAME/embedded.mobileprovision" -a -e "[.]app[.]" | sed 's/.[^.]*\.//' | sed 's/\<.*$//')
fi
BUNDLE_ID=$(echo "$BUNDLE_ID" | head -n 1)
rm -rf "$PWD/Payload"
}
run(){
if [[ $1 == "-a" ]]; then
check_for_update
ios_get_devices
get_bundle_id "$2"
for ID in "${IOS_USB_DEVICES[@]}"
do
install_app "$ID" "$2" &
done
wait
else
ios_choose_device
get_bundle_id "$1"
install_app "$SELECTED_DEVICE" "$1"
fi
}
check_args_valid "$@"
run "$@"
================================================
FILE: ios/ikill
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
ios_choose_device
if [[ "$1" == "-s" ]]; then
PACKAGES=($(go-ios apps --udid="$SELECTED_DEVICE" --system | jq -r '.[] | .CFBundleIdentifier'))
elif [[ -n "$1" ]]; then
PACKAGE="$1"
ios_is_package_installed "$PACKAGE"
else
PACKAGES=($(go-ios apps --udid="$SELECTED_DEVICE" | jq -r '.[] | .CFBundleIdentifier'))
fi
if [ -z "$PACKAGE" ]; then
PACKAGES_LISTED=()
for P in "${PACKAGES[@]}" #removes trailing \r
do
P=${P%$'\r'}
PACKAGES_LISTED+=("$P")
done
if [ ${#PACKAGES_LISTED[@]} -eq 0 ]; then
echo "🤷 No third-party apps installed, use \"alaunch -s\" to list system packages"
exit 1
fi
echo "📋 Choose application to kill:"
select OPTION in "${PACKAGES_LISTED[@]}"
do
case $OPTION in
*) PACKAGE=$OPTION;break; ;;
esac
done
fi
echo "🔪 Killing $PACKAGE..."
go-ios kill "$PACKAGE" --udid="$SELECTED_DEVICE" &> /dev/null
echo "🚀 Relaunching the app..."
go-ios launch "$PACKAGE" &> /dev/null
================================================
FILE: ios/ilang
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
ios_choose_device
LANGUAGES=( "en" "cs" "sk" "ar" "ca" "hr" "da" "nl" "en-GB" "fi" "fr" "de" "el" "he" "hi" "hu" "id" "it" "ja" "ko" "ms" "nb" "pl" "pt" "pt-BR" "ro" "ru" "es" "sv" "th" "tr" "uk" "vi")
if [ -n "$1" ]; then
LANG="$1"
else
echo "📋 Choose desired language:"
select OPTION in "${LANGUAGES[@]}"
do
case $OPTION in
*) LANG=$OPTION;break; ;;
esac
done
fi
echo "💬 Setting language to \"$LANG\" (it might take a while)..."
go-ios lang --udid="$SELECTED_DEVICE" --setlang="$LANG" &> /dev/null
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "🤷 Supplied language \"$1\" is not supported"
exit 1
fi
================================================
FILE: ios/ilaunch
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
ios_choose_device
if [[ "$1" == "-s" ]]; then
PACKAGES=($(go-ios apps --udid="$SELECTED_DEVICE" --system | jq -r '.[] | .CFBundleIdentifier'))
elif [[ -n "$1" ]]; then
PACKAGE="$1"
ios_is_package_installed "$PACKAGE"
else
PACKAGES=($(go-ios apps --udid="$SELECTED_DEVICE" | jq -r '.[] | .CFBundleIdentifier'))
fi
if [ -z "$PACKAGE" ]; then
PACKAGES_LISTED=()
for P in "${PACKAGES[@]}" #removes trailing \r
do
P=${P%$'\r'}
PACKAGES_LISTED+=("$P")
done
if [ ${#PACKAGES_LISTED[@]} -eq 0 ]; then
echo "🤷 No third-party apps installed, use \"alaunch -s\" to list system packages"
exit 1
fi
echo "📋 Choose application to launch:"
select OPTION in "${PACKAGES_LISTED[@]}"
do
case $OPTION in
*) PACKAGE=$OPTION;break; ;;
esac
done
fi
echo "🚀 Launching \"$PACKAGE\"..."
go-ios launch "$PACKAGE" --udid="$SELECTED_DEVICE" &> /dev/null
================================================
FILE: ios/ilog
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
ios_choose_device
echo "📜 Device log:"
go-ios syslog --udid="$SELECTED_DEVICE" --nojson
================================================
FILE: ios/ioptions
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
ios_choose_device
echo "🔨 Launching system settings..."
go-ios launch "com.apple.Preferences" --udid="$SELECTED_DEVICE" &> /dev/null
================================================
FILE: ios/iquicktime
================================================
#!/bin/bash
echo "📹 Opening QuickTime..."
osascript <<EOD
tell application "QuickTime Player"
activate
set newMovieRecording to new movie recording
end tell
tell application "System Events" to tell process "QuickTime Player"
click button 2 of window 1
end tell
return
EOD
================================================
FILE: ios/ireboot
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
ios_choose_device
should_proceed "🔌 Do you really want to reboot $SELECTED_DEVICE?"
echo "🔄 Restarting the device..."
go-ios reboot --udid="$SELECTED_DEVICE" &> /dev/null
================================================
FILE: ios/irecord
================================================
#!/bin/bash
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
trap 'ctrlc $@' 1 2 3 6 15
RECORDING=false
cd ~/Desktop || exit
ctrlc(){
osascript -e 'quit app "QuickTime Player"'
if $RECORDING ; then
compress_video "$FILENAME"
echo "✅ Saved into ~/Desktop/$FILENAME"
fi
exit
}
check_videosnap_dependency(){ #TODO refactor when videosnap available via Homberew
if ! [ -x "$(command -v "videosnap")" ]; then
echo "💥 \"videosnap\" command required!"
should_proceed "🛒 Install via GitHub? (download and install \"videosnap-0.0.7.pkg\")"
open "https://github.com/matthutchinson/videosnap/releases/download/v0.0.7/videosnap-0.0.7.pkg"
exit 1
fi
}
start_quicktime(){
echo "🎬 Initializing QuickTime (webcam LED might turn on)..."
osascript <<EOD
tell application "QuickTime Player"
set newMovieRecording to new movie recording
set miniaturized of window 1 to true
end tell
EOD
}
pick_recording_device(){
ios_choose_device
ios_device_info "$SELECTED_DEVICE"
DEVICE_NAME=$(go-ios devicename --udid="$SELECTED_DEVICE" --nojson)
FILENAME="$MANUFACTURER-$MODEL-iOS$VERSION-$(date +%Y-%m-%d-%H-%M-%S).mp4"
}
start_recording(){
RECORDING=true
echo "📹 Recording screen on $SELECTED_DEVICE ($DEVICE_NAME), stop it using ctrl^c"
videosnap -p High -d "$DEVICE_NAME" "$FILENAME" &> /dev/null
}
compress_video(){
if test -f "$1" ; then
echo "📦 Compressing video..."
ffmpeg -i "$1" "LQ-$1" -hide_banner -loglevel error #ultra basic ffmpeg compression
rm "$1" && mv "LQ-$1" "$1"
else
echo "❌ Video not captured possibly due to short recording time..."
osascript -e 'quit app "QuickTime Player"'
exit 1
fi
}
if uname -m | grep -q arm64 ; then
echo "🤕 This script is currently not working on M1 based macs"
echo "🔗 See https://github.com/matthutchinson/videosnap/issues/24"
echo "🩹 You can use \"iquicktime\" temporarily instead"
exit 1
fi
check_videosnap_dependency
check_dependency "ffmpeg"
start_quicktime
pick_recording_device
start_recording
================================================
FILE: ios/iscreenshot
================================================
#!/bin/bash
trap "kill 0" SIGINT # Kill all spawned subprocesses on ctrl^c
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
screenshot(){
ios_device_info "$1"
FILENAME="$MANUFACTURER-$MODEL-iOS$VERSION-$(date +%Y-%m-%d-%H-%M-%S).png"
echo "📸 Saving screenshot into $FILENAME..."
go-ios screenshot --udid="$1" --output="$HOME/Desktop/$FILENAME" &> /dev/null
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "🤷 Screenshot failed, error code: $EXIT_CODE"
fi
}
screenshot_all(){
check_for_update
ios_get_devices
for ID in "${IOS_USB_DEVICES[@]}"
do
screenshot "$ID" &
done
wait
}
if [ "$1" == "-a" ];
then
screenshot_all
else
ios_choose_device
screenshot "$SELECTED_DEVICE"
fi
================================================
FILE: ios/isimulator
================================================
#!/bin/bash
# shellcheck disable=SC1007
# ignore irrelevant warning "remove space after ="
TOOLKIT_LOCATION=$(dirname "$0")
source "$TOOLKIT_LOCATION"/../common_tools
LOCAL_SIMULATOR_LIST=$TOOLKIT_LOCATION/../data/toolkit_simulator_list.txt
help(){
if [[ $1 != "" ]]; then
echo "🤷 Unknown option: $1"
else
echo "🤷 Argument missing"
fi
echo -e "Use one of the following options:\\n start - choose and launch installed simulator\\n screenshot <filename> - save screenshot to Desktop\\n record <filename> - save screen recording to Desktop\\n paste <text> - insert text into pasteboard\\n url <url> - open link in web browser\\n logs - print simulator logs\\n battery <0-100> - set battery level\\n time <hh:mm> - set time\\n import <file> - import photo or video into gallery\\n wipe - wipe all simulator data"
}
import_simulator_list(){
xcrun simctl list -v devices | grep -i booted | sed 's/ (Booted) //g' > "$LOCAL_SIMULATOR_LIST"
RUNNING_SIMULATOR_COUNT=$(wc -l < "$LOCAL_SIMULATOR_LIST")
}
choose_simulator(){
read -r -p "📝 Choose: " SIMULATOR_INDEX
SIMULATOR_ID=$(sed "$SIMULATOR_INDEX"!d "$LOCAL_SIMULATOR_LIST")
if [[ $SIMULATOR_INDEX == "" || $SIMULATOR_ID != *"("* ]]; then
delete_lastline
choose_simulator
fi
SIMULATOR_ID=$(echo "$SIMULATOR_ID" | sed 's/.*(\(.*\))/\1/')
}
choose_running_simulator(){
import_simulator_list
if [[ $RUNNING_SIMULATOR_COUNT -le 0 ]]; then
echo "❌ No running simulators"
yes_or_no "❓ Do you want to start one?"
if [[ "$RESPONSE" == "y" || "$RESPONSE" == "Y" ]];
then
start_simulator
fi
exit
elif [[ $RUNNING_SIMULATOR_COUNT -eq 1 ]]; then
SIMULATOR_ID=$(sed 1!d "$LOCAL_SIMULATOR_LIST" | sed 's/.*(\(.*\))/\1/')
return
fi
echo "📱 Available simulators:"
nl "$LOCAL_SIMULATOR_LIST"
choose_simulator
}
start_simulator(){
echo "⏳ Getting iOS simulator list..."
rm -f "$LOCAL_SIMULATOR_LIST"
xcrun simctl list | grep -i "shutdown\\|booted\\|-- iOS\\|-- tvOS\\|-- watchOS" | grep -v "unavailable\\|Watch:\\|Phone:" | sed 's/ (Shutdown) //g' | sed 's/ (Booted) //g' >> "$LOCAL_SIMULATOR_LIST"
echo "📱 Available:"
nl "$LOCAL_SIMULATOR_LIST"
choose_simulator
echo "🚀 Launching simulator..."
xcrun simctl boot "$SIMULATOR_ID"
open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/
rm "$LOCAL_SIMULATOR_LIST"
}
open_url(){
check_url "$1"
echo "🌎 Opening link in a web browser..."
xcrun simctl openurl "$SIMULATOR_ID" "$URL" &> /dev/null
}
launch_app(){
if [[ $1 == "" || $1 != "com."*"."* ]]; then
read -r -p "📝 Enter bundle id: " BUNDLE_ID
launch_app "$BUNDLE_ID"
else
echo "🚀 Launching the app..."
xcrun simctl launch "$SIMULATOR_ID" "$1"
fi
}
insert_clipboard(){
if [[ $1 == "" ]]; then
read -r -p "📝 Enter pasteboard text: " TEXT
insert_clipboard "$TEXT"
else
echo "📥 Inserting text into clipboard..."
echo "$1" | xcrun simctl pbcopy "$SIMULATOR_ID" &> /dev/null
fi
}
wipe_contents(){
should_proceed "💣 Wipe all simulator data?"
echo "🚫 Shutting down the device..."
xcrun simctl shutdown "$SIMULATOR_ID"
echo "🔥 Wiping data..."
xcrun simctl erase "$SIMULATOR_ID"
echo "🚀 Booting..."
xcrun simctl boot "$SIMULATOR_ID"
}
record_screen(){
echo "📹 Recording screen on $SIMULATOR_ID, stop it with ctrl^c"
if [ -z "$1" ] ; then
FILENAME="Simulator-$(date +%Y-%m-%d-%H-%M-%S).mp4"
else
FILENAME="$1.mp4"
fi
if ! xcrun simctl io "$SIMULATOR_ID" recordVideo "$HOME/DESKTOP/$FILENAME"; then
echo "❌ Recording failed!"
else
echo "✅ Video saved to ~/Desktop/$FILENAME"
fi
}
take_screenshot(){
echo "📸 Taking screenshot on $SIMULATOR_ID"
if [ -z "$1" ] ; then
FILENAME="Simulator-$(date +%Y-%m-%d-%H-%M-%S).png"
else
FILENAME=$1
fi
xcrun simctl io "$SIMULATOR_ID" screenshot "$HOME/Desktop/$FILENAME" &> /dev/null
echo "✅ Screenshot saved to ~/Desktop/$FILENAME"
}
import_file(){
if [ -z "$1" ] ; then
echo "🤷 No file for import, use - isimulator import <file>"
exit
fi
echo "⏬ Importing file to $SIMULATOR_ID..."
xcrun simctl addmedia "$SIMULATOR_ID" "$PWD/$1"
echo "✅ File imported successfully"
}
print_logs(){
echo "📜 Simulator logs:"
xcrun simctl spawn "$SIMULATOR_ID" log stream --level=debug
}
check_xcode_version(){
if [ "$(FirefoxmdlsVersion= mdls -name kMDItemVersion /Applications/Xcode.app | tr -d "." | grep -oE '[0-9]+')" -lt 110 ]; then
should_proceed "🔄 Xcode 11 or later is required, open App Store?"
open -a "App Store"
exit 1
fi
}
set_battery_level(){
check_xcode_version
if [[ -z "$1" ]]; then
read -r -p "📝 Enter battery level: " LEVEL
set_battery_level "$LEVEL"
else
echo "🔋 Setting battery level to: $1"
xcrun simctl status_bar "$SIMULATOR_ID" override --batteryLevel "$1" # --batteryState charged
fi
}
set_time(){
check_xcode_version
if [[ -z "$1" ]]; then
read -r -p "📝 Enter battery level: " TIME
set_time "$TIME"
else
xcrun simctl status_bar "$SIMULATOR_ID" override --time "$1"
fi
}
check_for_update
case $1 in
'start')
import_simulator_list
start_simulator "$2"
;;
'screenshot')
choose_running_simulator
take_screenshot "$2"
;;
'record')
choose_running_simulator
record_screen "$2"
;;
'import')
choose_running_simulator
import_file "$2"
;;
'url')
choose_running_simulator
open_url "$2"
;;
'battery')
choose_running_simulator
set_battery_level "$2"
;;
'time')
choose_running_simulator
set_time "$2"
;;
'launch')
choose_running_simulator
launch_app "$2"
;;
'paste')
choose_running_simulator
insert_clipboard "$2"
;;
'logs'|'log')
choose_running_simulator
print_logs "$2"
;;
'wipe')
choose_running_simulator
wipe_contents
;;
*)
help "$1"
choose_running_simulator
;;
esac
================================================
FILE: ios/iuninstall
================================================
#!/bin/bash
trap "kill 0" SIGINT # Kill all spawned subprocesses on ctrl^c
LOCATION=$(dirname "$0")
source "$LOCATION"/../common_tools
IGNORED_PACKAGES=( "com.apple.TestFlight" "motif.FramerPreview" "com.figma.FigmaMirror" "com.invisionapp.InVisionApp-iOS" "com.8bit.bitwarden" )
ios_choose_device
select_option(){
echo "📋 Choose package number:"
select OPTION in "${INSTALLED_PACKAGES[@]}"
do
case $OPTION in
*) PACKAGE=$OPTION;break; ;;
esac
done
if [[ -z $PACKAGE ]]; then
echo "❌ Invalid option picked, retry"
select_option
fi
}
uninstall_package(){
PACKAGE="$1"
echo "${INSTALLED_PACKAGES[*]}" | grep -w "$PACKAGE" &> /dev/null || { echo "🤷 Package \"$PACKAGE\" not installed"; return 1; }
echo "${IGNORED_PACKAGES[*]}" | grep -w "$PACKAGE" &> /dev/null && { echo "❌ Package \"$PACKAGE\" is whitelisted"; return 1; }
echo "🔥 Uninstalling \"$PACKAGE\"..."
go-ios uninstall --udid="$SELECTED_DEVICE" "$PACKAGE" &> /dev/null
return 0
}
uninstall_all(){
tput setaf 1
should_proceed "💣 Delete all third-party apps on $SELECTED_DEVICE?"
tput sgr0
for PKG in "${INSTALLED_PACKAGES[@]}"
do
uninstall_package "$PKG" &
done
wait
}
handle_arguments(){
if [[ "$1" == "-w" ]]; then
uninstall_all
elif [[ -n "$1" ]]; then
uninstall_package "$1"
fi
if [ -z "$1" ]; then
if [ ${#INSTALLED_PACKAGES[@]} -eq 0 ]; then
echo "🤷 Nothing to uninstall"
exit
fi
select_option
uninstall_package "$PACKAGE"
fi
}
ios_get_installed_package_list "$SELECTED_DEVICE"
handle_arguments "$@"
echo "✅ Done"
gitextract_fh0eifjr/
├── .github/
│ ├── CONTRIBUTING.md
│ ├── ISSUE_TEMPLATE.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── count_lines.yml
│ └── shellcheck.yml
├── .gitignore
├── LICENCE.md
├── README.md
├── android/
│ ├── aanimationspeed
│ ├── aappinfo
│ ├── abounds
│ ├── abuildproject
│ ├── acamera
│ ├── acheckdevice
│ ├── acontrol
│ ├── adarkmode
│ ├── aemulator
│ ├── aerase
│ ├── afontscale
│ ├── agoogleplay
│ ├── ainstall
│ ├── akill
│ ├── alaunch
│ ├── alog
│ ├── aoptions
│ ├── apaste
│ ├── apermissionreset
│ ├── apowerbutton
│ ├── areboot
│ ├── arecord
│ ├── ascreenshot
│ ├── aservices
│ ├── atalkback
│ ├── atestmonkey
│ ├── atestmonkeykill
│ ├── auninstall
│ ├── aurl
│ ├── awipe
│ └── awireless
├── changelog.txt
├── common_tools
├── data/
│ └── .gitignore
└── ios/
├── icheckdevice
├── iconsole
├── iinstall
├── ikill
├── ilang
├── ilaunch
├── ilog
├── ioptions
├── iquicktime
├── ireboot
├── irecord
├── iscreenshot
├── isimulator
└── iuninstall
Condensed preview — 56 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (107K chars).
[
{
"path": ".github/CONTRIBUTING.md",
"chars": 645,
"preview": "## 💬 Contributing\n\nIf you consider contributing to this repository, please first discuss the desired changes via issue, "
},
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 257,
"preview": "### 🐞 Whats wrong\n~Describe requested functionality or existing bug~\n### 🌈 Desired state\n~Describe desired code and func"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 310,
"preview": "## ⚠️ Progress checklist\n- [ ] 🏗 **Features fully completed**\n- [ ] 🔬 **Shellcheck issues resolved**\n- [ ] 🔨 **All chang"
},
{
"path": ".github/workflows/count_lines.yml",
"chars": 444,
"preview": "name: Count lines\non: [push]\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v2\n "
},
{
"path": ".github/workflows/shellcheck.yml",
"chars": 514,
"preview": "name: 'Shellcheck'\non: push\njobs:\n shellcheck:\n name: Shellcheck\n runs-on: ubuntu-latest\n steps:\n - uses: a"
},
{
"path": ".gitignore",
"chars": 58,
"preview": "*DS_Store\nios/go-ios\nios/nohup.out\nios/selfidentity.plist\n"
},
{
"path": "LICENCE.md",
"chars": 1091,
"preview": "MIT License\n\nCopyright (c) 2019 IntergalacticPenguin - Adam Svoboda\n\nPermission is hereby granted, free of charge, to an"
},
{
"path": "README.md",
"chars": 17953,
"preview": "\n<div id='section-id-2'/>\n\n## What is its purpose?\n🛠 **Control Android & iOS dev"
},
{
"path": "android/aanimationspeed",
"chars": 1045,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\n\nset_animation_speed(){\n adb -s \"$SELECTED_DEVI"
},
{
"path": "android/aappinfo",
"chars": 1207,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nif [ -n \"$1\" ];\nthen\n "
},
{
"path": "android/abounds",
"chars": 769,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nredraw_screen(){\n adb -s"
},
{
"path": "android/abuildproject",
"chars": 1948,
"preview": "#!/bin/bash\n# shellcheck disable=SC2181\n#ignore indirect exit code check at line 54\n\nLOCATION=$(dirname \"$0\")\nsource \"$L"
},
{
"path": "android/acamera",
"chars": 226,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\necho \"📷 Opening camera ap"
},
{
"path": "android/acheckdevice",
"chars": 5322,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\n\nGSM_URL='https://www.gsmarena.com/res.php3?sSea"
},
{
"path": "android/acontrol",
"chars": 283,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\n\ncheck_dependency \"scrcpy\"\ncheck_adb_dependency\n"
},
{
"path": "android/adarkmode",
"chars": 711,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nturn_off_darkmode(){\n ec"
},
{
"path": "android/aemulator",
"chars": 5127,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nLOCAL_EMULATOR_LIST=$LOCATION/../data/toolkit_em"
},
{
"path": "android/aerase",
"chars": 464,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nif [[ \"$1\" != \"\" ]];\nthen"
},
{
"path": "android/afontscale",
"chars": 590,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\n\nset_font_scale(){\n adb -s \"$SELECTED_DEVICE\" s"
},
{
"path": "android/agoogleplay",
"chars": 551,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nsearch_gp(){\n APP_NAME=\""
},
{
"path": "android/ainstall",
"chars": 1473,
"preview": "#!/bin/bash\ntrap \"kill 0\" SIGINT # Kill all spawned subprocesses on ctrl^c\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/."
},
{
"path": "android/akill",
"chars": 503,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nif [[ \"$1\" != \"\" ]];\nthen"
},
{
"path": "android/alaunch",
"chars": 986,
"preview": "#!/bin/bash\nsource \"$(dirname \"$0\")\"/../common_tools\nandroid_choose_device\n\nif [[ \"$1\" == \"-s\" ]]; then\n PACKAGES=($(ad"
},
{
"path": "android/alog",
"chars": 605,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nfilter_by_package(){\n an"
},
{
"path": "android/aoptions",
"chars": 4610,
"preview": "#!/bin/bash\nTOOLKIT_LOCATION=$(dirname \"$0\")\nsource \"$TOOLKIT_LOCATION\"/../common_tools\nandroid_choose_device\n\nLOCAL_SET"
},
{
"path": "android/apaste",
"chars": 2337,
"preview": "#!/bin/bash\n# shellcheck disable=SC1001\n#ignore regex - sign occurence\ntrap \"kill 0\" SIGINT # Kill all spawned subproces"
},
{
"path": "android/apermissionreset",
"chars": 245,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\ntput setaf 1\nshould_proce"
},
{
"path": "android/apowerbutton",
"chars": 317,
"preview": "#!/bin/bash\nsource \"$(dirname \"$0\")\"/../common_tools\nandroid_choose_device\n\n# Reference for key events - https://gist.gi"
},
{
"path": "android/areboot",
"chars": 242,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nshould_proceed \"🔌 Do you "
},
{
"path": "android/arecord",
"chars": 1746,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\n\n# Trap signal handling\ntrap 'ctrlc \"$@\"' 1 2 3 "
},
{
"path": "android/ascreenshot",
"chars": 887,
"preview": "#!/bin/bash\ntrap \"kill 0\" SIGINT # Kill all spawned subprocesses on ctrl^c\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/."
},
{
"path": "android/aservices",
"chars": 894,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nSERVICE_LIST=$LOCATION/../data/toolkit_android_services.txt\nsource \"$LOCATION\"/../c"
},
{
"path": "android/atalkback",
"chars": 704,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nturn_off_talkback(){\n ec"
},
{
"path": "android/atestmonkey",
"chars": 2731,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\ntrap 'ctrlc' 1 2 3 6 15\n\nctrlc(){\n if $RUNNING_"
},
{
"path": "android/atestmonkeykill",
"chars": 486,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\ntrap \"kill 0\" SIGINT # Kill all spawned subproce"
},
{
"path": "android/auninstall",
"chars": 2335,
"preview": "#!/bin/bash\ntrap \"kill 0\" SIGINT # Kill all spawned subprocesses on ctrl^c\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/."
},
{
"path": "android/aurl",
"chars": 711,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\n\nopen_url(){\n check_url \"$2\"\n echo \"🌎 Opening "
},
{
"path": "android/awipe",
"chars": 660,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nandroid_choose_device\n\nprompt(){\n tput setaf 1\n"
},
{
"path": "android/awireless",
"chars": 1075,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\n\nget_device_ip(){\n android_choose_device\n DEVI"
},
{
"path": "changelog.txt",
"chars": 675,
"preview": " 🎉 This is a new (experimental) version 1.4.1!\n\n 📹 arecord was fixed to work with latest scrcpy version\n If you a"
},
{
"path": "common_tools",
"chars": 16052,
"preview": "#!/bin/bash\n# shellcheck disable=SC2034\n\n##############################################################################\n"
},
{
"path": "data/.gitignore",
"chars": 8,
"preview": "toolkit*"
},
{
"path": "ios/icheckdevice",
"chars": 405,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nios_choose_device\nios_device_info \"$SELECTED_DEV"
},
{
"path": "ios/iconsole",
"chars": 121,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\n\necho \"📋 Opening Console app...\"\nopen -a Console"
},
{
"path": "ios/iinstall",
"chars": 2173,
"preview": "#!/bin/bash\ntrap \"kill 0\" SIGINT # Kill all spawned subprocesses on ctrl^c\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/."
},
{
"path": "ios/ikill",
"chars": 1025,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nios_choose_device\n\nif [[ \"$1\" == \"-s\" ]]; then\n "
},
{
"path": "ios/ilang",
"chars": 707,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nios_choose_device\nLANGUAGES=( \"en\" \"cs\" \"sk\" \"ar"
},
{
"path": "ios/ilaunch",
"chars": 965,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nios_choose_device\n\nif [[ \"$1\" == \"-s\" ]]; then\n "
},
{
"path": "ios/ilog",
"chars": 161,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\n\nios_choose_device\necho \"📜 Device log:\"\ngo-ios s"
},
{
"path": "ios/ioptions",
"chars": 206,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nios_choose_device\n\necho \"🔨 Launching system sett"
},
{
"path": "ios/iquicktime",
"chars": 276,
"preview": "#!/bin/bash\necho \"📹 Opening QuickTime...\"\n\nosascript <<EOD\ntell application \"QuickTime Player\"\n\tactivate\n\tset newMovieRe"
},
{
"path": "ios/ireboot",
"chars": 244,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\nios_choose_device\n\nshould_proceed \"🔌 Do you real"
},
{
"path": "ios/irecord",
"chars": 2037,
"preview": "#!/bin/bash\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/../common_tools\ntrap 'ctrlc $@' 1 2 3 6 15\n\nRECORDING=false\ncd ~"
},
{
"path": "ios/iscreenshot",
"chars": 727,
"preview": "#!/bin/bash\ntrap \"kill 0\" SIGINT # Kill all spawned subprocesses on ctrl^c\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/."
},
{
"path": "ios/isimulator",
"chars": 5948,
"preview": "#!/bin/bash\n# shellcheck disable=SC1007\n# ignore irrelevant warning \"remove space after =\"\n\nTOOLKIT_LOCATION=$(dirname \""
},
{
"path": "ios/iuninstall",
"chars": 1602,
"preview": "#!/bin/bash\ntrap \"kill 0\" SIGINT # Kill all spawned subprocesses on ctrl^c\nLOCATION=$(dirname \"$0\")\nsource \"$LOCATION\"/."
}
]
About this extraction
This page contains the full source code of the IGPenguin/mobile-toolkit GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 56 files (94.1 KB), approximately 29.9k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.