Android-ElectricSheep-Automator

 view release on metacpan or  search on metacpan

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

package Android::ElectricSheep::Automator;

# see also https://www.reddit.com/r/privacytoolsIO/comments/fit0tr/taking_almost_full_control_of_your_unrooted/
# swipe adb shell input touchscreen swipe 300 1200 100 1200 100

use 5.006;
use strict;
use warnings;

our $VERSION = '0.09';

use Mojo::Log;
use Config::JSON::Enhanced;
# it requires v0.002 (which is with my modifications)
#use Android::ADB;
# issue filed for Android::ADB :
#   https://rt.cpan.org/Public/Bug/Display.html?id=163391
# until this is resolved I am copying Android::ADB
# into my distribution, fixing the issues and renaming it to
# Android::ElectricSheep::Automator::ADB
# and using that. When the issue is resolved I will go back
# using Android::ADB
# Credits for Android::ADB (now Android::ElectricSheep::Automator::ADB)
# go to Marius Gavrilescu (marius@ieval.ro)
# as seen in:
#   https://metacpan.org/pod/Android::ADB
#
use Android::ElectricSheep::Automator::ADB;
use File::Temp qw/tempfile/;
use File::Basename;
use File::Spec;
use File::Path qw/make_path/;
use Cwd;
use FindBin;
use Time::HiRes qw/usleep/;
use Image::PNG;
use XML::LibXML;
use XML::LibXML::XPathContext;
use Text::ParseWords;

use Data::Roundtrip qw/perl2dump perl2json no-unicode-escape-permanently/;

use Android::ElectricSheep::Automator::DeviceProperties;
use Android::ElectricSheep::Automator::AppProperties;
use Android::ElectricSheep::Automator::ScreenLayout;
use Android::ElectricSheep::Automator::XMLParsers;

my $_DEFAULT_CONFIG = <<'EODC';
</* $VERSION = '0.09'; */>
</* comments are allowed */>
</* and <% vars %> and <% verbatim sections %> */>
{
	"adb" : {
		"path-to-executable" : "/usr/local/android-sdk/platform-tools/adb"
	},
	"debug" : {
		"verbosity" : 0,
		</* cleanup temp files on exit */>
		"cleanup" : 1
	},
	"logger" : {
		</* log to file if you uncomment this */>
		</* "filename" : "..." */>
	}
	</* config for our plugins (each can go to separate file also) */>
}
EODC

