Android-ElectricSheep-Automator
view release on metacpan or search on metacpan
lib/Android/ElectricSheep/Automator/ScreenLayout.pm view on Meta::CPAN
$doc = XML::LibXML->load_xml(string => $params->{'xml-string'});
}
if( ! defined $doc ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'XML::XPath->new()'." has failed."); return undef }
# find a node AT THE TOP for setting the width and height
# text=""
# content-desc=""
# resource-id=""
# class="android.view.FrameLayout"
my $xpath = '/hierarchy/node[@text=\'\' and @resource-id=\'\' and @class=\'android.widget.FrameLayout\']';
my $numframes = 0; # paranoid check how many frames found?
my @nodes = eval { $doc->findnodes($xpath) };
if( $@ ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'findnodes()'." has failed for this xpath: $xpath : $@"); return undef };
foreach my $anode (@nodes){
# the whole screen size is in bounds
my $bounds = $anode->getAttribute('bounds');
$bounds =~ s/\s+//;
if( $bounds =~ /^\[(\d+),(\d+)\]\[(\d+),(\d+)\]$/ ){
my ($x1, $y1, $x2, $y2) = ($1, $2, $3, $4);
$self->set('w', $x2-$x1);
$self->set('h', $y2-$y1);
} else { $log->error($anode."\n${whoami} (via $parent), line ".__LINE__." : error, above node has invalid bounds/1."); return undef }
$numframes++;
}
if( $numframes != 1 ){ $log->error($doc."\n${whoami} (via $parent), line ".__LINE__." : error, failed to find exactly one node with XPath=${xpath} but found ${numframes} instead, see above xml."); return undef }
if( exists($params->{'fully'}) && defined($params->{'fully'}) && ($params->{'fully'}==1) ){
# find the app-icons-area, it may not be there
# text=""
# content-desc=""
# resource-id="com.huawei.android.launcher:id/workspace_screen" <<<< we will filterout huawei
# class="android.view.ViewGroup"
# ONLY XPATH1 is supported, so no ends-with or matching regex, we have to filter ourselves
#my $xpath = '//node[@text=\'\' and @class=\'android.view.ViewGroup\' and ends-with(@resource-id, \'/workspace_screen\')]';
$xpath = '//node[@text=\'\' and @content-desc=\'\' and @class=\'android.view.ViewGroup\' and contains(@resource-id, \'/workspace_screen\')]';
$numframes = 0; # paranoid check how many frames found?
@nodes = eval { $doc->findnodes($xpath) };
if( $@ ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'findnodes()'." has failed for this xpath: $xpath"); return undef };
foreach my $anode (@nodes){
my $resource_id = $anode->getAttribute('resource-id');
if( $resource_id =~ /\/workspace_screen$/i ){
my $bounds = $anode->getAttribute('bounds');
$bounds =~ s/\s+//;
if( $bounds =~ /^\[(\d+),(\d+)\]\[(\d+),(\d+)\]$/ ){
my ($x1, $y1, $x2, $y2) = ($1, $2, $3, $4);
$self->set('app-icons-area', [$x1, $y1, $x2, $y2, $x2-$x1, $y2-$y1]);
} else { $log->error($anode."\n${whoami} (via $parent), line ".__LINE__." : error, above node has invalid bounds/2."); return undef }
$numframes++;
} else { $log->error($anode."\n${whoami} (via $parent), line ".__LINE__." : error, above node has unexpected 'resource-id' ($resource_id), does not end in 'workspace_screen'."); return undef }
}
if( $numframes != 1 ){ $log->warn($doc."\n${whoami} (via $parent), line ".__LINE__." : error, failed to find exactly one node with XPath=${xpath} but found ${numframes} instead, see above xml.") }
# now search for dock_divider to find its dimensions, it may not be there
# text=""
# resource-id="com.huawei.android.launcher:id/dock_divider"
# class="android.widget.ImageView"
# content-desc="Page indicator"
$xpath = '//node[@text=\'\' and @class=\'android.widget.ImageView\' and @content-desc=\'Page indicator\' and contains(@resource-id, \'id/dock_divider\')]';
$numframes = 0;
@nodes = eval { $doc->findnodes($xpath) };
if( $@ ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'findnodes()'." has failed for this xpath: $xpath"); return undef };
foreach my $anode (@nodes){
my $resource_id = $anode->getAttribute('resource-id');
if( $resource_id =~ /\/dock_divider$/i ){
# the app-icons space is inside a frame
my $bounds = $anode->getAttribute('bounds');
$bounds =~ s/\s+//;
if( $bounds =~ /^\[(\d+),(\d+)\]\[(\d+),(\d+)\]$/ ){
my ($x1, $y1, $x2, $y2) = ($1, $2, $3, $4);
$self->set('dock-divider-area', [$x1, $y1, $x2, $y2, $x2-$x1, $y2-$y1]);
} else { $log->error($anode."\n${whoami} (via $parent), line ".__LINE__." : error, above node has invalid bounds/3."); return undef }
$numframes++;
} else { $log->error($anode."\n${whoami} (via $parent), line ".__LINE__." : error, above node has unexpected 'resource-id' ($resource_id), does not end in 'dock_divider'."); return undef }
}
if( $numframes != 1 ){ $log->warn($doc."\n${whoami} (via $parent), line ".__LINE__." : error, failed to find exactly one node with XPath=${xpath} but found ${numframes} instead, see above xml.") }
# now search for hotseat (the common apps at the bottom invariant to swiping)
# text=""
# resource-id="com.huawei.android.launcher:id/hotseat"
# class="android.widget.FrameLayout"
# content-desc=""
$xpath = '//node[@text=\'\' and @class=\'android.widget.FrameLayout\' and @content-desc=\'\' and contains(@resource-id, \'id/hotseat\')]';
$numframes = 0;
@nodes = eval { $doc->findnodes($xpath) };
if( $@ ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'findnodes()'." has failed for this xpath: $xpath"); return undef };
foreach my $anode (@nodes){
my $resource_id = $anode->getAttribute('resource-id');
if( $resource_id =~ /\/hotseat$/i ){
# the app-icons space is inside a frame
my $bounds = $anode->getAttribute('bounds');
$bounds =~ s/\s+//;
if( $bounds =~ /^\[(\d+),(\d+)\]\[(\d+),(\d+)\]$/ ){
my ($x1, $y1, $x2, $y2) = ($1, $2, $3, $4);
$self->set('hotseat-area', [$x1, $y1, $x2, $y2, $x2-$x1, $y2-$y1]);
} else { $log->error($anode."\n${whoami} (via $parent), line ".__LINE__." : error, above node has invalid bounds/4."); return undef }
$numframes++;
} else { $log->error($anode."\n${whoami} (via $parent), line ".__LINE__." : error, above node has unexpected 'resource-id' ($resource_id), does not end in 'hotseat'."); return undef }
}
if( $numframes != 1 ){ $log->warn($doc."\n${whoami} (via $parent), line ".__LINE__." : error, failed to find exactly one node with XPath=${xpath} but found ${numframes} instead, see above xml.") }
# the screen name, it may not be there
# find a node with
# text=""
# content-desc="Screen 2 of 5"
# resource-id="com.huawei.android.launcher:id/workspace" <<<< we will filterout huawei
# class="android.view.ViewGroup"
# ONLY XPATH1 is supported, so no ends-with or matching regex, we have to filter ourselves
#my $xpath = '//node[@text=\'\' and @class=\'android.view.ViewGroup\' and ends-with(@resource-id, \'/workspace\')]';
$xpath = '//node[@text=\'\' and @text=\'\' and @class=\'android.view.ViewGroup\' and contains(@resource-id, \'/workspace\')]';
$numframes = 0; # paranoid check how many frames found?
@nodes = eval { $doc->findnodes($xpath) };
if( $@ ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'findnodes()'." has failed for this xpath: $xpath"); return undef };
foreach my $anode (@nodes){
my $resource_id = $anode->getAttribute('resource-id');
if( $resource_id =~ /\/workspace$/i ){
my $screenname = $anode->getAttribute('content-desc');
if( ! defined($screenname) || ($screenname =~ /^\s*$/) ){ $log->error("$anode\n${whoami} (via $parent), line ".__LINE__." : error, above node has the right class (android.widget.TextView) but its text is empty and it should have been the screen-n...
$self->set('screen-name', $screenname);
$numframes++;
}
}
if( $numframes != 1 ){ $log->warn($doc."\n${whoami} (via $parent), line ".__LINE__." : error, failed to find exactly one node with XPath=${xpath} but found ${numframes} instead, see above xml.") }
# now search for the apps
# text=""
# resource-id="com.huawei.android.launcher:id/workspace_screen"
# class="android.view.ViewGroup"
# content-desc=""
# and then it has a child of
# class="android.widget.TextView"
# content-desc=""
# resource-id=""
# text="<appname>"
$xpath = '//node[@text=\'\' and @class=\'android.view.ViewGroup\' and @content-desc=\'\' and contains(@resource-id, \'id/workspace_screen\')]/node[@class=\'android.view.ViewGroup\']/node[@class=\'android.widget.TextView\']';
@nodes = eval { $doc->findnodes($xpath) };
if( $@ ){ $log->error("${whoami} (via $parent), line ".__LINE__." : error, call to ".'findnodes()'." has failed for this xpath: $xpath"); return undef };
my %apps = ();
foreach my $anode (@nodes){
my $class = $anode->getAttribute('class');
if( $class =~ /^android.widget.TextView$/ ){
# the app-icons space is inside a frame
my $appname = $anode->getAttribute('text');
if( ! defined($appname) || ($appname =~ /^\s*$/) ){ $log->error("$anode\n${whoami} (via $parent), line ".__LINE__." : error, above node has the right class (android.widget.TextView) but its text is empty and it should have been the app-name inste...
my $bounds = $anode->getAttribute('bounds');
$bounds =~ s/\s+//;
if( $bounds =~ /^\[(\d+),(\d+)\]\[(\d+),(\d+)\]$/ ){
$apps{$appname} = [$1,$2,$3,$4];
} else { $log->error($anode."\n${whoami} (via $parent), line ".__LINE__." : error, above node has invalid bounds/4."); return undef }
} else { $log->error($anode."\n${whoami} (via $parent), line ".__LINE__." : error, above node has unexpected 'class', it is not 'android.widget.TextView'."); return undef }
}
$self->set('apps', \%apps);
( run in 0.378 second using v1.01-cache-2.11-cpan-e1769b4cff6 )