Android-ElectricSheep-Automator

 view release on metacpan or  search on metacpan

lib/Android/ElectricSheep/Automator.pm  view on Meta::CPAN

	$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'){
		if( ! exists($params->{$_}) || ! defined($params->{$_}) ){ last }
		push @fullspec, $params->{$_};
	}
	my @cmd;
	if( scalar(@fullspec) == 4 ){
		if( ($params->{'x1'} < 0) || ($params->{'x1'} > $w) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'x1' has a value (".$params->{'x1'}.") which is out of bounds."); return 1 }
		if( ($params->{'y1'} < 0) || ($params->{'y1'} > $h) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'y1' has a value (".$params->{'y1'}.") which is out of bounds."); return 1 }
		if( ($params->{'x2'} < 0) || ($params->{'x2'} > $w) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'x2' has a value (".$params->{'x2'}.") which is out of bounds."); return 1 }
		if( ($params->{'y2'} < 0) || ($params->{'y2'} > $h) ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'y2' has a value (".$params->{'y2'}.") which is out of bounds."); return 1 }
		@cmd = ('input', 'touchscreen', 'swipe', @fullspec);
	} else {
		# the time to do the move in milliseconds, there is a default of 100
		# which is enough to swipe to next screen
		my $dt = (exists($params->{'dt'}) && defined($params->{'dt'})) ? $params->{'dt'} : 100;
		my $direction = (exists($params->{'direction'}) && defined($params->{'direction'})) ? $params->{'direction'} : undef;
		if( ! defined $direction ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, input parameter 'direction' was not specified."); return 1 }

		my ($x1, $y1, $x2, $y2);

		if( ($direction =~ /^l(eft)?$/i) || ($direction =~ /^r(ight)?$/i) ){
			# horizontal
			$y1 = $y2 = int(3*$h/4);
		} else {
			# vertical
			$x1 = $x2 = int($w/2);
		}
		if( ($direction =~ /^r(ight)?$/i) ){
			$x1 = int(0.2*$w);
			$x2 = $w - $x1;
		}
		if( ($direction =~ /^l(eft)?$/i) ){
			$x2 = int(0.2*$w);
			$x1 = $w - $x2;
		}
		if( ($direction =~ /^d(own)?$/i) ){
			$y1 = int(0.2*$h);
			$y2 = $h - $y1;
		}
		if( ($direction =~ /^u(p)?$/i) ){
			$y2 = int(0.2*$h);
			$y1 = $h - $y2;
		}
		@cmd = ('input', 'touchscreen', 'swipe', $x1, $y1, $x2, $y2, $dt);
	}

	# unfortunately Android::ADB uses IPC::Open2::open2() to run the adb shell command
	# which does not capture STDERR, and so either they use open3 or we capture stderr thusly:

	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
}

# It finds all installed apps on device and appends with
# earlier results in $self->apps, and returns them as a hash
# keyed on appname. It also saves the returned hash into $self->apps
# optionally erasing previous entries (if 'make-fresh-apps-list'==1)
# The big question is whether to enquire the device for each package (app)
# installed and create an AppProperties object for each or not.
# The former is expensive and so you can do it on if-and-when-needed-basis
# (lazily). Or you can do it all at once here, it takes like 10-20 seconds.
# In any way, lazy or not, at the end the $self->apps HASH will be filled
# with the names of all packages installed on device (key).
# If 'lazy'==0, then for each installed app the device will be enquired
# and an AppProperties object will be created (it contains MainActivity,
# Permissions, etc.) and set as the value in the apps HASH.
# If 'packages' is specified and 'lazy'==0, then only those packages
# in 'packages' will be enquired, the $self->apps list will be
# refreshed with all the package names (key) but only some of them will
# contain an AppProperties object as the value, the other values
# will be undef.
# If no 'packages' was specified and 'lazy'==0, then all
# packages installed on device will be enquired and an AppProperties object
# will be associated with each of them in $self->apps.
# Default 'lazy' value is 1.
# Input:
#   'packages' => 'packagename' or regex (e.g. qr//) or [...] or { ...} :
#       optionally specify a list of package names to find ONLY,
#       default is to find ALL apps, which can be expensive if lazy>0
#       the 'packages' items can be a scalar string for exact match
#       or a compiled regex (qr//)
#   'force-reload-apps-list' => 0 or 1 : if 1, erase current list and start afresh
#   'lazy' => 1 or 0 : optionally specify not to enquire each package in detail,
#       i.e. creating an AppProperties object for each package,
#       but just add the package name as a key to the hash,
#       leaving the value undef. This value will be
#       created when needed, e.g. in an open_app() call.
#       Default is to be lazy, 1.
# It needs that connect_device() to have been called prior to this call
#
# On failure it returns undef.
# On success it saves the results in $self->apps HASH and returns that.
#
# NOTE: enquiring installed apps entails this:
#  1. adb shell dumpsys package packages
#     which is a general output of installed packages but does not contain
#     activity information.
#  2. For a given installed app name (package) we enquire by
#       adb shell dumpsys package com.example.myapp
#  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' => [...]



( run in 1.471 second using v1.01-cache-2.11-cpan-39bf76dae61 )