Skip to content

Commit 1c39e9b

Browse files
mstangeMarcLeclair
authored andcommitted
Add support for screen recording with VIEW intent.
You can run it as follows: ``` python3 ./record_adb.py --mode applink --package org.mozilla.fenix --url https://theme-crave-demo.myshopify.com/ --output shopify-app-link.mp4 ``` This also adds support for launching the app with the launcher activity, as an alternative to simulating user touch. Simulating user touch to start an app can be tricky if you're installing apps in an automated fashion (e.g. for CI testing) and can't ensure that the app icon is placed in a specific place on the screen. ``` python3 ./record_adb.py --mode launch --package org.mozilla.fenix --output launch.mp4 ```
1 parent 4187327 commit 1c39e9b

File tree

1 file changed

+64
-26
lines changed

1 file changed

+64
-26
lines changed

record_adb.py

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,30 @@
66
import argparse
77
import subprocess
88
import time
9-
import os
10-
import signal
119

1210

13-
# This script records the phone either through intent or simulating user touch
14-
# for the purpose of generating videos that are consistent.
15-
# The consistency allows us to compare said video.
11+
# This script records a video of the phone screen and triggers app activity in one of three ways:
12+
# - mode == "touch": Simulates user touch at the specified coordinates
13+
# - mode == "launch": Launches an app with the .MainActivity
14+
# - mode == "applink": Launches an app with the VIEW intent and a URL
15+
# We can then compare the recorded videos across browsers.
1616
def main(args):
17-
method = args.input
17+
mode = args.mode
1818
device_path = './sdcard/output.mp4'
1919

20-
if method in 'touch' and (args.coordinate_x is None or args.coordinate_y is None):
21-
print('--touch requires --coordinate-x <coordinate> --coordinate-y <coordinate> to use the touch input')
20+
if mode == 'touch' and (args.coordinate_x is None or args.coordinate_y is None):
21+
print('--mode touch requires --coordinate-x <coordinate> --coordinate-y <coordinate> '
22+
'to use the touch input. Enable the touch coordinate overlay in the Android debug '
23+
'settings to find the right coordinates.')
24+
sys.exit()
25+
26+
if mode == 'launch' and (args.package is None):
27+
print('--mode launch requires --package argument')
28+
sys.exit()
29+
30+
if mode == 'applink' and (args.url is None or args.package is None):
31+
print('--mode applink requires --url and --package arguments')
2232
sys.exit()
23-
# if method in 'intent' and args.package is None:
24-
# print('--intent requires --package <your.package.name>')
25-
# sys.exit()
2633

2734
kill_existing_processes("org.mozilla")
2835
kill_existing_processes("com.android.chrome")
@@ -34,27 +41,57 @@ def main(args):
3441
record_process = subprocess.Popen(['adb', 'shell', 'screenrecord', '--bugreport'] + [device_path])
3542
time.sleep(3)
3643

37-
# TODO allow intent trigger
38-
# if method in 'intent':
39-
# record_with_intent(args.package)
40-
# else:
41-
simulate_input(args.coordinate_x, args.coordinate_y)
44+
if mode == "touch":
45+
simulate_input(args.coordinate_x, args.coordinate_y)
46+
elif mode == "launch":
47+
# The launch activity name depends on the app.
48+
# To find the right activity name, run `adb shell pm dump <packagename>` and look for an
49+
# activity with `Action: "android.intent.action.MAIN"` and
50+
# `Category: "android.intent.category.LAUNCHER"`.
51+
if args.package.startswith("org.mozilla"):
52+
activity = args.package + "/.App"
53+
else:
54+
# Assume Chrome
55+
activity = args.package + "/com.google.android.apps.chrome.Main"
56+
record_with_activity(activity)
57+
else:
58+
# The app link activity name depends on the app.
59+
# To find the right activity name, run `adb shell pm dump <packagename>` and look for an
60+
# activity with `Action: "android.intent.action.VIEW"` and `Category: "android.intent.category.BROWSABLE"`.
61+
if args.package.startswith("org.mozilla"):
62+
activity = args.package + "/org.mozilla.fenix.IntentReceiverActivity"
63+
else:
64+
# Assume Chrome
65+
activity = args.package + "/com.google.android.apps.chrome.IntentDispatcher"
66+
record_with_view_intent(activity, args.url)
67+
4268
time.sleep(5)
4369
record_process.kill()
4470
time.sleep(5)
4571
pull_recording(device_path, args.output)
4672

47-
# def record_with_intent(package):
48-
# activity_start = subprocess.Popen(['adb', 'shell', 'am', 'start-activity', package +'/.App',
49-
# '--ez finishonboarding true'])
50-
# activity_start.wait()
51-
5273

5374
def simulate_input(x, y):
5475
tap_event = subprocess.Popen(['adb', 'shell', 'input', 'tap'] + [str(x), str(y)])
5576
tap_event.wait()
5677

5778

79+
def record_with_activity(activity):
80+
activity_start = subprocess.Popen(
81+
['adb', 'shell', 'am', 'start-activity',
82+
'-a', 'android.intent.action.VIEW', activity]
83+
)
84+
activity_start.wait()
85+
86+
87+
def record_with_view_intent(activity, url):
88+
activity_start = subprocess.Popen(
89+
['adb', 'shell', 'am', 'start-activity', '-d', url,
90+
'-a', 'android.intent.action.VIEW', activity]
91+
)
92+
activity_start.wait()
93+
94+
5895
def pull_recording(device_path, output):
5996
proc = subprocess.Popen(['adb', 'pull', device_path, output])
6097
proc.wait()
@@ -79,13 +116,14 @@ def kill_existing_processes(package_substr):
79116

80117
if __name__ == "__main__":
81118
parser = argparse.ArgumentParser(description='record video through adb',
82-
usage=('record_adb.py --input <touch> --coordinate-x and --cordinate-y '
119+
usage=('record_adb.py --mode touch -cx 660 -cy 2222 '
83120
'--output <name.mp4>'))
84-
# add intent later
85-
parser.add_argument('-i', '--input', required=True, choices=("touch"))
121+
122+
parser.add_argument('-m', '--mode', required=True, choices=("touch", "launch", "applink"))
86123
parser.add_argument('-cx', '--coordinate-x', type=int, help="X position of touch event")
87124
parser.add_argument('-cy', '--coordinate-y', type=int, help="Y position of touch event")
88-
# parser.add_argument('-p','--package', type=str, help='package name to record if intent is used')
89-
parser.add_argument('-o', '--output', type=str, help="output name of file")
125+
parser.add_argument('-p', '--package', type=str, help="App package for launch / applink")
126+
parser.add_argument('-u', '--url', type=str, help="applink URL")
127+
parser.add_argument('-o', '--output', required=True, type=str, help="output file path")
90128
args = parser.parse_args()
91129
main(args)

0 commit comments

Comments
 (0)