view release on metacpan or search on metacpan
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# or
# use param 'device-object' => <device object>
# (of type Android::ElectricSheep::Automator::ADB::Device)
# or after instantiation with $obj->connect_device(...);
# and similarly for disconnect_device()
# NOTE: without connecting to a device you can not use e.g. open_app(), swipe() etc.
sub new {
my $class = ref($_[0]) || $_[0]; # aka proto
my $params = $_[1] // {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $self = {
'_private' => {
'confighash' => undef,
'configfile' => '', # this should never be undef
'Android::ADB' => undef,
'debug' => {
'verbosity' => 0,
'cleanup' => 1,
},
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# as returned by any item of $self->adb->devices()
# However, if there is ONLY ONE device connected to the desktop, then
# you do not need to specify a device, use this method without arguments
#
# It returns the device object (Android::ADB::Device) on success
# or undef on failure
sub connect_device {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity;
my ($what_device, $m);
if( exists($params->{'serial'}) && defined($m=$params->{'serial'}) ){
my $devs = $self->devices();
for (@$devs){
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# optionally saving it to the specified file
# It returns undef on failure.
# On success, it returns a hash with 2 keys:
# 'raw' : contains the raw XML content (as a string)
# 'XML::LibXML' : contains an XML::LibXML object with the parsed
# XML string, ready to do XPath queries
# it needs that connect_device() to have been called prior to this call
sub dump_current_screen_ui {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity;
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'device_connected()'." before calling this."); return undef }
my $filename = exists($params->{'filename'}) && defined($params->{'filename'}) ? $params->{'filename'} : undef;
my $FH;
if( ! defined $filename ){
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# It swipes the screen as per the 'direction'
# or full spec (x1,y1,x2,y2) (e.g. from x1 to x2 etc.)
# optional parameter 'dt' is the milliseconds to take for the swipe
# small is fast. Some speed is needed for certain gestures, so
# this is important parameter. E.g. for swiping to another screen.
# it needs that connect_device() to have been called prior to this call
sub swipe {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return 1 }
my $w = $self->device_properties->get('w');
my $h = $self->device_properties->get('h');
my @fullspec;
for ('x1', 'y1', 'x2', 'y2', 'dt'){
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# WARNING: the 2nd step if called for all the installed apps can take some
# time as it is done for each installed app.
# Perhaps a better approach is to lazily find apps by
# specifying the name of the app with the input parameter
# 'packages' => [...]
# This will append to apps() the result.
sub find_installed_apps {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
# optionally caller can specify a list of app names to enquire
# either as exact package name (string), a Regexp object (qr//)
# an ARRAY of package names or a HASH of package names:
my $packages = exists($params->{'packages'}) && defined($params->{'packages'}) ? $params->{'packages'} : undef;
my $rr = ref $packages;
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# It returns the found packages (full package name (which is a key in $self->{'apps'}))
# as a HASHref if any found, or {} if none found.
# the key to the returned hash is the full package name and the value
# will be AppProperties object or undef if not instantiated for that app
# because of lazy=1
# It returns undef on failure.
sub search_app {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
my $package;
if( ! exists($params->{'package'}) || ! defined($package=$params->{'package'}) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'package' was not specified, it must be a package name or a compiled regex (e.g. via "...
if( (ref($package)ne'') && (ref($package)ne'Regexp') ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, the type of input parameter 'package' must be a scalar string (the package name) or a Regexp object (compiled regex via ".'qr//'...
my $force_reload = (exists($params->{'force-reload-apps-list'}) && defined($params->{'force-reload-apps-list'})) ? $params->{'force-reload-apps-list'} : 0;
my $lazy = (exists($params->{'lazy'}) && defined($params->{'lazy'})) ? $params->{'lazy'} : 1;
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# THIS APPLIES ONLY TO THE MATCHED 'package'
# On success it returns a hash of {appname => appproperties} of the opened app
# (which will be created if not existing). It may return {} if no match
# was found for the specified 'package' name.
# On failure it returns undef
# it needs that connect_device() to have been called prior to this call
sub open_app {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my ($package);
if( ! exists($params->{'package'}) || ! defined($package=$params->{'package'}) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'package' is required."); return undef }
if( (ref($package)ne'') && (ref($package)ne'Regexp') ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, the type of input parameter 'package' must be a scalar string (the package name) or a Regexp object (compiled regex via ".'qr//'...
# optional activity, else we will see if we find one
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# Default is force-reload-apps-list=>0
# THIS APPLIES ONLY TO THE MATCHED 'package'
# On success it returns the a hash of {appname => appproperties} of the closed app
# (which will be created if not existing). It may return {} if no match.
# On failure it returns undef
# it needs that connect_device() to have been called prior to this call
sub close_app {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my ($package);
if( ! exists($params->{'package'}) || ! defined($package=$params->{'package'}) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'package' is required."); return undef }
if( (ref($package)ne'') && (ref($package)ne'Regexp') ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, the type of input parameter 'package' must be a scalar string (the package name) or a Regexp object (compiled regex via ".'qr//'...
# optional activity, else we will see if we find one
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# or
# 'bounds' => [ [topleftX,topleftY], [bottomrightX, bottomrightY] ]
# in which case, the tap position will be the mid-point of the 'bounds'
# rectangle.
# It returns 1 on failure, 0 on success
# it needs that connect_device() to have been called prior to this call
sub tap {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my (@position, $m);
if( exists($params->{'position'}) && defined($m=$params->{'position'}) ){
@position = ($m->[0], $m->[1]);
} elsif( exists($params->{'bounds'}) && defined($m=$params->{'bounds'}) ){
@position = ( int(($m->[1]->[0] + $m->[0]->[0])/2), int(($m->[1]->[1] + $m->[0]->[1])/2) );
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
return 0; # success
}
# returns 1 on failure, 0 on success
# it needs that connect_device() to have been called prior to this call
sub input_text {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my (@position, $m);
if( exists($params->{'position'}) && defined($m=$params->{'position'}) ){
@position = ($m->[0], $m->[1]);
} elsif( exists($params->{'bounds'}) && defined($m=$params->{'bounds'}) ){
@position = ( int(($m->[1]->[0] + $m->[0]->[0])/2), int(($m->[1]->[1] + $m->[0]->[1])/2) );
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
return 0; # success
}
# returns 1 on failure, 0 on success
# it needs that connect_device() to have been called prior to this call
sub clear_input_field {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my (@position, $m);
if( exists($params->{'position'}) && defined($m=$params->{'position'}) ){
@position = ($m->[0], $m->[1]);
} elsif( exists($params->{'bounds'}) && defined($m=$params->{'bounds'}) ){
@position = ( int(($m->[1]->[0] + $m->[0]->[0])/2), int(($m->[1]->[1] + $m->[0]->[1])/2) );
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# each process
# is represented by a hashref of items, e.g. %CPU
# (basically all the items from the header of the `ps` command)
# keyed on the full process command and its arguments (verbatim from `ps` output).
# 'json': the above perl data structure converted to JSON.
# NOTE: it uses _ps_parse_output() which is copied verbatim from System::Process
# I wish they would load ps info from a string rather than running their own `ps`
sub list_running_processes {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity;
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'device_connected()'." before calling this."); return undef }
my $filename = exists($params->{'filename'}) && defined($params->{'filename'}) ? $params->{'filename'} : undef;
my $extrafields = exists($params->{'extra-fields'}) && defined($params->{'extra-fields'}) ? $params->{'extra-fields'} : [];
my ($FH, $tmpfilename) = tempfile(CLEANUP=>$self->cleanup);
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
}
# ONLY FOR EMULATORS, it fixes the Geolocation to the
# specified coordinates (with 'latitude' and 'longitude').
# returns 1 on failure, 0 on success
# it needs that connect_device() to have been called prior to this call
sub geofix {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
for ('latitude', 'longitude'){
if( ! exists $params->{$_} ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter '$_' was not specified (as [x,y])."); return 1 }
}
my @cmd = ('emu', 'geo', 'fix', $params->{'longitude'}, $params->{'latitude'});
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# the provider provided including lat/lon
# It returns undef undef on failure or the above hash on success.
# NOTE: some providers may exist but have the Location[...] string as null
# meaning not available (e.g. 'network provider' when no internet exists)
# in this case lat,lon etc. will be '<na>' and the strings will be 'null'.
# it needs that connect_device() to have been called prior to this call
sub dump_current_location {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my @cmd = ('dumpsys', 'location');
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : sending command to adb: @cmd") }
my $res = $self->adb->shell(@cmd);
if( ! defined $res ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, got undefined result, most likely shell command did not run at all, this should not be happening."); return 1 }
if( $res->[0] != 0 ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, with:\nSTDOUT:\n".$res->[1]."\n\nSTDERR:\n".$res->[2]."\nEND."); return 1 }
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
}
# It lists the IDs of all the physical displays connected to the
# device, including the main one and returns these back as a HASH
# keyed on display ID.
# it needs that connect_device() to have been called prior to this call
sub list_physical_displays {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my @cmd = ('dumpsys', 'SurfaceFlinger', '--display-id');
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : sending command to adb: @cmd") }
my $res = $self->adb->shell(@cmd);
if( ! defined $res ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, got undefined result, most likely shell command did not run at all, this should not be happening."); return 1 }
if( $res->[0] != 0 ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, with:\nSTDOUT:\n".$res->[1]."\n\nSTDERR:\n".$res->[2]."\nEND."); return 1 }
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# It takes a screendump of current screen on device and returns it as
# a Image::PNG object, optionally saving it to the specified file.
# it needs that connect_device() to have been called prior to this call
# It returns undef on failure or the screenshot as an Image::PNG object
# on success.
# it needs that connect_device() to have been called prior to this call
sub dump_current_screen_shot {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity;
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'device_connected()'." before calling this."); return undef }
my $filename = exists($params->{'filename'}) && defined($params->{'filename'}) ? $params->{'filename'} : undef;
my $FH;
if( ! defined $filename ){
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# Optionally specify 'bit-rate'.
# Optionally specify %size = ('width' => ..., 'height' => ...)
# Optionally specify if $bugreport==1, then Android will overlay debug info on movie.
# Optionally specify 'display-id'.
# Output format of recording is MP4.
# It returns 1 on failure, 0 on success.
# it needs that connect_device() to have been called prior to this call
sub dump_current_screen_video {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity;
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'device_connected()'." before calling this."); return 1 }
my $filename = exists($params->{'filename'}) && defined($params->{'filename'}) ? $params->{'filename'} : undef;
if( ! defined $filename ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'filename' is not specified, an output filename must be specified."); return 1 }
my @options;
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
return 0; # success
}
# returns 1 on failure, 0 on success
# it needs that connect_device() to have been called prior to this call
sub wake_up {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my @cmd = qw/input keyevent KEYCODE_WAKEUP/;
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : sending command to adb: @cmd") }
my $res = $self->adb->shell(@cmd);
if( ! defined $res ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, got undefined result, most likely shell command did not run at all, this should not be happening."); return unde...
if( $res->[0] != 0 ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, with:\nSTDOUT:\n".$res->[1]."\n\nSTDERR:\n".$res->[2]."\nEND."); return undef }
return 0; # success
}
# goes to the home screen
# returns 1 on success, 0 on failure
# it needs that connect_device() to have been called prior to this call
sub home_screen {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
$self->wake_up();
my @cmd = qw/am start -a android.intent.action.MAIN -c android.intent.category.HOME/;
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : sending command to adb: @cmd") }
my $res = $self->adb->shell(@cmd);
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
return 0; # success
}
# It swipes right basically
# it returns 0 on success, 1 on failure
# it needs that connect_device() to have been called prior to this call
sub next_screen {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
if( $self->swipe({'direction' => 'right', dt => 100}) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'swipe()'." has failed."); return undef }
return 0; # success
}
# It swipes left basically
# it returns 0 on success, 1 on failure
# it needs that connect_device() to have been called prior to this call
sub previous_screen {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
if( $self->swipe({'direction' => 'left', dt => 100}) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'swipe()'." has failed."); return undef }
return 0; # success
}
# it returns 0 on success, 1 on failure
# it needs that connect_device() to have been called prior to this call
# the left-triangle button (see http://developer.android.com/reference/android/view/KeyEvent.html)
sub navigation_menu_back_button {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my @cmd = ('input', 'keyevent', 'KEYCODE_BACK');
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : sending command to adb: @cmd") }
my $res = $self->adb->shell(@cmd);
if( ! defined $res ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, got undefined result, most likely shell command did not run at all, this should not be happening."); return unde...
if( $res->[0] != 0 ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, with:\nSTDOUT:\n".$res->[1]."\n\nSTDERR:\n".$res->[2]."\nEND."); return undef }
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
return 0; # success
}
# it returns 0 on success, 1 on failure
# it needs that connect_device() to have been called prior to this call
# the round button, it goes to home (see http://developer.android.com/reference/android/view/KeyEvent.html)
sub navigation_menu_home_button {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my @cmd = ('input', 'keyevent', 'KEYCODE_HOME');
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : sending command to adb: @cmd") }
my $res = $self->adb->shell(@cmd);
if( ! defined $res ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, got undefined result, most likely shell command did not run at all, this should not be happening."); return unde...
if( $res->[0] != 0 ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, with:\nSTDOUT:\n".$res->[1]."\n\nSTDERR:\n".$res->[2]."\nEND."); return undef }
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
}
# it returns 0 on success, 1 on failure
# it needs that connect_device() to have been called prior to this call
# the square button, aka overview, shows all apps running in some sort of gallery view
# (see http://developer.android.com/reference/android/view/KeyEvent.html)
sub navigation_menu_overview_button {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my @cmd = ('input', 'keyevent', 'KEYCODE_APP_SWITCH');
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : sending command to adb: @cmd") }
my $res = $self->adb->shell(@cmd);
if( ! defined $res ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, got undefined result, most likely shell command did not run at all, this should not be happening."); return unde...
if( $res->[0] != 0 ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, with:\nSTDOUT:\n".$res->[1]."\n\nSTDERR:\n".$res->[2]."\nEND."); return undef }
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# it swipes up and lists all the apps found in that "drawer"
# with their icon bounds (which is where you "tap").
# It returns undef on failure
# It returns a hashref of all the apps found with their name as key and bounds content etc.
# it needs that connect_device() to have been called prior to this call
sub find_all_apps_roundabout_way {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
# go to home, swipe up and all apps will be revealed
# then dump the UI
# then swipe down
if( $self->home_screen() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'home_screen()'." has failed."); return undef }
usleep(300);
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
return $apps; # success
}
# It opens the specified (by 'name' or 'bounds' - for tapping) app
# and returns the a hashref with appname (only if name was specified) and bounds
# it needs that connect_device() to have been called prior to this call
sub open_app_roundabout_way {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( ! $self->is_device_connected() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, you need to connect a device to the desktop and ALSO explicitly call ".'connect_device()'." before calling this."); return undef }
my $apps = $self->apps_roundabout_way();
if( (! defined($apps))
|| (exists($params->{'force-reload-apps-list'}) && defined($params->{'force-reload-apps-list'}) && ($params->{'force-reload-apps-list'}>0))
){
if( ! defined $self->find_all_apps_roundabout_way() ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, failed to load list of installed apps, call to ".'find_all_apps_roundabout_way()'." has failed."); return undef }
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
sub apps_roundabout_way { return $_[0]->{'apps-roundabout-way'} }
sub adb { return $_[0]->{'_private'}->{'Android::ADB'} }
sub log { return $_[0]->{'_private'}->{'log'}->{'logger-object'} }
# returns the current verbosity level optionally setting its value
# Value must be an integer >= 0
# setting a verbosity level will also spawn a chain of other debug subs,
sub verbosity {
my ($self, $m) = @_;
my $log = $self->log();
if( defined $m ){
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
$self->{'_private'}->{'debug'}->{'verbosity'} = $m;
if( defined $self->adb ){ $self->adb->{'verbosity'} = $m }
}
return $self->{'_private'}->{'debug'}->{'verbosity'}
}
sub cleanup {
my ($self, $m) = @_;
my $log = $self->log();
if( defined $m ){
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
$self->{'_private'}->{'debug'}->{'cleanup'} = $m;
}
return $self->{'_private'}->{'debug'}->{'cleanup'}
}
# return configfile or read+check+set a configfile,
# returns undef on failure or the configfile on success
sub configfile {
my ($self, $infile) = @_;
return $self->{'_private'}->{'configfile'} unless defined $infile;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
# this can be called before the logger is created, so create a temp logger for this
my $log = $self->log() // Mojo::Log->new();
my $ch = parse_configfile($infile, $log);
if( ! defined $ch ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'parse_configfile()'." has failed for configuration file '$infile'."); return undef }
# set it in self, it will also do checks on required keys
if( ! defined $self->confighash($ch) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, failed to load specified confighash, , there must be errors in the configuration."); return undef }
$self->{'_private'}->{'configfile'} = $infile;
return $infile #success
}
# return configfile or read+check+set a configfile,
# returns undef on failure or the configfile on success
sub parse_configfile {
my ($infile, $log) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
# this can be called before the logger is created, so create a temp logger for this
$log //= Mojo::Log->new();
my $ch = Config::JSON::Enhanced::config2perl({
'filename' => $infile,
'commentstyle' => 'custom(</*)(*/>)',
'tags' => ['<%','%>'],
'variable-substitutions' => {
'SCRIPTDIR' => Cwd::abs_path($FindBin::Bin),
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# returns the confighash stored or if one is supplied
# it checks it and sets it and returns it
# or it returns undef on failure
# NOTE, if param is specified then we assume we do not have any configuration,
# we do not have a logger yet, we have no configuration, no verbosity, etc.
sub confighash {
my ($self, $m) = @_;
if( ! defined $m ){ return $self->{'_private'}->{'confighash'} }
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
#print STDOUT "${whoami} (via $parent), line ".__LINE__." : called ...\n";
# we are storing specified confighash but first check it for some fields
# required fields:
for ('adb', 'debug', 'logger'){
if( ! exists($m->{$_}) || ! defined($m->{$_}) ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, configuration does not have key '$_'.\n"; return undef }
}
my $x;
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
# ok!
$self->{'_private'}->{'confighash'} = $m;
return $m
}
# initialises
# do the verbositys
# returns 1 on failure, 0 on success
sub init {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
# Confighash
# first see if either user specified a config file or the default is present and read it,
# then we will overwrite with user-specified params if any
my ($configfile, $confighash);
if( exists($params->{'configfile'}) && defined($configfile=$params->{'configfile'}) ){
if( ! -f $configfile ){ print STDERR __PACKAGE__."${whoami} (via $parent), line ".__LINE__." : error, specified configfile '$configfile' does not exist or it is not a file.\n"; return 1 }
# this reads, creates confighash and calls confighash() which will do all the tests
if( ! defined $self->configfile($configfile) ){ print STDERR __PACKAGE__."${whoami} (via $parent), line ".__LINE__." : error, call to ".'configfile()'." has failed for configfile '$configfile'.\n"; return 1 }
$confighash = $self->confighash();
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
}
if( $self->cleanup($v) < 0 ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to 'cleanup()' has failed for value '$v'."); return 1 }
return 0 # success
}
# initialises module-specific things, no need to copy this to other modules
# returns 1 on failure, 0 on success
sub init_module_specific {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
my $confighash = $self->confighash();
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : called ...") }
# set or create the Android::ADB object
if( exists($params->{'adb'}) && defined($params->{'adb'}) ){
# caller supplied an existing ADB object
$self->{'_private'}->{'Android::ADB'} = $params->{'adb'}
} else {
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
if( $verbosity > 0 ){ $log->info($devobj."\n${whoami} (via $parent), line ".__LINE__." : device set as above.") }
}
# done
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : ".__PACKAGE__." has been initialised ...") }
return 0 # success
}
sub disconnect_device {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : called ...") }
$self->{'device-properties'} = undef;
$self->{'device-object'} = undef;
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : done.") }
return 0; # success
lib/Android/ElectricSheep/Automator.pm view on Meta::CPAN
sub is_device_connected { return defined($_[0]->{'device-properties'}) ? 1 : 0 }
# enquire screen properties (e.g. w, h) and save them to our $self
# if already exists a DeviceProperties object, then we just return that
# and do nothing UNLESS param 'force' => 1
# On failure it returns undef
# On success it creates a new DeviceProperties Object which is saved in $self
# and also returned to caller
sub find_current_device_properties {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
my $confighash = $self->confighash();
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : called ...") }
my $sl;
if( defined($sl=$self->device_properties())
|| (
exists($params->{'force'})
&& defined($params->{'force'})
lib/Android/ElectricSheep/Automator/AppProperties.pm view on Meta::CPAN
use XML::LibXML;
use Data::Roundtrip qw/perl2dump no-unicode-escape-permanently/;
use overload ( '""' => \&toString );
sub new {
my $class = $_[0];
my $params = $_[1] // {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $self = {
'_private' => {
'logger-object' => undef,
'verbosity' => 0,
'mother' => 0,
},
'data' => {
# both are extracted from pkg=Package{3d33653 com.viber.voip}
'packageName' => '',
lib/Android/ElectricSheep/Automator/AppProperties.pm view on Meta::CPAN
# So either specify lazy=0 for getting info on all packages installed (takes some time!)
# or set 'packages' to include those package names you want non-lazy, letting all other lazy.
# It returns undef on failure
# It returns %{ AppProperties objects } keyed on the app name (packageName),
# on success. The values of the hash can be undef if lazy>0
# meaning that they will be left to be enquired when someone needs them
# e.g. in an open_app() call.
sub enquire_installed_apps_factory {
my $params = $_[0] // {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
# we need a mother object (Android::ElectricSheep::Automator)
if( (! exists $params->{'mother'})
|| (! defined $params->{'mother'})
|| (! defined $params->{'mother'}->adb())
){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, input parameter 'mother' with our parent Android::ElectricSheep::Automator object was not specified.\n"; return undef }
my $mother = $params->{'mother'};
# we now have a mother
my $log = $mother->log;
lib/Android/ElectricSheep/Automator/AppProperties.pm view on Meta::CPAN
return \%apps;
}
# does a adb shell dumpsys and reads various things from it
# it may also do a adb shell wm density
# returns 0 on success, 1 on failure
sub enquire {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log;
my $verbosity = $self->verbosity;
# NOTE
# dumpsys package packages
# and
# dumpsys package com.example.xyz
# will yield different things for the package com.example.xyz
# we need to enquire twice, 1 for all the package names
# 2 for the full content of the package info, including activities
lib/Android/ElectricSheep/Automator/DeviceProperties.pm view on Meta::CPAN
use XML::LibXML;
use Data::Roundtrip qw/perl2dump no-unicode-escape-permanently/;
use overload ( '""' => \&toString );
sub new {
my $class = $_[0];
my $params = $_[1] // {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $self = {
'_private' => {
'logger-object' => undef,
'verbosity' => 0,
'mother' => 0,
},
'data' => {
# corresponds to dumpsys->RawSurfaceWidth,RawSurfaceHeight
'w' => 0,
lib/Android/ElectricSheep/Automator/DeviceProperties.pm view on Meta::CPAN
return $self;
}
# does a adb shell dumpsys and reads various things from it
# it may also do a adb shell wm density
# returns 0 on success, 1 on failure
sub enquire {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log;
my $verbosity = $self->verbosity;
# first get the serial of the device
my @cmd = ('get-serialno');
my $res = $self->adb->run(@cmd);
if( ! defined $res ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, got undefined result, most likely shell command did not run at all, this should not be happening."); return 1 }
if( $res->[0] != 0 ){ $log->error(join(" ", @cmd)."\n${whoami} (via $parent), line ".__LINE__." : error, above shell command has failed, with:\nsSTDOUT:\n".$res->[1]."\n\nSTDERR:\n".$res->[2]."\nEND."); return 1 }
$self->set('serial', $res->[1]=~s/\s*$//gmr); # it has a newline at the end
lib/Android/ElectricSheep/Automator/Plugins/Base.pm view on Meta::CPAN
},
"Android::ElectricSheep::Automator::Plugins::Viber" : {
}
}
EODC
sub new {
my $class = ref($_[0]) || $_[0];
my $params = $_[1] // {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $self = {
'_private' => {
'child-class' => $class,
'mother' => undef, # the Android::ElectricSheep::Automator object
'confighash' => undef,
'configfile' => '', # this should never be undef
},
};
bless $self => $class;
lib/Android/ElectricSheep/Automator/Plugins/Base.pm view on Meta::CPAN
sub mother { return $_[0]->{'_private'}->{'mother'} }
sub child_class { return $_[0]->{'_private'}->{'child-class'} }
# returns the current verbosity level optionally setting its value
# Value must be an integer >= 0
# setting a verbosity level will also spawn a chain of other debug subs,
sub verbosity {
my ($self, $m) = @_;
my $log = $self->log();
if( defined $m ){
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
$self->{'_private'}->{'debug'}->{'verbosity'} = $m;
if( defined $self->adb ){ $self->adb->{'verbosity'} = $m }
}
return $self->{'_private'}->{'debug'}->{'verbosity'}
}
sub cleanup {
my ($self, $m) = @_;
my $log = $self->log();
if( defined $m ){
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
$self->{'_private'}->{'debug'}->{'cleanup'} = $m;
}
return $self->{'_private'}->{'debug'}->{'cleanup'}
}
# return configfile or read+check+set a configfile,
# returns undef on failure or the configfile on success
sub configfile {
my ($self, $infile) = @_;
return $self->{'_private'}->{'configfile'} unless defined $infile;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $ch = Android::ElectricSheep::Automator::parse_configfile($infile, $log);
if( ! defined $ch ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'Config::JSON::Enhanced::config2perl()'." has failed for configuration file '$infile'."); return undef }
# set it in self, it will also do checks on required keys
if( ! defined $self->confighash($ch) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, failed to load specified confighash, , there must be errors in the configuration."); return undef }
$self->{'_private'}->{'configfile'} = $infile;
lib/Android/ElectricSheep/Automator/Plugins/Base.pm view on Meta::CPAN
# returns the confighash stored or if one is supplied
# it checks it and sets it and returns it
# or it returns undef on failure
# NOTE, if param is specified then we assume we do not have any configuration,
# we do not have a logger yet, we have no configuration, no verbosity, etc.
sub confighash {
my ($self, $m) = @_;
if( ! defined $m ){ return $self->{'_private'}->{'confighash'} }
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
print STDOUT "${whoami} (via $parent), line ".__LINE__." : called ...\n";
# the confighash must contain a mother section: 'Android::ElectricSheep::Automator'
# and a child section,
# e.g. 'Android::ElectricSheep::Automator::Plugins::Viber'
# check for both here:
for ('Android::ElectricSheep::Automator', $self->child_class){
if( ! exists($m->{$_}) || ! defined($m->{$_}) || (ref($m->{$_})ne'HASH') ){ print STDERR perl2dump($m)."${whoami} (via $parent), line ".__LINE__." : error, configuration (see above) does not have key '$_' or its value is not a HASHref.\n"; return u...
}
lib/Android/ElectricSheep/Automator/Plugins/Base.pm view on Meta::CPAN
# ok!
$self->{'_private'}->{'confighash'} = $m;
return $m
}
# initialises
# returns 1 on failure, 0 on success
sub init {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
# we don't have a log yet
if( exists($params->{'child-class'}) && defined($params->{'child-class'}) ){
$self->{'_private'}->{'child-class'} = $params->{'child-class'};
} else { print STDERR "${whoami} (via $parent), line ".__LINE__." : error, input parameter 'child-class' was not specified, this is the Plugin class calling us, e.g. 'Android::ElectricSheep::Automator::Plugins::Viber'. At the moment this is not ext...
return 0 # success
}
# initialises module-specific things
# by now we already have read confighash and have logger, verbosity etc.
# returns 1 on failure, 0 on success
sub init_module_specific {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
# Confighash
# first see if either user specified a config file or the default is present and read it,
# then we will overwrite with user-specified params if any
my ($configfile, $confighash);
if( exists($params->{'configfile'}) && defined($configfile=$params->{'configfile'}) ){
if( ! -f $configfile ){ print STDERR __PACKAGE__." (via ".$self->child_class.") : ${whoami} (via $parent), line ".__LINE__." : error, specified configfile '$configfile' does not exist or it is not a file.\n"; return 1 }
# this reads, creates confighash and calls confighash() which will do all the tests
if( ! defined $self->configfile($configfile) ){ print STDERR __PACKAGE__." (via ".$self->child_class.") : ${whoami} (via $parent), line ".__LINE__." : error, call to ".'configfile()'." has failed for configfile '$configfile'.\n"; return 1 }
lib/Android/ElectricSheep/Automator/Plugins/Viber.pm view on Meta::CPAN
%$params,
'child-class' => $class,
});
$self->{'_private'}->{'appname'} = 'com.viber.voip';
return $self;
}
sub appname { return $_[0]->{'_private'}->{'appname'} }
sub open_viber_app {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
my $packagename = $self->appname;
my $ret = $self->mother->open_app({'package' => $packagename});
if( ! defined $ret ){
my $instapps = $self->mother->find_installed_apps();
if( defined $instapps ){
$log->error("All installed apps on current device:\n".join("\n ".$_, sort keys %$instapps)."\n\n");
}
$log->error("${whoami} (via $parent), line ".__LINE__." : failed to open app '$packagename'.");
return undef
}
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : app '$packagename' is now opening ...") }
return $ret;
}
sub close_viber_app {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
my $packagename = $self->appname;
my $ret = $self->mother->close_app({'package' => $packagename});
if( ! defined $ret ){ $log->error("${whoami} (via $parent), line ".__LINE__." : failed to close app '$packagename'."); return undef }
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : app '$packagename' is now closing ...") }
return $ret;
}
# keeps pressing the back-arrow at the top of the app to hopefully
# arrive at the main activity of the app,
# TODO: is there a way to tell it to go to main activity ? WelcomeActivity does not seem to work
# returns 1 on failure, 0 on success.
sub navigate_to_viber_home_activity {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
my ($outbase, $outfile);
# for debugging purposes, save each UI we get here
$outbase = exists($params->{'outbase'}) ? $params->{'outbase'} : undef;
my ($ui, $dom, $xc, $asel, @nodes, $N, $node, $boundstr, $bounds);
my $repeats = 3;
lib/Android/ElectricSheep/Automator/Plugins/Viber.pm view on Meta::CPAN
if( $self->mother->tap({'bounds' => $bounds}) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, failed to tap on $bounds."); return 1 }
usleep(0.75);
}
if( $verbosity > 0 ){ $log->info("${whoami} (via $parent), line ".__LINE__." : hopefully we are now at the very first screen of the app.") }
return 0 # success
}
sub send_message {
my ($self, $params) = @_;
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log();
my $verbosity = $self->verbosity();
my ($recipient, $message, $outbase, $outfile);
if( ! exists($params->{'recipient'}) || ! defined($recipient=$params->{'recipient'}) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'recipient' was not specified."); return undef }
if( ! exists($params->{'message'}) || ! defined($message=$params->{'message'}) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'message' was not specified."); return undef }
# for debugging purposes, save each UI we get here
$outbase = exists($params->{'outbase'}) ? $params->{'outbase'} : undef;
# do everything except clicking the send button
my $mock = exists($params->{'mock'}) ? $params->{'mock'} : 0;
lib/Android/ElectricSheep/Automator/ScreenLayout.pm view on Meta::CPAN
use XML::LibXML;
use Data::Roundtrip qw/perl2dump no-unicode-escape-permanently/;
use overload ( '""' => \&toString );
sub new {
my $class = $_[0];
my $params = $_[1] // {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $self = {
'_private' => {
'xml' => undef,
'logger-object' => undef,
'verbosity' => 0,
},
'data' => {
'w' => 0,
'h' => 0,
lib/Android/ElectricSheep/Automator/ScreenLayout.pm view on Meta::CPAN
# will not be found here.
# my $xmlstring = $self->dump_current_screen_ui();
# my $sl = Android::ElectricSheep::Automator::ScreenLayout->new({'xml-string' => $xmlstring});
# will call fromXML();
# Or make it yourself: adb shell uiautomator dump outfile
# or adb exec-out uiautomator dump /dev/tty | awk '{gsub("UI hierchary dumped to: /dev/tty", "");print}'
sub fromXML {
my ($self, $params) = @_;
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = $self->log;
my $verbosity = $self->verbosity;
my $doc;
if( exists $params->{'xml-filename'} ){
$doc = XML::LibXML->load_xml(location => $params->{'xml-filename'});
} elsif( exists $params->{'xml-string'} ){
$doc = XML::LibXML->load_xml(string => $params->{'xml-string'});
}
lib/Android/ElectricSheep/Automator/XMLParsers.pm view on Meta::CPAN
# my $ret = Android::ElectricSheep::Automator::XMLParsers::XMLParser_find_all_apps(
# {'xml-string' => $xmlstring}
# );
# will call fromXML();
# Or make it yourself: adb shell uiautomator dump outfile
# or adb exec-out uiautomator dump /dev/tty | awk '{gsub("UI hierchary dumped to: /dev/tty", "");print}'
sub XMLParser_find_all_apps {
my $params = $_[0];
$params //= {};
my $parent = ( caller(1) )[3] || "N/A";
my $whoami = ( caller(0) )[3];
my $log = (exists($params->{'log'}) && defined($params->{'log'})) ? $params->{'log'} : Mojo::Log->new;
my $verbosity = (exists($params->{'verbosity'}) && defined($params->{'verbosity'})) ? $params->{'verbosity'} : 0;
my $doc;
if( exists($params->{'xml-filename'}) && defined($params->{'xml-filename'}) ){
$doc = eval { XML::LibXML->load_xml(location => $params->{'xml-filename'}) };
if( $@ || (! defined $doc) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'XML::LibXML->load_xml()'." has failed for file '".$params->{'xml-filename'}."' : $@"); return undef }
} elsif( exists($params->{'xml-string'}) && defined($params->{'xml-string'}) ){
$doc = eval { XML::LibXML->load_xml(string => $params->{'xml-string'}) };