Saturday, 14 October 2017

Delphi build/install/launch Android app from the command-line

Quite some while back I answered a question on Stack Overflow, which explained how to build a Delphi project from the command line and also how to deploy it. The context of the question was Andriod development

In the case of an Android application deploying it has absolutely nothing to do with installing the resultant .apk file onto your Android device, despite what your personal interpretation of the word may be. Oh no, most definitely not.

Instead, deployment is about packaging up all your various files - your compiled Android library (a .so file), all the images, splash screens, icons, custom files, databases, application manifest file and so forth – all into an .apk file. In other words as far as the Delphi IDE is concerned, deploying a Delphi project means going from a .so native ARM library to an installable .apk file.

Clearly when you press F9 or Ctrl+Shift+F9 to run your application the IDE works out how to install your .apk on the currently connected and selected device, but that is subsequent to the IDE’s notion of the deployment step.

So, installation notwithstanding, that SO answer shows how to make/build and deploy a Delphi project, such as an Android project, from a RAD Studio command prompt:

To recap on it this does a build:

msbuild Foo.dproj /p:Config=Debug /p:Platform=Android /t:Build

This does a make, which only compiles files that have changed:

msbuild Foo.dproj /p:Config=Debug /p:Platform=Android /t:Make

This step, assuming you have done a deployment at least once in the IDE and thereby have had a Foo.deployproj file generated, will do the deployment:

msbuild Foo.dproj /p:Config=Debug /p:Platform=Android /t:Deploy

If you have the .deployproj file you can combine the two steps in this one command (excuse any line wrapping this blog theme applies):

msbuild Foo.dproj /p:Config=Debug /p:Platform=Android /t:Make;Deploy

[Update – 16/10/2-17:

I also bumped into the property that controls the Target Configuration, which can be Development or Application Store for Android. The BT_BuildType can either be Debug or AppStore for Android (for iOS there is also AdHoc. So if you want to build a signed app ready for upload to the Google Play store you could run:

msbuild Foo.dproj /p:Config=Release /p:Platform=Android /t:Make;Deploy /p:BT_BuildType=AppStore

End Update ]

So anyway, history to one side, I was wondering if there was another MSBuild target that did the installation, or if this was some custom code in the IDE, not exposed through MSBuild. My investigation suggests the latter to be the case, but I wanted a convenient command-line way to make, deploy and install the Android application (and even possibly launch it!).

The best option I could rustle up at short notice was a batch file (or command script, if you prefer). Save the file below as BuildAndInstall.bat or BuildAndInstall.cmd, set up any of the paths etc. that need personalising to your system.

Again, please excuse unsolicited line wrapping…. There is probably a nifty way to get this code into a horizontally scrollable div or similar, but I don’t have the time to do the research just now….

@echo off
rem Syntax
rem  Arg 1 = project name
rem  Arg 2 (optional) = build configuration
rem  Arg 3 (optional) = package name
set ANDROID_SDK=%PUBLIC%\Documents\Embarcadero\Studio\19.0\PlatformSDKs\android-sdk-windows
set ADB=%ANDROID_SDK%\platform-tools\adb.exe
set FQ_PROJECT=%~f1
set PROJECT_DIR=%~p1
set PROJECT_NAME=%~n1
set PACKAGE_NAME=com.embarcadero.%PROJECT_NAME%
set CONFIG=Debug
if X%1 == X goto syntax
if not exist %1 (
  echo Cannot locate project %FQ_PROJECT%
  goto :EOF
)
if not X%2 == X (
  if "%2" == "Release" set CONFIG=Release
)
if not X%3 == X (
  set PACKAGE_NAME=%3
)
pushd %PROJECT_DIR%
echo.&echo Building %1&echo.
msbuild %PROJECT_NAME%.dproj /p:Config=%CONFIG% /p:Platform=Android /t:Make || goto build_error
echo.&echo Deploying %1&echo.
msbuild %PROJECT_NAME%.dproj /p:Config=%CONFIG% /p:Platform=Android /t:Deploy || goto deploy_error
echo.&echo Installing Android package&echo.
%ADB% install -r Android\%CONFIG%\%PROJECT_NAME%\bin\%PROJECT_NAME%.apk || goto install_error
echo.&echo Launching Android app&echo.
%ADB% -d shell am start -a android.intent.action.MAIN -n %PACKAGE_NAME%/com.embarcadero.firemonkey.FMXNativeActivity || goto launch_error
popd
echo.&echo Done!
goto :EOF
:syntax
echo BuildAndInstall syntax:
echo.
echo   BuildAndInstall ^<DelphiProjectFile^> [^<Configuration^> [^<AndroidPackageName^>]]
echo.
echo where:
echo.
echo ^<DelphiprojectFile^> is a Delphi project.dproj file
echo ^<Configuration^> is the required build configuration, Release or Debug, which defaults to Debug
echo ^<AndroidPackageName^> is the Android package name for the project, in case it is different from com.embarcadero.project
goto :EOF
:build_error
echo Problem encountered while build the Android lib%PROJECT_NAME%.so native library
goto :EOF
:deploy_error
echo Problem encountered while creating the %PROJECT_NAME%.apk Android package
goto :EOF
:install_error
echo Problem encountered while installing %PROJECT_NAME%.apk
goto :EOF
:launch_error
echo Problem encountered while launching %PROJECT_NAME%.apk
goto :EOF

If you young pups reading this are all into relatively modern PowerShell scripting or traditional Windows scripting, then this throwback to the world of DOS may fall uneasily on the eye, but it works and there is a lot of power available in DOS scripting commands.

[ Update – 16/10/2017: I initially forgot to mention that you’d be wise to run this from a RAD Studio Command Prompt for the version of RAD Studio that you want to build your project. This ensures that the Windows search path is set up to find the correct compilers etc. Alternatively, at the top of my batch file you can do the equivalent of running a RAD Studio Command Prompt by inserting:

CALL C:\Program Files (x86)\Embarcadero\Studio\19.0\bin\rsvars.bat

If you choose this latter option then you can use any old command prompt you like.

End Update ]

Now you can install and run an Android project with a command-line of:

BuildAndInstall Foo.dproj

if you want the release build, use:

BuildAndInstall Foo.dproj Release

If you’ve changed the package name (specified as package in the project options Version Info page) from the default com.embarcadero.Foo then to launch the app you’ll need to pass the package name on the command line:

BuildAndInstall Foo.dproj Debug com.blong.Foo

Don’t forget that you will have to choose Project, Deploy libProjectname.so in the IDE menus once before this will work.

I hope this is of use to someone….