flick 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +39 -30
- data/bin/flick +21 -5
- data/flick.gemspec +4 -1
- data/lib/flick.rb +6 -1
- data/lib/flick/android.rb +63 -32
- data/lib/flick/checker.rb +30 -4
- data/lib/flick/ios.rb +36 -13
- data/lib/flick/log.rb +17 -7
- data/lib/flick/manager.rb +41 -0
- data/lib/flick/screenshot.rb +10 -6
- data/lib/flick/simple_daemon.rb +18 -12
- data/lib/flick/system.rb +36 -16
- data/lib/flick/version.rb +1 -1
- data/lib/flick/video.rb +37 -42
- metadata +57 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb64107c4d21b8fc509321fdc0d98763e3e376e6
|
4
|
+
data.tar.gz: 154aa4c74efa4fead2f6cdd5880c7b71602607ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07dba93a03a97b5a725bc98afca7e3cda8c66138aab7ae1f15efaa6f3caf4a43a01599344117130f04f54391ef6c40629178b66e714c5693e0d1dacd7f026c43
|
7
|
+
data.tar.gz: 7e400657a20828488546d0229b251fe3bbe7a125c25aee55eb23aba1cc41fdc275b0d2aa6bd4c76c1c04295194e535fdd2bddab91a18486db83214081abd991e
|
data/README.md
CHANGED
@@ -14,6 +14,7 @@ Features
|
|
14
14
|
* Falls back to screenshot recording if video record is not available.
|
15
15
|
* Video record android emulators and **real** iOS devices.
|
16
16
|
* Takes a screenshot every 0.5 seconds (default), then combines the screenshots into a single mp4 or gif.
|
17
|
+
* Android pulls only unique (default) screenshots from devices/emulators. e.g. A 1 minute test run might convert to only 30 seconds of video based on unique images. You can change this by passing `-q false` to pull all images instead.
|
17
18
|
* iOS example [here](https://www.dropbox.com/s/4pjhhmnsx9gj5pi/ios-flick-example.mp4?dl=0)
|
18
19
|
* Android Emulator example [here](https://www.dropbox.com/s/gwunrvgzxkny13z/android-flick-example.mp4?dl=0)
|
19
20
|
* Flick auto selects device when only one device is connected, per platform.
|
@@ -28,17 +29,24 @@ So I created Flick to work for my needs, and included a couple other tools I use
|
|
28
29
|
|
29
30
|
If you're looking for high-quality video, then this wouldn't be the tool for you. Take a look at this great tool [androidtool-mac](https://github.com/mortenjust/androidtool-mac) instead.
|
30
31
|
|
31
|
-
Prerequisites
|
32
|
+
Prerequisites
|
32
33
|
-------------
|
33
34
|
#### System Tools
|
34
35
|
* Install ffmpeg. [OSX](https://trac.ffmpeg.org/wiki/CompilationGuide/MacOSX)
|
35
36
|
* ```$ brew install ffmpeg```
|
37
|
+
* Install ffmpeg. [Windows](https://ffmpeg.zeranoe.com/builds/)
|
38
|
+
* Download either the 32-bit or 64-bit static versions.
|
39
|
+
* Extract the zip file and move the ffmpeg folder somewhere else.
|
40
|
+
* Add the ffmpeg bin location to your PATH user variables. e.g. C:\ffmpeg\bin
|
36
41
|
* Install mp4box. [OSX](http://hunterford.me/compiling-mp4box-on-mac-os-x/)
|
37
42
|
* ```$ brew install mp4box```
|
43
|
+
* Install mp4box. [Windows](http://www.videohelp.com/software/MP4Box)
|
44
|
+
* Run the gpac-0.6.2-DEV-rev634-gd2332cb-master-x(64 or 32 bit).exe
|
45
|
+
* Select to install only the MP4Box component.
|
38
46
|
|
39
47
|
#### Android
|
40
48
|
* Install [SDK Tools](http://developer.android.com/sdk/installing/index.html?pkg=tools).
|
41
|
-
* SDK tools are added to your $PATH. [OSX](http://stackoverflow.com/questions/5526470/trying-to-add-adb-to-path-variable-osx)
|
49
|
+
* SDK tools are added to your $PATH. [OSX](http://stackoverflow.com/questions/5526470/trying-to-add-adb-to-path-variable-osx)
|
42
50
|
* Enable [USB Debugging](https://www.kingoapp.com/root-tutorials/how-to-enable-usb-debugging-mode-on-android.htm) on your device(s).
|
43
51
|
* Emulator or Devices have approximately 1GB of [sdcard space](http://developer.android.com/tools/help/mksdcard.html).
|
44
52
|
|
@@ -60,54 +68,55 @@ Usage:
|
|
60
68
|
$ flick --help
|
61
69
|
|
62
70
|
DESCRIPTION:
|
63
|
-
|
71
|
+
|
64
72
|
A CLI to capture screenshots, video, logs, and device info for Android (Devices & Emulators) and iOS (Devices).
|
65
|
-
|
73
|
+
|
66
74
|
COMMANDS:
|
67
|
-
|
68
|
-
help Display global or [command] help documentation
|
69
|
-
info Get device information
|
70
|
-
log Get device log output
|
71
|
-
screenshot Take a screenshot
|
72
|
-
video Record video
|
73
|
-
|
75
|
+
|
76
|
+
help Display global or [command] help documentation
|
77
|
+
info Get device information
|
78
|
+
log Get device log output
|
79
|
+
screenshot Take a screenshot
|
80
|
+
video Record video
|
81
|
+
|
74
82
|
GLOBAL OPTIONS:
|
75
|
-
|
76
|
-
-h, --help
|
83
|
+
|
84
|
+
-h, --help
|
77
85
|
Display help documentation
|
78
|
-
|
79
|
-
-v, --version
|
86
|
+
|
87
|
+
-v, --version
|
80
88
|
Display version information
|
81
|
-
|
82
|
-
-t, --trace
|
89
|
+
|
90
|
+
-t, --trace
|
83
91
|
Display backtrace when an error occurs
|
84
92
|
|
85
|
-
* See usage examples in:
|
86
|
-
|
87
93
|
`$ flick info --help`
|
88
|
-
|
94
|
+
|
89
95
|
$ flick info -p (ios or android)
|
90
96
|
$ flick info -p (ios or android) -s true -o $HOME
|
91
|
-
|
92
|
-
|
97
|
+
|
98
|
+
|
93
99
|
`$ flick log --help`
|
94
|
-
|
100
|
+
|
95
101
|
$ flick log -a start -p (ios or android) -o $HOME -n iosLog
|
96
102
|
$ flick log -a stop -p (ios or android)
|
97
103
|
|
98
104
|
`$ flick screenshot --help`
|
99
|
-
|
100
|
-
$ flick screenshot -p (ios or android)
|
101
|
-
|
105
|
+
|
106
|
+
$ flick screenshot -p (ios or android) -o $HOME -n myImage
|
107
|
+
|
102
108
|
`$ flick video --help`
|
103
|
-
|
109
|
+
|
104
110
|
$ flick video -a start -p (ios or android)
|
105
111
|
$ flick video -a stop -p (ios or android) -o /output -n myVideo -f gif
|
106
112
|
$ flick video -a start -p android -u emulator-5554 -c 1000
|
107
113
|
$ flick video -a stop -p android -u emulator-5554
|
108
114
|
|
109
|
-
|
110
|
-
|
115
|
+
`$ flick manager --help`
|
116
|
+
$ flick manager -a install -p (ios or android) -f ~/myApp/my-awesome-app.apk or .app
|
117
|
+
$ flick maanger -a uninstall -p (ios or android) -n com.package.name
|
118
|
+
|
119
|
+
##Demo
|
111
120
|
<img src="https://www.dropbox.com/s/9be37gc1c2dlxa6/flick-demo.gif?raw=1" width="600">
|
112
121
|
|
113
122
|
## Contributing
|
@@ -119,7 +128,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/isonic
|
|
119
128
|
* Setup Flick android for cross platform os's (windows & linux)
|
120
129
|
* Add screenshot capture for iOS Simulators.
|
121
130
|
* Multithread the screenshot and pull process.
|
122
|
-
* Look into capturing video
|
131
|
+
* Look into capturing video for iOS similar to [this](https://github.com/mortenjust/androidtool-mac/blob/9347cd9aeca9e7370e323d12f862bc5d8beacc25/AndroidTool/IOSDeviceHelper.swift#L56)
|
123
132
|
|
124
133
|
## License
|
125
134
|
|
data/bin/flick
CHANGED
@@ -28,7 +28,7 @@ command :video do |c|
|
|
28
28
|
:unique => true, #defaults to pulling only unique screenshots. Speeds up pulling process from device.
|
29
29
|
:format => "mp4",
|
30
30
|
:outdir => Dir.pwd #defaults to save in current directory.
|
31
|
-
|
31
|
+
|
32
32
|
Video.new(options.default).run
|
33
33
|
end
|
34
34
|
end
|
@@ -45,11 +45,11 @@ command :screenshot do |c|
|
|
45
45
|
c.action do |args, options|
|
46
46
|
options.default \
|
47
47
|
:outdir => Dir.pwd #defaults to save in current directory.
|
48
|
-
|
48
|
+
|
49
49
|
Screenshot.new(options.default).screenshot
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
command :log do |c|
|
54
54
|
c.syntax = 'flick log [options]'
|
55
55
|
c.summary = 'Get device log output'
|
@@ -63,7 +63,7 @@ command :log do |c|
|
|
63
63
|
c.action do |args, options|
|
64
64
|
options.default \
|
65
65
|
:outdir => Dir.pwd #defaults to save in current directory.
|
66
|
-
|
66
|
+
|
67
67
|
Log.new(options.default).run
|
68
68
|
end
|
69
69
|
end
|
@@ -81,7 +81,23 @@ command :info do |c|
|
|
81
81
|
options.default \
|
82
82
|
:save => false,
|
83
83
|
:outdir => Dir.pwd #defaults to save in current directory.
|
84
|
-
|
84
|
+
|
85
85
|
Info.new(options.default).info
|
86
86
|
end
|
87
|
+
end
|
88
|
+
|
89
|
+
command :manager do |c|
|
90
|
+
c.syntax = 'flick manager [options]'
|
91
|
+
c.summary = 'Manage apps on devices'
|
92
|
+
c.description = c.summary
|
93
|
+
c.example 'description', "flick manager -a install -p android -f ~/my-awesome-app.apk\n flick manager -a uninstall -p ios -n com.viber"
|
94
|
+
c.option '-a', '--action ACTION', String, 'Set action: install or uninstall'
|
95
|
+
c.option '-p', '--platform PLATFORM', String, 'Set platform: android or ios'
|
96
|
+
c.option '-u', '--udid UDID', String, 'Set device UDID.'
|
97
|
+
c.option '-f', '--file FILE', String, 'Set the apk or app file location path.'
|
98
|
+
c.option '-n', '--name NAME', String, 'Set the package name.'
|
99
|
+
c.action do |args, options|
|
100
|
+
|
101
|
+
Manager.new(options.default).run
|
102
|
+
end
|
87
103
|
end
|
data/flick.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.bindir = "bin"
|
25
25
|
spec.executables = ["flick"]
|
26
26
|
spec.require_paths = ["lib"]
|
27
|
-
|
27
|
+
|
28
28
|
spec.add_development_dependency "bundler", "~> 1.10"
|
29
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
30
30
|
spec.add_development_dependency "rspec", '~> 3.4', '>= 3.4.0'
|
@@ -34,4 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_dependency "json", '~> 1.8', '>= 1.8.3'
|
35
35
|
spec.add_dependency "wannabe_bool", "~> 0.5.0"
|
36
36
|
spec.add_dependency "awesome_print", '~> 1.6', '>= 1.6.1'
|
37
|
+
spec.add_dependency "os", "~> 0.9.6"
|
38
|
+
spec.add_dependency "sys-proctable", '~> 1.1', '>= 1.1.1'
|
39
|
+
spec.add_dependency "apktools", '~> 0.7.1', '>= 0.7.1'
|
37
40
|
end
|
data/lib/flick.rb
CHANGED
@@ -3,6 +3,10 @@ require 'json'
|
|
3
3
|
require 'parallel'
|
4
4
|
require 'wannabe_bool'
|
5
5
|
require 'awesome_print'
|
6
|
+
require 'os'
|
7
|
+
require 'tempfile'
|
8
|
+
require 'sys/proctable'
|
9
|
+
require 'apktools/apkxml'
|
6
10
|
|
7
11
|
require "flick/version"
|
8
12
|
require_relative "./flick/android"
|
@@ -13,4 +17,5 @@ require_relative "./flick/log"
|
|
13
17
|
require_relative "./flick/screenshot"
|
14
18
|
require_relative "./flick/simple_daemon"
|
15
19
|
require_relative "./flick/system"
|
16
|
-
require_relative "./flick/video"
|
20
|
+
require_relative "./flick/video"
|
21
|
+
require_relative "./flick/manager"
|
data/lib/flick/android.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Flick
|
2
2
|
class Android
|
3
3
|
attr_accessor :flick_dir, :dir_name, :udid, :name, :outdir, :unique, :limit, :specs
|
4
|
-
|
4
|
+
|
5
5
|
def initialize options
|
6
6
|
Flick::Checker.system_dependency "adb"
|
7
7
|
self.flick_dir = "#{Dir.home}/.flick"
|
@@ -14,43 +14,43 @@ module Flick
|
|
14
14
|
self.specs = options.fetch(:specs, false)
|
15
15
|
create_flick_dirs
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def create_flick_dirs
|
19
19
|
Flick::System.setup_system_dir flick_dir
|
20
|
-
%x(adb -s #{udid} shell 'mkdir #{dir_name}'
|
20
|
+
%x(adb -s #{udid} shell 'mkdir #{dir_name}')
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def clear_files
|
24
|
-
%x(adb -s #{udid} shell rm '#{dir_name}/*' >> /dev/null 2>&1)
|
25
24
|
Flick::System.clean_system_dir flick_dir, udid
|
25
|
+
%x(adb -s #{udid} shell rm '#{dir_name}/*')
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def devices
|
29
29
|
(`adb devices`).scan(/\n(.*)\t/).flatten
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def devices_connected?
|
33
|
-
|
33
|
+
devices.any?
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def check_for_devices
|
37
37
|
unless devices_connected?
|
38
|
-
puts "\nNo Devices Connected or Authorized!!!\nMake sure at least one device (emulator/simulator) is
|
38
|
+
puts "\nNo Devices Connected or Authorized!!!\nMake sure at least one device (emulator/simulator) is connected!\n".red
|
39
39
|
abort
|
40
40
|
end
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def get_device_udid opts_hash
|
44
44
|
devices_connected?
|
45
45
|
return unless opts_hash[:udid].nil?
|
46
46
|
if devices.size == 1
|
47
|
-
devices
|
47
|
+
devices.first
|
48
48
|
else
|
49
49
|
puts "\nMultiple android devices '#{devices}' found.\nSpecify a single UDID. e.g. -u #{devices.sample}\n".red
|
50
50
|
abort unless specs
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
def info
|
55
55
|
specs = { os: "ro.build.version.release", manufacturer: "ro.product.manufacturer", model: "ro.product.model", sdk: "ro.build.version.sdk" }
|
56
56
|
hash = { udid: udid }
|
@@ -61,54 +61,85 @@ module Flick
|
|
61
61
|
hash
|
62
62
|
end
|
63
63
|
|
64
|
+
def install app_path
|
65
|
+
%x(adb -s #{udid} install -r #{app_path})
|
66
|
+
end
|
67
|
+
|
68
|
+
def uninstall package
|
69
|
+
if app_installed? package
|
70
|
+
%x(adb -s #{udid} shell pm uninstall #{package})
|
71
|
+
else
|
72
|
+
puts packages
|
73
|
+
puts "\n#{package} was not found on device #{udid}! Please choose one from above. e.g. #{packages.sample}\n".red
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def app_version app_path
|
78
|
+
manifest(app_path).find {|x| x.name == "versionName" }["value"]
|
79
|
+
end
|
80
|
+
|
81
|
+
def package_name app_path
|
82
|
+
manifest(app_path).find {|x| x.name == "package" }["value"]
|
83
|
+
end
|
84
|
+
|
85
|
+
def manifest app_path
|
86
|
+
data = ApkXml.new app_path
|
87
|
+
data.parse_xml("AndroidManifest.xml", false, true)
|
88
|
+
data.xml_elements[0].attributes
|
89
|
+
end
|
90
|
+
|
91
|
+
def app_installed? package
|
92
|
+
packages.include? "package:#{package}"
|
93
|
+
end
|
94
|
+
|
95
|
+
def packages
|
96
|
+
%x(adb -s #{udid} shell pm list packages).split
|
97
|
+
end
|
98
|
+
|
64
99
|
def os_version
|
65
|
-
|
100
|
+
%x(adb -s #{udid} shell getprop "ro.build.version.release").strip.to_f
|
66
101
|
end
|
67
|
-
|
102
|
+
|
68
103
|
def screenshot name
|
69
104
|
%x(adb -s #{udid} shell screencap #{dir_name}/#{name}.png)
|
70
105
|
end
|
71
|
-
|
106
|
+
|
72
107
|
def log name
|
73
108
|
%x(adb -s #{udid} logcat -v long > #{outdir}/#{name}.log)
|
74
109
|
end
|
75
|
-
|
110
|
+
|
76
111
|
def recordable?
|
77
|
-
(
|
112
|
+
%x(adb -s #{udid} shell "ls /system/bin/screenrecord").strip == "/system/bin/screenrecord"
|
78
113
|
end
|
79
|
-
|
114
|
+
|
80
115
|
def screenrecord name
|
81
116
|
%x(adb -s #{udid} shell screenrecord --time-limit #{limit} --size 720x1280 #{dir_name}/#{name}.mp4)
|
82
117
|
end
|
83
|
-
|
118
|
+
|
84
119
|
def pull_file file, dir
|
85
|
-
%x(adb -s #{udid} pull #{file} #{dir}
|
120
|
+
%x(adb -s #{udid} pull #{file} #{dir})
|
86
121
|
end
|
87
|
-
|
88
|
-
def unique_files
|
122
|
+
|
123
|
+
def unique_files type
|
89
124
|
if os_version < 6.0
|
90
125
|
command = "md5"
|
91
126
|
else
|
92
127
|
command = "md5sum"
|
93
128
|
end
|
94
|
-
files =
|
129
|
+
files = %x(adb -s #{udid} shell "#{command} #{dir_name}/#{type}-#{udid}*")
|
95
130
|
hash = files.split("\r\n").map { |file| { md5: file.match(/(.*) /)[1].strip, file: file.match(/ (.*)/)[1].strip } }
|
96
131
|
hash.uniq! { |e| e[:md5] }
|
97
132
|
hash.map { |file| file[:file] }
|
98
133
|
end
|
99
|
-
|
100
|
-
def pull_files
|
134
|
+
|
135
|
+
def pull_files type
|
101
136
|
if unique
|
102
|
-
files = unique_files
|
137
|
+
files = unique_files type
|
103
138
|
else
|
104
|
-
files = (
|
139
|
+
files = %x(adb -s #{udid} shell "ls #{dir_name}/#{type}-#{udid}*").split("\r\n")
|
105
140
|
end
|
106
141
|
return if files.empty?
|
107
142
|
Parallel.map(files, in_threads: 10) { |file| pull_file file, flick_dir }
|
108
143
|
end
|
109
|
-
|
110
|
-
def screenshots_exist?
|
111
|
-
(`adb -s #{udid} shell "ls #{dir_name}/#{udid}-*.png | wc -l"`).to_i > 0
|
112
|
-
end
|
113
144
|
end
|
114
145
|
end
|
data/lib/flick/checker.rb
CHANGED
@@ -1,13 +1,24 @@
|
|
1
1
|
module Flick
|
2
2
|
module Checker
|
3
|
+
def self.which(cmd)
|
4
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
5
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
6
|
+
exts.each { |ext|
|
7
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
8
|
+
return exe if File.executable?(exe) && !File.directory?(exe)
|
9
|
+
}
|
10
|
+
end
|
11
|
+
return nil
|
12
|
+
end
|
13
|
+
|
3
14
|
def self.system_dependency dep
|
4
|
-
program =
|
15
|
+
program = self.which dep
|
5
16
|
if program.empty?
|
6
17
|
puts "\n#{dep} was not found. Please ensure you have installed #{dep} and it's in your $PATH\n".red
|
7
18
|
abort
|
8
19
|
end
|
9
20
|
end
|
10
|
-
|
21
|
+
|
11
22
|
def self.platform platform
|
12
23
|
platforms = ["android","ios"]
|
13
24
|
unless platforms.include? platform
|
@@ -15,7 +26,7 @@ module Flick
|
|
15
26
|
abort
|
16
27
|
end
|
17
28
|
end
|
18
|
-
|
29
|
+
|
19
30
|
def self.action action
|
20
31
|
actions = ["start","stop"]
|
21
32
|
unless actions.include? action
|
@@ -23,7 +34,22 @@ module Flick
|
|
23
34
|
abort
|
24
35
|
end
|
25
36
|
end
|
26
|
-
|
37
|
+
|
38
|
+
def self.manager option
|
39
|
+
options = ["install","uninstall"]
|
40
|
+
unless options.include? option
|
41
|
+
puts "\nPlease specify a valid option #{options}. e.g. flick <job> -a #{options.sample} -p ios\n".red
|
42
|
+
abort
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.file_exists? file
|
47
|
+
unless File.exists? file
|
48
|
+
puts "\n#{file} does not exist! Please specify a valid file path.".red
|
49
|
+
abort
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
27
53
|
def self.format format
|
28
54
|
formats = ["mp4","gif"]
|
29
55
|
unless formats.include? format
|
data/lib/flick/ios.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Flick
|
2
2
|
class Ios
|
3
3
|
attr_accessor :flick_dir, :udid, :name, :outdir, :todir, :specs
|
4
|
-
|
4
|
+
|
5
5
|
def initialize options
|
6
6
|
Flick::Checker.system_dependency "idevice_id"
|
7
7
|
self.flick_dir = "#{Dir.home}/.flick"
|
@@ -12,26 +12,26 @@ module Flick
|
|
12
12
|
self.specs = options.fetch(:specs, false)
|
13
13
|
create_flick_dirs
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def create_flick_dirs
|
17
17
|
Flick::System.setup_system_dir flick_dir
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def devices
|
21
21
|
(`idevice_id -l`).split.uniq.map { |d| d }
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def devices_connected?
|
25
|
-
|
25
|
+
devices.any?
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def check_for_devices
|
29
29
|
unless devices_connected?
|
30
30
|
puts "\nNo iPhone or iPad Devices Connected!!!\nMake sure at least one REAL device is connected!\n".red
|
31
31
|
abort
|
32
|
-
end
|
32
|
+
end
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def get_device_udid opts_hash
|
36
36
|
check_for_devices
|
37
37
|
return unless opts_hash[:udid].nil?
|
@@ -42,7 +42,7 @@ module Flick
|
|
42
42
|
abort unless specs
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
def info
|
47
47
|
specs = { os: "ProductVersion", name: "DeviceName", arc: "CPUArchitecture", type: "DeviceClass", sdk: "ProductType" }
|
48
48
|
hash = { udid: udid }
|
@@ -52,23 +52,46 @@ module Flick
|
|
52
52
|
end
|
53
53
|
hash
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def recordable?
|
57
57
|
false
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
def clear_files
|
61
61
|
Flick::System.clean_system_dir flick_dir, udid
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def screenshot name
|
65
65
|
Flick::Checker.system_dependency "idevicescreenshot"
|
66
66
|
%x(idevicescreenshot -u #{udid} #{todir}/#{name}.png)
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
def log name
|
70
70
|
Flick::Checker.system_dependency "idevicesyslog"
|
71
71
|
%x(idevicesyslog -u #{udid} > #{outdir}/#{name}.log)
|
72
72
|
end
|
73
|
+
|
74
|
+
def install app_path
|
75
|
+
Flick::Checker.system_dependency "ideviceinstaller"
|
76
|
+
%x(ideviceinstaller -u #{udid} -i #{app_path})
|
77
|
+
end
|
78
|
+
|
79
|
+
def uninstall package
|
80
|
+
Flick::Checker.system_dependency "ideviceinstaller"
|
81
|
+
if app_installed? package
|
82
|
+
%x(ideviceinstaller -u #{udid} -U #{package})
|
83
|
+
else
|
84
|
+
puts packages
|
85
|
+
puts "\n#{package} was not found on device #{udid}! Please choose one from above. e.g. #{packages.sample}\n".red
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def app_installed? package
|
90
|
+
packages.include? "#{package}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def packages
|
94
|
+
%x(ideviceinstaller -u #{udid} -l -o list_user).split("\n")[1..100000].map { |p| p.match(/(.*) -/)[1] }
|
95
|
+
end
|
73
96
|
end
|
74
97
|
end
|
data/lib/flick/log.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Log
|
2
|
-
|
2
|
+
|
3
3
|
attr_accessor :action, :platform, :driver, :udid
|
4
|
-
|
4
|
+
|
5
5
|
def initialize options
|
6
6
|
Flick::Checker.action options[:action]
|
7
7
|
Flick::Checker.platform options[:platform]
|
@@ -16,24 +16,34 @@ class Log
|
|
16
16
|
end
|
17
17
|
self.udid = self.driver.udid
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
|
+
def android
|
21
|
+
platform == "android"
|
22
|
+
end
|
23
|
+
|
24
|
+
def ios
|
25
|
+
platform == "ios"
|
26
|
+
end
|
27
|
+
|
20
28
|
def run
|
21
29
|
self.send(action)
|
22
30
|
end
|
23
|
-
|
31
|
+
|
24
32
|
def start
|
25
33
|
puts "Saving to #{driver.outdir}/#{driver.name}.log"
|
26
34
|
log
|
27
35
|
end
|
28
|
-
|
36
|
+
|
29
37
|
def stop
|
30
38
|
Flick::System.kill_process "log", udid
|
39
|
+
Flick::System.kill "idevicesyslog -u #{udid}" if ios
|
40
|
+
Flick::System.kill "adb -s #{udid} logcat" if android
|
31
41
|
end
|
32
|
-
|
42
|
+
|
33
43
|
def log
|
34
44
|
stop
|
35
45
|
$0 = "flick-log-#{udid}"
|
36
|
-
SimpleDaemon.daemonize!
|
46
|
+
SimpleDaemon.daemonize!
|
37
47
|
command = -> do
|
38
48
|
driver.log driver.name
|
39
49
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Manager
|
2
|
+
|
3
|
+
attr_accessor :action, :platform, :driver, :udid, :file, :name
|
4
|
+
|
5
|
+
def initialize options
|
6
|
+
Flick::Checker.manager options[:action]
|
7
|
+
Flick::Checker.platform options[:platform]
|
8
|
+
self.action = options[:action]
|
9
|
+
self.platform = options[:platform]
|
10
|
+
case platform
|
11
|
+
when "ios"
|
12
|
+
self.driver = Flick::Ios.new options
|
13
|
+
when "android"
|
14
|
+
self.driver = Flick::Android.new options
|
15
|
+
end
|
16
|
+
self.udid = self.driver.udid
|
17
|
+
self.file = options[:file]
|
18
|
+
self.name = options[:name]
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
self.send(action)
|
23
|
+
end
|
24
|
+
|
25
|
+
def install
|
26
|
+
if file.nil?
|
27
|
+
puts "Specify a file path. e.g. -f #{Dir.home}/myApp/amazing-app.apk or .app".red; abort
|
28
|
+
else
|
29
|
+
Flick::Checker.file_exists? file
|
30
|
+
driver.install file
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def uninstall
|
35
|
+
if name.nil?
|
36
|
+
puts "Specify a Package Name or Bundle ID. e.g. -n ".red; abort
|
37
|
+
else
|
38
|
+
driver.uninstall name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/flick/screenshot.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Screenshot
|
2
|
-
|
2
|
+
|
3
3
|
attr_accessor :platform, :driver
|
4
|
-
|
4
|
+
|
5
5
|
def initialize options
|
6
6
|
Flick::Checker.platform options[:platform]
|
7
7
|
self.platform = options[:platform]
|
@@ -14,15 +14,19 @@ class Screenshot
|
|
14
14
|
end
|
15
15
|
setup
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
|
+
def android
|
19
|
+
platform == "android"
|
20
|
+
end
|
21
|
+
|
18
22
|
def screenshot
|
19
23
|
puts "Saving to #{driver.outdir}/#{driver.name}.png"
|
20
24
|
driver.screenshot driver.name
|
21
|
-
driver.pull_file "#{driver.dir_name}/#{driver.name}.png", driver.outdir if
|
25
|
+
driver.pull_file "#{driver.dir_name}/#{driver.name}.png", driver.outdir if android
|
22
26
|
end
|
23
|
-
|
27
|
+
|
24
28
|
private
|
25
|
-
|
29
|
+
|
26
30
|
def setup
|
27
31
|
driver.clear_files
|
28
32
|
end
|
data/lib/flick/simple_daemon.rb
CHANGED
@@ -18,7 +18,7 @@
|
|
18
18
|
# * The process becomes a session leader of a new session
|
19
19
|
# * The process becomes the process group leader of a new process group
|
20
20
|
# * The process has no controlling terminal
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# Optionally fork again and have the parent exit. This guarantes that
|
23
23
|
# the daemon is not a session leader nor can it acquire a controlling
|
24
24
|
# terminal (under SVR4)
|
@@ -28,13 +28,13 @@
|
|
28
28
|
# \_ simple daemon - writes out its pid to file
|
29
29
|
#
|
30
30
|
# Change the current working directory to / to avoid interfering with
|
31
|
-
# mounting and unmounting. By default don't bother to chdir("/") here
|
31
|
+
# mounting and unmounting. By default don't bother to chdir("/") here
|
32
32
|
# because we might to run inside APP_ROOT.
|
33
33
|
#
|
34
34
|
# Set file mode creation mask to 000 to allow creation of files with any
|
35
|
-
# required permission later. By default umask is whatever was set by the
|
36
|
-
# parent process at startup and can be set in config.ru and config_file,
|
37
|
-
# so making it 0000 and potentially exposing sensitive log data can be
|
35
|
+
# required permission later. By default umask is whatever was set by the
|
36
|
+
# parent process at startup and can be set in config.ru and config_file,
|
37
|
+
# so making it 0000 and potentially exposing sensitive log data can be
|
38
38
|
# bad policy.
|
39
39
|
#
|
40
40
|
# Close unneeded file descriptors inherited from the parent (there is no
|
@@ -46,8 +46,9 @@
|
|
46
46
|
# value of getpid() after step 3.
|
47
47
|
#
|
48
48
|
class SimpleDaemon
|
49
|
+
|
49
50
|
# In the directory where you want your daemon add a git submodule to
|
50
|
-
# your project and create a daemon launcher script:
|
51
|
+
# your project and create a daemon launcher script:
|
51
52
|
#
|
52
53
|
# #!/usr/bin/env ruby
|
53
54
|
#
|
@@ -74,14 +75,16 @@ class SimpleDaemon
|
|
74
75
|
# $ ps aux | grep "my daemon"
|
75
76
|
#
|
76
77
|
#
|
77
|
-
def self.daemonize!
|
78
|
+
def self.daemonize! out = '/dev/null', err = '/dev/null', safe = true
|
78
79
|
raise 'First fork failed' if (pid = fork) == -1
|
79
80
|
exit unless pid.nil?
|
80
81
|
Process.setsid
|
81
82
|
raise 'Second fork failed' if (pid = fork) == -1
|
82
83
|
exit unless pid.nil?
|
83
|
-
|
84
|
-
|
84
|
+
kill_pid
|
85
|
+
@file = Tempfile.new
|
86
|
+
@file.write Process.pid
|
87
|
+
@file.rewind
|
85
88
|
unless safe
|
86
89
|
Dir.chdir '/'
|
87
90
|
File.umask 0000
|
@@ -103,9 +106,12 @@ class SimpleDaemon
|
|
103
106
|
|
104
107
|
# Try and read the existing pid from the pid file and signal HUP to
|
105
108
|
# process.
|
106
|
-
def self.
|
107
|
-
|
108
|
-
|
109
|
+
def self.kill_pid
|
110
|
+
unless @file.nil?
|
111
|
+
opid = @file.read
|
112
|
+
Process.kill "HUP", opid
|
113
|
+
@file.unlink
|
114
|
+
end
|
109
115
|
rescue TypeError
|
110
116
|
$stdout.puts "#{pidfile} was empty: TypeError"
|
111
117
|
rescue Errno::ENOENT
|
data/lib/flick/system.rb
CHANGED
@@ -1,28 +1,48 @@
|
|
1
1
|
module Flick
|
2
2
|
module System
|
3
|
+
|
4
|
+
include Sys #load sys-proctable methods
|
5
|
+
|
3
6
|
def self.setup_system_dir dir_name
|
4
|
-
|
7
|
+
Dir.mkdir dir_name unless File.exists? dir_name
|
5
8
|
end
|
6
|
-
|
9
|
+
|
7
10
|
def self.clean_system_dir dir_name, udid
|
8
|
-
|
11
|
+
Dir.glob("#{dir_name}/*#{udid}*").each do |file|
|
12
|
+
File.delete file
|
13
|
+
end
|
9
14
|
end
|
10
|
-
|
11
|
-
def self.
|
12
|
-
|
15
|
+
|
16
|
+
def self.find_pid string
|
17
|
+
processes = ProcTable.ps.find_all { |x| x.cmdline.include? string }
|
18
|
+
processes.map { |p| p.pid } rescue []
|
13
19
|
end
|
14
|
-
|
15
|
-
def self.
|
16
|
-
if
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
|
21
|
+
def self.kill_pids pid_array
|
22
|
+
return if pid_array.empty?
|
23
|
+
pid_array.each { |p| Process.kill 'SIGKILL', p }
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.process_running? string
|
27
|
+
pid = self.find_pid string
|
28
|
+
unless pid.empty?
|
29
|
+
puts "PROCESSING IS RUNNING!!!"
|
30
|
+
true
|
31
|
+
else
|
32
|
+
false
|
23
33
|
end
|
24
34
|
end
|
25
|
-
|
35
|
+
|
36
|
+
def self.kill_process type, udid
|
37
|
+
pids = self.find_pid "#{type}-#{udid}"
|
38
|
+
self.kill_pids pids
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.kill string
|
42
|
+
pids = self.find_pid string
|
43
|
+
self.kill_pids pids
|
44
|
+
end
|
45
|
+
|
26
46
|
def self.video_length file
|
27
47
|
(`ffmpeg -i #{file} 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//`).strip
|
28
48
|
end
|
data/lib/flick/version.rb
CHANGED
data/lib/flick/video.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Video
|
2
2
|
|
3
3
|
attr_accessor :action, :platform, :driver, :image_count, :seconds, :extended, :udid, :format
|
4
|
-
|
4
|
+
|
5
5
|
def initialize options
|
6
6
|
Flick::Checker.action options[:action]
|
7
7
|
Flick::Checker.platform options[:platform]
|
@@ -20,19 +20,19 @@ class Video
|
|
20
20
|
self.udid = self.driver.udid
|
21
21
|
self.format = options[:format]
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def android
|
25
25
|
platform == "android"
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def ios
|
29
29
|
platform == "ios"
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def run
|
33
33
|
self.send(action)
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def start
|
37
37
|
driver.clear_files
|
38
38
|
puts "\nStarting Recoder!!!"
|
@@ -49,7 +49,7 @@ class Video
|
|
49
49
|
start_screenshot_record
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def stop
|
54
54
|
puts "\nStopping Recorder!!!"
|
55
55
|
if driver.recordable?
|
@@ -60,99 +60,94 @@ class Video
|
|
60
60
|
sleep 1
|
61
61
|
driver.clear_files
|
62
62
|
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
66
|
def start_record
|
67
67
|
Flick::System.kill_process "video", udid
|
68
68
|
$0 = "flick-video-#{udid}"
|
69
|
-
SimpleDaemon.daemonize!
|
69
|
+
SimpleDaemon.daemonize!
|
70
70
|
command = -> do
|
71
|
-
driver.screenrecord "
|
71
|
+
driver.screenrecord "video-#{udid}-single"
|
72
72
|
end
|
73
73
|
command.call
|
74
74
|
end
|
75
|
-
|
76
|
-
def is_recording?
|
77
|
-
!(`pgrep -f #{udid}-`).empty?
|
78
|
-
end
|
79
|
-
|
75
|
+
|
80
76
|
def loop_record
|
81
77
|
Flick::System.kill_process "video", udid
|
82
78
|
$0 = "flick-video-#{udid}"
|
83
|
-
SimpleDaemon.daemonize!
|
79
|
+
SimpleDaemon.daemonize!
|
84
80
|
command = -> do
|
85
81
|
count = "%03d" % 1
|
86
82
|
loop do
|
87
|
-
unless
|
88
|
-
driver.screenrecord "
|
83
|
+
unless Flick::System.process_running? "#{udid}-"
|
84
|
+
driver.screenrecord "video-#{udid}-#{count}"
|
89
85
|
count.next!
|
90
86
|
end
|
91
87
|
end
|
92
88
|
end
|
93
89
|
command.call
|
94
90
|
end
|
95
|
-
|
91
|
+
|
96
92
|
def stop_record
|
97
93
|
Flick::System.kill_process "video", udid
|
98
94
|
sleep 5 #wait for video process to finish
|
99
|
-
driver.pull_files
|
100
|
-
files = (
|
95
|
+
driver.pull_files "video"
|
96
|
+
files = Dir.glob("#{driver.flick_dir}/video-#{udid}*.mp4")
|
101
97
|
return if files.empty?
|
102
98
|
files.each { |file| system("mp4box -cat #{file} #{driver.flick_dir}/#{driver.name}.mp4") }
|
103
99
|
puts "Saving to #{driver.outdir}/#{driver.name}.#{format}"
|
104
100
|
if format == "gif"
|
105
101
|
gif
|
106
102
|
else
|
107
|
-
|
103
|
+
File.rename "#{driver.flick_dir}/#{driver.name}.mp4", "#{driver.outdir}/#{driver.name}.mp4"
|
108
104
|
end
|
109
105
|
end
|
110
|
-
|
106
|
+
|
111
107
|
def start_screenshot_record
|
112
108
|
Flick::System.kill_process "screenshot", udid
|
113
109
|
puts "Process will stop after #{image_count} screenshots.\n"
|
114
110
|
$0 = "flick-screenshot-#{udid}"
|
115
|
-
SimpleDaemon.daemonize!
|
111
|
+
SimpleDaemon.daemonize!
|
116
112
|
command = -> do
|
117
113
|
count = "%03d" % 1
|
118
114
|
loop do
|
119
|
-
if count.to_i
|
120
|
-
driver.screenshot "
|
115
|
+
if count.to_i <= image_count
|
116
|
+
driver.screenshot "screenshot-#{udid}-#{count}"
|
121
117
|
count.next!; sleep seconds
|
122
118
|
else
|
123
|
-
|
124
|
-
self.send(format)
|
119
|
+
stop_screenshot_recording
|
125
120
|
break
|
126
121
|
end
|
127
122
|
end
|
128
123
|
end
|
129
124
|
command.call
|
130
125
|
end
|
131
|
-
|
132
|
-
def stop_screenshot_recording
|
133
|
-
|
134
|
-
`rm /tmp/#{udid}-pidfile >> /dev/null 2>&1`
|
135
|
-
driver.pull_files if android
|
126
|
+
|
127
|
+
def stop_screenshot_recording
|
128
|
+
driver.pull_files "screenshot" if android
|
136
129
|
puts "Saving to #{driver.outdir}/#{driver.name}.#{format}"
|
137
130
|
self.send(format)
|
138
131
|
end
|
139
|
-
|
132
|
+
|
140
133
|
def gif
|
141
134
|
convert_images_to_mp4 unless driver.recordable?
|
142
|
-
%x(
|
135
|
+
%x(ffmpeg -loglevel quiet -i #{driver.flick_dir}/#{driver.name}.mp4 -pix_fmt rgb24 #{driver.outdir}/#{driver.name}.gif)
|
143
136
|
end
|
144
|
-
|
137
|
+
|
145
138
|
def mp4
|
146
139
|
convert_images_to_mp4
|
147
|
-
|
140
|
+
File.rename "#{driver.flick_dir}/#{driver.name}.mp4", "#{driver.outdir}/#{driver.name}.mp4" unless format == "gif"
|
148
141
|
end
|
149
|
-
|
142
|
+
|
150
143
|
def convert_images_to_mp4
|
151
144
|
remove_zero_byte_images
|
152
|
-
%x(
|
145
|
+
%x(ffmpeg -loglevel quiet -framerate 1 -pattern_type glob -i '#{driver.flick_dir}/screenshot-#{udid}*.png' -c:v libx264 -pix_fmt yuv420p #{driver.flick_dir}/#{driver.name}.mp4)
|
153
146
|
end
|
154
|
-
|
147
|
+
|
155
148
|
def remove_zero_byte_images
|
156
|
-
|
149
|
+
Dir.glob("#{driver.flick_dir}/screenshot-#{udid}*.png").each do |f|
|
150
|
+
File.delete f if File.zero? f
|
151
|
+
end
|
157
152
|
end
|
158
153
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -166,6 +166,60 @@ dependencies:
|
|
166
166
|
- - ">="
|
167
167
|
- !ruby/object:Gem::Version
|
168
168
|
version: 1.6.1
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
name: os
|
171
|
+
requirement: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - "~>"
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: 0.9.6
|
176
|
+
type: :runtime
|
177
|
+
prerelease: false
|
178
|
+
version_requirements: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - "~>"
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: 0.9.6
|
183
|
+
- !ruby/object:Gem::Dependency
|
184
|
+
name: sys-proctable
|
185
|
+
requirement: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - "~>"
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '1.1'
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: 1.1.1
|
193
|
+
type: :runtime
|
194
|
+
prerelease: false
|
195
|
+
version_requirements: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - "~>"
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '1.1'
|
200
|
+
- - ">="
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: 1.1.1
|
203
|
+
- !ruby/object:Gem::Dependency
|
204
|
+
name: apktools
|
205
|
+
requirement: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - "~>"
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: 0.7.1
|
210
|
+
- - ">="
|
211
|
+
- !ruby/object:Gem::Version
|
212
|
+
version: 0.7.1
|
213
|
+
type: :runtime
|
214
|
+
prerelease: false
|
215
|
+
version_requirements: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - "~>"
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: 0.7.1
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: 0.7.1
|
169
223
|
description: A CLI with helpful QA tools for iOS and Android from the command line
|
170
224
|
email:
|
171
225
|
- justin.ison@gmail.com
|
@@ -192,6 +246,7 @@ files:
|
|
192
246
|
- lib/flick/info.rb
|
193
247
|
- lib/flick/ios.rb
|
194
248
|
- lib/flick/log.rb
|
249
|
+
- lib/flick/manager.rb
|
195
250
|
- lib/flick/screenshot.rb
|
196
251
|
- lib/flick/simple_daemon.rb
|
197
252
|
- lib/flick/system.rb
|
@@ -224,4 +279,3 @@ specification_version: 4
|
|
224
279
|
summary: A CLI to capture screenshots, video, logs, and device information for Android
|
225
280
|
(Devices & Emulators) and iOS (Devices).
|
226
281
|
test_files: []
|
227
|
-
has_rdoc:
|