Android-Build

 view release on metacpan or  search on metacpan

lib/Android/Build.pm  view on Meta::CPAN

my $permissions =                                                               # Default permissions
   [qw(INTERNET ACCESS_WIFI_STATE ACCESS_NETWORK_STATE WRITE_EXTERNAL_STORAGE),
    qw(READ_EXTERNAL_STORAGE RECEIVE_BOOT_COMPLETED)];
my $version     = strftime('%Y%m%d', localtime);                                # Version number without dots
my $javaTarget  = 7;                                                            # Java release level to target

#-------------------------------------------------------------------------------
# Private methods
#-------------------------------------------------------------------------------

sub getSDKLevels($)                                                             # File name of Android jar for linting
 {my ($android) = @_;                                                           # Android build
  my $l = $android->sdkLevels;
  return @$l if $l and @$l;
  (15,25)
 }

sub getInstructions                                                             # How to get the build tools
 {<<END
Download the Linux tools as specified at the end of page:

lib/Android/Build.pm  view on Meta::CPAN

containing the Android SDK platform tools.  You can get these tools from:

END
  -d $f or confess <<END;
Cannot find platformTools folder:
$f
END
  $f
 }

sub getDevice($)                                                                # Device to be used
 {my ($android) = @_;
  my $d = $android->device;
  return '-e' unless $d;
  return $d if $d =~ m(\A-)s;
  "-s $d"
 }

sub getAndroidJar($)                                                            # File name of Android jar for linting
 {my ($android) = @_;
  my $p = $android->getPlatform;
  my $a = filePath($p, qw(android.jar));
  -e $a or confess "Cannot find android.jar via file:\n$a\n";
  $a
 }

sub getPackage                                                                  # Get and validate the package name for this app
 {my ($a) = @_;
  my $d = $a->package;

lib/Android/Build.pm  view on Meta::CPAN

sub apk                                                                         # Apk name - with full path
 {my ($a) = @_;
  $a->getBinFolder.$a->apkFileName;
 }

sub getVersion                                                                  # Version of the app or default to today's date
 {my ($a) = @_;
  $a->version // $version;
 }

sub buildArea($)                                                                # Build folder name
 {my ($a) = @_;
  $a->buildFolder // '/tmp/app/'                                                # Either the user supplied build folder name or the default
 }

sub getAssFolder($)     {my ($a) = @_; $a->buildArea.'assets/'}                 # Assets folder name
sub getBinFolder($)     {my ($a) = @_; $a->buildArea.'bin/'}                    # Bin folder name
sub getGenFolder($)     {my ($a) = @_; $a->buildArea.'gen/'}                    # Gen folder name
sub getResFolder($)     {my ($a) = @_; $a->buildArea.'res/'}                    # Res folder name
sub getManifestFile($)  {my ($a) = @_; $a->buildArea.'AndroidManifest.xml'}     # Name of manifest file

sub logMessage($@)                                                              # Log a message
 {my ($android, @message) = @_;
  my $s = join '', grep {$_} @message;
  chomp($s) if $s =~ /\n\Z/;
  push @{$android->log}, $s;
  say STDERR $s if -t STDERR;
 }

#-------------------------------------------------------------------------------
# Create icons for app
#-------------------------------------------------------------------------------

lib/Android/Build.pm  view on Meta::CPAN

</manifest>
END
  $manifest =~ s/android:debuggable="true"//gs unless $android->debug;
  overWriteFile($man, $manifest);
 }

#-------------------------------------------------------------------------------
# Create resources for app
#-------------------------------------------------------------------------------

