├── .gitignore ├── LICENSE ├── adb-all.sh ├── adb.service ├── add-android-licenses-validation.sh ├── cp-env-to-properties.sh ├── disable-animation.sh ├── install-android-dependencies.sh ├── login.sh ├── readme.md ├── run-tests-on-firebase.py ├── take-screenshot.sh ├── test-deeplink.sh └── wait-for-device.sh /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/linux,macos 3 | 4 | ### Linux ### 5 | *~ 6 | 7 | # temporary files which can be created if a process still has a handle open of a deleted file 8 | .fuse_hidden* 9 | 10 | # KDE directory preferences 11 | .directory 12 | 13 | # Linux trash folder which might appear on any partition or disk 14 | .Trash-* 15 | 16 | # .nfs files are created when an open file is removed but is still being accessed 17 | .nfs* 18 | 19 | 20 | ### macOS ### 21 | *.DS_Store 22 | .AppleDouble 23 | .LSOverride 24 | 25 | # Icon must end with two \r 26 | Icon 27 | # Thumbnails 28 | ._* 29 | # Files that might appear in the root of a volume 30 | .DocumentRevisions-V100 31 | .fseventsd 32 | .Spotlight-V100 33 | .TemporaryItems 34 | .Trashes 35 | .VolumeIcon.icns 36 | .com.apple.timemachine.donotpresent 37 | # Directories potentially created on remote AFP share 38 | .AppleDB 39 | .AppleDesktop 40 | Network Trash Folder 41 | Temporary Items 42 | .apdisk 43 | 44 | # End of https://www.gitignore.io/api/linux,macos -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Daniel Gomez Rico 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /adb-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Run adb on every connected device 4 | # 5 | 6 | adb devices | while read line 7 | do 8 | if [ ! "$line" = "" ] && [ `echo $line | awk '{print $2}'` = "device" ] 9 | then 10 | device=`echo $line | awk '{print $1}'` 11 | echo "$device $@ ..." 12 | adb -s $device $@ || true 13 | fi 14 | done 15 | -------------------------------------------------------------------------------- /adb.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Android Debug Server Daemon 3 | 4 | [Service] 5 | Type=forking 6 | User=root 7 | ExecStart=/usr/bin/adb start-server 8 | ExecStop=/usr/bin/adb kill-server 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /add-android-licenses-validation.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Manually add android licenses acceptance 4 | # source: https://discuss.bitrise.io/t/android-sdk-license-issue/97/2 5 | # 6 | 7 | 8 | mkdir -p $ANDROID_HOME/licenses 9 | echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > $ANDROID_HOME/licenses/android-sdk-license 10 | echo "d56f5187479451eabf01fb78af6dfcb131a6481e" >> $ANDROID_HOME/licenses/android-sdk-license 11 | -------------------------------------------------------------------------------- /cp-env-to-properties.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copy ALL env variables to gradle properties file 4 | # 5 | # You may want another output file then use PROPERTIES_FILE_PATH variable for that 6 | # 7 | # Note: you can use System.getenv("VAR_NAME") instead of this if you dont need to create a local .properties files 8 | # in your project. 9 | # 10 | 11 | PROPERTIES_FILE_PATH=gradle.properties 12 | 13 | set +x // dont print the next lines on run script 14 | 15 | printenv | tr ' ' '\n' > $PROPERTIES_FILE_PATH 16 | 17 | set -x 18 | -------------------------------------------------------------------------------- /disable-animation.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Disable all animations on connected devices with adb 4 | # 5 | 6 | adb_all () { 7 | adb devices | while read line 8 | do 9 | if [ ! "$line" = "" ] && [ `echo $line | awk '{print $2}'` = "device" ] 10 | then 11 | device=`echo $line | awk '{print $1}'` 12 | echo "$device $@ ..." 13 | adb -s $device $@ || true 14 | fi 15 | done 16 | } 17 | 18 | adb_all shell "settings put global window_animation_scale 0" 19 | adb_all shell "settings put global transition_animation_scale 0" 20 | adb_all shell "settings put global animator_duration_scale 0" 21 | -------------------------------------------------------------------------------- /install-android-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Install required dependencies 4 | # sdkmanager can be found in $ANDROID_HOME/tools/bin/sdkmanager 5 | # 6 | 7 | # Accept licences 8 | # src http://vgaidarji.me/blog/2017/05/31/automatically-accept-android-sdkmanager-licenses/ 9 | /usr/bin/expect -c ' 10 | set timeout -1; 11 | spawn '"${ANDROID_HOME}"'/tools/bin/sdkmanager --licenses; 12 | expect { 13 | "y/N" { exp_send "y\r" ; exp_continue } 14 | eof 15 | } 16 | ' 17 | 18 | echo "--------------------------------------------------------" 19 | echo "Trying to update dependencies with tools/bin/sdkmanager: " 20 | echo "--------------------------------------------------------" 21 | 22 | for I in "platforms;android-26" \ 23 | "platforms;android-25" \ 24 | "platforms;android-23" \ 25 | "platforms;android-21" \ 26 | "build-tools;26.0.1" \ 27 | "tools" \ 28 | "platform-tools" \ 29 | "extras;google;m2repository" \ 30 | "extras;android;m2repository" \ 31 | "extras;google;google_play_services" \ 32 | "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2"\ 33 | "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.2"; do 34 | echo "-> " $I 35 | sdkmanager $I 36 | done 37 | 38 | sdkmanager --update 39 | 40 | echo "--------------------------------------------------------" 41 | -------------------------------------------------------------------------------- /login.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Helper to write user and pwd to login faster. 4 | # 5 | 6 | adb shell input text "d@d.d" # user 7 | adb shell input keyevent 66 # next 8 | adb shell input text "d" # user 9 | 10 | adb shell input keyevent 66 # next 11 | adb shell input keyevent 66 # enter -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Android Scripts 2 | 3 | Some scripts to make life easier working with android projects, to install dependencies on CI 4 | or create `gradle.properties` files from env variables, etc... -------------------------------------------------------------------------------- /run-tests-on-firebase.py: -------------------------------------------------------------------------------- 1 | # 2 | # Filter some items based on the current day of the week and send to firebase to run tests on them. 3 | # Check https://firebase.google.com/docs/test-lab/command-line 4 | # 5 | 6 | import commands 7 | from datetime import date 8 | import random 9 | 10 | class Device: 11 | def __init__(self, model_id, model_name, android_versions): 12 | self.model_id = model_id.strip() 13 | self.model_name = model_name.strip() 14 | self.android_versions = android_versions.strip().split(",") 15 | 16 | def read_devices(count): 17 | left_index_limit = (date.today().isocalendar()[2] * count) - count + 7 # devices info starts on 7 on output 18 | list_models_command = "gcloud firebase test android models list" 19 | full_output = commands.getstatusoutput(list_models_command)[1] 20 | split_data = full_output.split("\n") 21 | 22 | found_devices = [] 23 | 24 | print("--> Output from firebase:") 25 | print(full_output) 26 | 27 | right_index_limit = left_index_limit + count 28 | if (right_index_limit >= len(split_data) - 1): 29 | right_index_limit = len(split_data) - 1 30 | 31 | for i in range(left_index_limit, right_index_limit): 32 | split_device = split_data[i].split("|") 33 | device = Device(split_device[1], split_device[2], split_device[6]) 34 | found_devices.append(device) 35 | 36 | print("\n--> Selected found_devices \n") 37 | for d in found_devices: 38 | print("-----> {0}, {1}, {2}".format(d.model_id, d.model_name, d.android_versions)) 39 | 40 | return found_devices 41 | 42 | def build_firebase_test_command(devices): 43 | apk_path="app/build/outputs/apk" 44 | run_tests_command = "gcloud firebase test android run --type instrumentation --use-orchestrator --app {0}/debug/app-debug.apk --test {0}/androidTest/debug/app-debug-androidTest.apk \\".format(apk_path) 45 | 46 | for device in devices: 47 | android_version = random.choice(device.android_versions) 48 | run_tests_command += "\n--device model={0},version={1},locale=en,orientation=portrait \\".format(device.model_id, android_version) 49 | 50 | return run_tests_command[:-1] # to remove '\' on the last item 51 | 52 | def run_command(command): 53 | print("\n--> Running: \n'${0}'".format(command)) 54 | output = commands.getstatusoutput(command) 55 | print(output[1]) 56 | 57 | 58 | run_command("gcloud config set project ") 59 | devices = read_devices(8) 60 | runTestsCommand = build_firebase_test_command(devices) 61 | 62 | # Run connectedCheck to build the required apks, dont worry if no devices are connected for this 63 | run_command("./gradlew app:assembleDebug -PenableAnalytics") 64 | run_command("./gradlew app:assembleAndroidTest -PenableAnalytics") 65 | run_command(runTestsCommand) -------------------------------------------------------------------------------- /take-screenshot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Take an screenshot into "screenshots/" using current date/time as file name. 4 | # src: https://gist.github.com/FokkeZB/86713457bf84808a12a6 5 | # 6 | 7 | adb shell screencap -p | perl -pe "s/\x0D\x0A/\x0A/g" > "screenshots/$(date +%Y%m%d-%H%M%S).png" -------------------------------------------------------------------------------- /test-deeplink.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Send the needed event through adb to launch a deeplink. 4 | # 5 | # 6 | 7 | COLOR_PURPLE='\033[0;35m' 8 | COLOR_GREEN='\033[0;32m' 9 | COLOR_OFF='\033[0m' 10 | 11 | DEEP_LINKS=( "http://myapp.com/feed/504" \ 12 | "http://myapp.com/profile/" \ 13 | ) 14 | 15 | print_step () { 16 | echo "${COLOR_PURPLE}\n---> $1: ${COLOR_OFF}" 17 | } 18 | 19 | print_item () { 20 | echo "- [${COLOR_GREEN}$1${COLOR_OFF}]: $2" 21 | } 22 | 23 | print_step "Supported deep links" 24 | for i in "${!DEEP_LINKS[@]}"; do 25 | print_item $i "${DEEP_LINKS[$i]}" 26 | done 27 | 28 | print_step "Enter the index of the wanted deep link to test" 29 | read INDEX 30 | 31 | SELECTED_DEEP_LINK=${DEEP_LINKS[$INDEX]} 32 | 33 | print_step "Selected" 34 | echo "${SELECTED_DEEP_LINK}" 35 | 36 | print_step "Sending..." 37 | adb shell am start -a android.intent.action.VIEW \ 38 | -c android.intent.category.BROWSABLE \ 39 | -d $SELECTED_DEEP_LINK 40 | 41 | 42 | -------------------------------------------------------------------------------- /wait-for-device.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | adb_all () { 3 | adb devices | while read line 4 | do 5 | if [ ! "$line" = "" ] && [ `echo $line | awk '{print $2}'` = "device" ] 6 | then 7 | device=`echo $line | awk '{print $1}'` 8 | echo "$device $@ ..." 9 | adb -s $device $@ || true 10 | fi 11 | done 12 | } 13 | 14 | awake_screen() { 15 | ANDROID_SDK_VERSION="$(adb shell getprop ro.build.version.sdk)" 16 | 17 | if [ "$ANDROID_SDK_VERSION" -gt 19 ]; then 18 | echo "Awaking android device." 19 | adb_all shell input keyevent 224 # KEYCODE_WAKEUP just for < Android 19 20 | else 21 | echo "Checking if its needed to turn on the screen." 22 | 23 | adb shell dumpsys power | grep -i 'Display Power: state=OFF' 24 | if [ $? -eq 0 ]; then 25 | echo "Screen is off. Wake up the phone" 26 | adb shell input keyevent 26 # KEYCODE_POWER will turn of if it is turned on 27 | else 28 | echo "Screen is on so no action required." 29 | fi 30 | fi 31 | } 32 | 33 | awake_screen 34 | adb_all shell input keyevent 3 # HOME 35 | adb_all shell input keyevent 4 # BACK 36 | adb_all shell input keyevent 4 # BACK 37 | adb_all shell input keyevent 4 # BACK 38 | 39 | adb_all wait-for-device 40 | adb_all shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;' 41 | --------------------------------------------------------------------------------