# NOTE: by default, it assumes that no device is connected
# and so it does not enquire about screen size etc on startup
# In order to tell it that a device (just one)
# is connected to the desktop and that we should connect to
# it, 
#   use param 'device-is-connected' => 1
# if there are more than one devices and you want to connect to
# one of them, then 
#  use param 'device-serial' => <serial-of-device-to-connect>
# 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
#       methods which require a connected device, 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,
			},
			'log' => {

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

by a regular expression in the package specification.

C<$params> is a HASH_REF which may or should contain:

=over 4

=item * B<C<package>>

is required. It can either be
a scalar string with the exact package name
or a L<Regexp> object which is a compiled regular expression
created by e.g. C<qr/^\.com.+?\.settings$/i>. If a regular
expression, the call will fail if there is not
exactly one match.

=item * B<C<lazy>>

is a flag to be passed on to L</find_installed_apps($params)>,
if needed, to denote whether to enquire
information about each package (app) at the time of this
call (set it to C<1>) or lazily, on a if-and-when-needed basis
(set it to C<0> which is the default). C<lazy> affects
all packages except those specified in C<packages>, if any. Default is C<1>.

=item * B<C<force-reload-apps-list>>

is a flag to be passed on to L</find_installed_apps($params)>,
if needed, and can be set to 1 to
erase previous packages information and start fresh. Default is C<0>.

=back

It returns a HASH_REF of matched packages names (keys) along
with enquired information (as a L<Android::ElectricSheep::Automator::AppProperties>
object). At the moment, because L</close_app($params)> allows closing only a single app,
this hash will contain only one entry unless we allow closing multiple
apps (e.g. via a regex which it is already supported) in the future.


=head1 SCRIPTS

For convenience, a few simple scripts are provided:

=head2 B<C<electric-sheep-find-installed-apps.pl>>

Find all install packages in the connected device. E.g.

    electric-sheep-find-installed-apps.pl --configfile config/myapp.conf --device Pixel_2_API_30_x86_ --output myapps.json

    electric-sheep-find-installed-apps.pl --configfile config/myapp.conf --device Pixel_2_API_30_x86_ --output myapps.json --fast


=head2 B<C<electric-sheep-open-app.pl>>

Open an app by its exact name or a keyword matching it (uniquely):

    electric-sheep-open-app.pl --configfile config/myapp.conf --name com.android.settings

    electric-sheep-open-app.pl --configfile config/myapp.conf --keyword 'clock'

Note that it constructs a regular expression from escaped user input.

=head2 B<C<electric-sheep-close-app.pl>>

Close an app by its exact name or a keyword matching it (uniquely):

    electric-sheep-close-app.pl --configfile config/myapp.conf --name com.android.settings

    electric-sheep-close-app.pl --configfile config/myapp.conf --keyword 'clock'

Note that it constructs a regular expression from escaped user input.

=head2 B<C<electric-sheep-dump-ui.pl>>

Dump the current screen UI as XML to STDOUT or to a file:

    electric-sheep-dump-ui.pl --configfile config/myapp.conf --output ui.xml

Note that it constructs a regular expression from escaped user input.

=head2 B<C<electric-sheep-dump-current-location.pl>>

Dump the GPS / geo-location position for the device from its various providers, if enabled.

    electric-sheep-dump-current-location.pl --configfile config/myapp.conf --output geolocation.json

=head2 B<C<electric-sheep-emulator-geofix.pl>>

Set the GPS / geo-location position to the specified coordinates.

    electric-sheep-dump-ui.pl --configfile config/myapp.conf --latitude 12.3 --longitude 45.6

=head2 B<C<electric-sheep-dump-screen-shot.pl>>

Take a screenshot of the device (current screen) and save to a PNG file.

    electric-sheep-dump-screen-shot.pl --configfile config/myapp.conf --output screenshot.png

=head2 B<C<electric-sheep-dump-screen-video.pl>>

Record a video of the device's current screen and save to an MP4 file.

    electric-sheep-dump-screen-video.pl --configfile config/myapp.conf --output video.mp4 --time-limit 30

=head2 B<C<electric-sheep-pull-app-apk.pl>>

Extract the APK file (java bytecode) for an app installed on the device and save locally, perhaps, for disassembly and/or modification and/or re-installation.

    electric-sheep-pull-app-apk.pl --package calendar2 --wildcard --output anoutdir --configfile config/myapp.conf --device Pixel_2_API_30_x86_

=head2 B<C<electric-sheep-install-app>>

Install an APK file onto the device, passing extra installation
parameters C<-r> (for re-install) and C<-g> (for granting permissions),

    electric-sheep-install-app --apk-filename test.apk -p '-r' -p '-g' --configfile config/myapp.conf --device Pixel_2_API_30_x86_


=head2 B<C<electric-sheep-viber-send-message.pl>>

Send a message using the Viber app.

    electric-sheep-viber-send-message.pl --message 'hello%sthere' --recipient 'george' --configfile config/myapp.conf --device Pixel_2_API_30_x86_

This one saves a lot of debugging information to C<debug> which can be used to
deal with special cases or different versions of Viber:

    electric-sheep-viber-send-message.pl --outbase debug --verbosity 1 --message 'hello%sthere' --recipient 'george' --configfile config/myapp.conf --device Pixel_2_API_30_x86_


=head1 TESTING

The normal tests under the C<t/> directory, initiated with C<make test> command,
are quite limited in scope because they do not assume
a connected device. That is, they do not check any
functions which require interaction with a connected
device.

The I<live tests> under the C<xt/live> directory, initiated with



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