sub resources()
 {my ($android)  = @_;
  my $title      = $android->getTitle;
  my $version    = $android->getVersion;
  my $parameters = $android->parameters // '';
  my $package    = $android->getPackage;
  my $res        = $android->getResFolder;
  my $strings    = sub
   {return qq(<string name="parameters">$parameters</string>)
      unless ref $parameters;
    my $s = '';

lib/Android/Build.pm  view on Meta::CPAN

# Make app
#-------------------------------------------------------------------------------

sub getAdb
 {my ($android) = @_;
  filePath($android->getPlatformTools, qw(adb))
 }

my $confirmRequiredUtilitiesAreInPosition;

sub confirmRequiredUtilitiesAreInPosition($)                                    # Confirm required utilities are in position
 {my ($android)  = @_;
  return if $confirmRequiredUtilitiesAreInPosition++;                           # Only do this once per run

  my $buildTools   = $android->getBuildTools;
  my $adb          = $android->getAdb;
  my $aapt         = filePath($buildTools, qw(aapt));
  my $dx           = filePath($buildTools, qw(dx));
  my $zipAlign     = filePath($buildTools, qw(zipalign));

  zzz("$aapt version", qr(Android Asset Packaging Tool), 0,
      "aapt not found at:\n$aapt");
  zzz("$adb version", qr(Android Debug Bridge), 0, "adb not found at:\n$adb");
  zzz("$dx --version", qr(dx version), 0, "dx not found at:\n$dx");
  zzz("jarsigner", qr(Usage: jarsigner), 0, "jarsigner not found");
  zzz("javac -version", qr(javac), 0, "javac not found");
  zzz("zip -v", qr(Info-ZIP), 0, "zip not found\n");
  zzz("$zipAlign", 0, 2, "zipalign not found at:\n$zipAlign");
 }

sub signApkFile($$)                                                             # Sign an apk file
 {my ($android, $apkFile) = @_;                                                 # Android, apk file to sign
  $android->confirmRequiredUtilitiesAreInPosition;

  my $keyStoreFile = $android->keyStoreFileX;
  -e $keyStoreFile or confess"Key store file does not exists:\n$keyStoreFile\n";
  my $keyAlias     = $android->keyAliasX;
  my $keyStorePwd  = $android->keyStorePwd;

  my $alg = $android->debug ? '' : "-sigalg SHA1withRSA -digestalg SHA1";

lib/Android/Build.pm  view on Meta::CPAN

    zzz(qq(cd $assetsFolder && cd .. && zip -rv $apj assets));                  # Add assets to apk
   }

  $android->signApkFile($apj);                                                  # Sign the apk file

  zzz("$zipAlign -f 4 $apj $apk");                                              # Zip align

  unlink $_ for $api, $apj;                                                     # Remove intermediate apks
 }

sub cloneApk2($$)                                                               # Clone an apk file: copy the apk, replace the L<assets|assets/>, re-sign, zipalign, return the name of the newly created apk file.
 {my ($android, $oldApk) = @_;                                                  # Android, file name of apk to be cloned
  $android->confirmRequiredUtilitiesAreInPosition;

  confess "Old apk file name not supplied\n"   unless    $oldApk;
  confess "Old apk does not exist:\n$oldApk\n" unless -e $oldApk;

  my $buildTools   = $android->getBuildTools;
  my $zipAlign     = filePath($buildTools, qw(zipalign));

  my $tempFolder = temporaryFolder;                                             # Temporary folder to unzip into

lib/Android/Build.pm  view on Meta::CPAN


  my $newApk = fpe(temporaryFile, q(apk));                                      # New apk
  zzz("$zipAlign -f 4 $tmpApk $newApk", 0, 0, "Unable to zipalign");            # Zip align

  unlink $tmpApk;                                                               # Clean up
  clearFolder($tempFolder, 100);

  return $newApk;
 }

sub compile2($)                                                                 #P Compile the app
 {my ($android) = @_;                                                           # Android build
  $android->create;
  $android->make;                                                               # Compile the app
 }

sub install2($)                                                                 #P Install an already L<compiled|/compile> app on the selected L<device|/device>:
 {my ($android)  = @_;                                                          # Android build
  my $apk        = $android->apk;
  my $device     = $android->getDevice;
  my $package    = $android->getPackage;
  my $activity   = $android->activityX;
  my $adb        = $android->getAdb." $device ";
# say STDERR "Install app";
  zzz("$adb install -r $apk");
# say STDERR "Start app";
  zzz("$adb shell am start $package/.Activity");
# say STDERR "App installed and started";
 }

sub lint2($)                                                                    #P Lint all the source code java files for the app
 {my ($android)  = @_;                                                          # Android build
  my $src        = $android->getLintFile;
  my $androidJar = $android->getAndroidJar;
  my $area       = $android->classes // 'Classes';
  makePath($area);
  zzz("javac *.java -d $area -cp $androidJar:$area");                           # Android, plus locally created classes
 }

#1 Methods and attributes

sub new()                                                                       #S Create a new build.
 {bless{action     =>qq(run),
        activity   =>qw(Activity),
        device     =>qq(emulator-5554),
        home       =>$home,
        icon       =>'icon.png',
        log        =>[],
        parameters =>'',
        permissions=>$permissions,
        version    =>$version};
 }

lib/Android/Build.pm  view on Meta::CPAN

  genLValueScalarMethods(qw(platform));                                         # Folder containing B<android.jar>. For example B<~/Android/sdk/platforms/25.0.2>
  genLValueScalarMethods(qw(platformTools));                                    # Folder containing L<adb|https://developer.android.com/studio/command-line/adb.html>
  genLValueArrayMethods (qw(sdkLevels));                                        # [minSdkVersion, targetSdkVersion], default is [15, 25]
  genLValueArrayMethods (qw(src));                                              # A reference to an array of java source files to be compiled to create this app.
  genLValueScalarMethods(qw(title));                                            # Title of app, the default is the L<package|/package> name of the app.
  genLValueScalarMethods(qw(titles));                                           # A hash of translated titles: {ISO::639 2 digit language code=>title in that language}* for this app.
  genLValueScalarMethods(qw(verifyApk));                                        # Verify the signed apk if this is true.
  genLValueScalarMethods(qw(version));                                          # The version number of the app. Default is today's date, formatted as B<YYYYMMDD>
 }

sub compile($)                                                                  # Compile the app.
 {my ($android)  = @_;                                                          # Android build
  eval {&compile2(@_)};
  if ($@)
   {$android->logMessage($@);
    return $@;
   }
  undef                                                                         # No errors encountered
 }

sub cloneApk($$)                                                                # Clone an apk file: copy the existing apk, replace the L<assets|/assets>, re-sign, zipalign, return the name of the newly created apk file.
 {my ($android, $oldApk) = @_;                                                  # Android build, the file name of the apk to be cloned
  &cloneApk2(@_);
 }

sub lint($)                                                                     # Lint all the Java source code files for the app.
 {my ($android)  = @_;                                                          # Android build
  eval {&lint2(@_)};
  if ($@)
   {$android->logMessage($@);
    return $@;
   }
  undef                                                                         # No errors encountered
 }

sub install($)                                                                  # Install an already L<compiled|/compile> app on to the selected L<device|/device>
 {my ($android)  = @_;                                                          # Android build
  eval {&install2(@_)};
  if ($@)
   {$android->logMessage($@);
    return $@;
   }
  undef                                                                         # No errors encountered
 }

sub run($)                                                                      # L<Compile|/compile> the app, L<install|/install> and then run it on the selected L<device|/device>
 {my ($android)  = @_;                                                          # Android build
  for(qw(compile install))                                                      # Compile, install and run
   {my $r = $android->$_;
    return $r if $r;
   }
  undef                                                                         # No errors encountered
 }

# podDocumentation



( run in 0.654 second using v1.01-cache-2.11-cpan-65fba6d93b7 )