RAD Studio 10.3.x Rio’s Android Intent support (or current lack thereof) by Brian Long

emailx45

Местный
Регистрация
5 Май 2008
Сообщения
3,571
Реакции
2,438
Credits
573
RAD Studio 10.3.x Rio’s Android Intent support (or current lack thereof)
Brian Long - 08/Dec/2018
[SHOWTOGROUPS=4,20]
Sometimes when a new product is released there are a few ‘teething issues’. That certainly seems to be the case with RAD Studio 10.3 Rio. Both Delphi and C++Builder are hitting a few problems on various fronts. Now, it is true that internally in the product there has been a lot of change in the IDE, the VCL and FireMonkey, and perhaps it is therefore unsurprising a few slip-ups will have occurred.

It is, however, quite annoying when you fall foul of these slip-ups and have to wait for a fix….

The issue I want to address in this post is the breakage in the Android support for registering an interest in knowing about certain Для просмотра ссылки Войди или Зарегистрируйся objects received by the app. This is normally achieved by a call to MainActivity.registerIntentAction, as pseudo-documented Для просмотра ссылки Войди или Зарегистрируйся (when it was introduced in RAD Studio 10 Seattle) and Для просмотра ссылки Войди или Зарегистрируйся (in reference to a sample app) on Embarcadero's docwiki and illustrated Для просмотра ссылки Войди или Зарегистрируйся.

This new Intent support worked nicely in RAD Studio 10 Seattle, 10.1 Berlin and 10.2 Tokyo. Not so in RAD Studio 10.3 Rio. You get a crash when trying to register a new Intent that you want to act upon.

This issue has already been reported twice, once Для просмотра ссылки Войди или Зарегистрируйся and again Для просмотра ссылки Войди или Зарегистрируйся. I’ve had direct contact from someone using my NFC ode who has hit this problem. The cause of the problem was an oversight in a change made to the Java code underlying the FMX Android integration during a refactoring exercise. This is highlighted in the RSP-21841 report by Dave Nottage.

In short an array used to hold the list of registered Intents is now set up as an immutable array instead of a mutable array and this leads to the following unsavoury response to any call to MainActivity.registerIntentAction:

1589076965155.png

So, while we await an official fix for this can we generate an unofficial fix? Yes! And what’s more it doesn’t take much effort.

The steps below assume a default installation with default folders and so on. You’ll need to change any folders that you customised.

1) First things first, download and install Для просмотра ссылки Войди или Зарегистрируйся: December 2018 Missing Files Patch for 10.3. That then gives is the full set of Android Java files within RAD Studio.

Now we are going to correct the error and rebuild fmx.jar and fmx.dex.jar, which contain the errant code.
2) Make a backup of fmx.jar and fmx.dex.jar from these two folders (so 4 files in total being backed up):
  • C:\Program Files (x86)\Embarcadero\Studio\20.0\lib\android\debug
  • C:\Program Files (x86)\Embarcadero\Studio\20.0\lib\android\release
The next step is to fix the broken Java source code. The source file in question is in the Program Files (x86) folder tree and so can’t be edited normally. You need to run a text editor (for example RAD Studio or Notepad++) as administrator in order to be allowed to do that.

3) Anyway, open up C:\Program Files (x86)\Embarcadero\Studio\20.0\source\rtl\androiddex\java\fmx\src\com\embarcadero\firemonkey\FMXNativeActivity.java.
3a) Now locate the declaration of the field mRegisteredIntentActions, which is currently declared and (wrongly) initialised like this:
Код:
private List<String> mRegisteredIntentActions = Arrays.asList(
NotificationInfo.ACTION_NOTIFICATION,
  NotificationPublisher.ACTION_GCM_NOTIFICATION);

Change this to:
Код:
private List<String> mRegisteredIntentActions;

3b) Next find where the onCreate method calls it inherited version with this statement:
Код:
super.onCreate(savedInstanceState);
Precede that with these three statements:
mRegisteredIntentActions = new java.util.ArrayList<String>();
mRegisteredIntentActions.add(NotificationInfo.ACTION_NOTIFICATION);
mRegisteredIntentActions.add(NotificationPublisher.ACTION_GCM_NOTIFICATION);

That’s the code sorted out.

4) Now that’s done you should save the batch script shown at the end of this post in a text file somewhere (it doesn’t matter where) called BuildFMX.bat. Note that it’s important to ensure the file is stored as either a .bat file or a .cmd file if you prefer – if your Windows File Explorer is still left with its default options you won’t see file extensions and it’s easy to go wrong… I’ll work on the assumption you have saved it into a folder called C:\Scripts as C:\Scripts\BuildFMX.bat
Please ensure that all the paths used to set up variables at the start of the script are valid for your system. They certainly work on mine, and mine was a fresh default Delphi installation on a clean VM. In particular, check these are correct:
  • BDS
  • JAVA_PATH
  • SDK_PATH - for me with my ISO install this path needs to be:
    C:\Users\Public\Documents\Embarcadero\Studio\20.0\PlatformSDKs\android-sdk-windows
    but I gather you may perhaps find your SDK is installed to:
    C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.32429.4364
  • ANDROID_JAR - it may be that you have a different platform folder containing your android.jar file
[ Apologies for the lack of eye-pleasing syntax highlighting in the rendering of the script – I don’t really have time to sort out the blog gadgets to make it display nicer, so it’ll just have to do! ]

5) The final job is to run the batch file BuildFMX.bat. Since it needs to generate and update files in the protected Program Files (x86) folder you will need to run up an administrative command prompt. The easiest way to do this is to press the Windows key (ÿ), type cmd and press Ctrl+Shift+Enter. This will run cmd.exe as Administrator.
Change to the folder where you stored the batch file, e.g.:
Код:
cd C:\Scripts
Now run the script:
BuildFMX

You should see this:

1589076965199.png

Just clean your project (right click the output file in the Project Manager and choose Clean) and things will be back as they should be – you can register to respond to Intents as you might’ve expected to be able to all along.

Here’s the batch script to be saved into a batch file [ BTW, hat tip to my friend coma_g for employing his Ninja batch script skills to fix my for loop ]:
Код:
[ Updated 10/12/2018: added error checking (and reporting) on the environment variables, as this has tripped up one or two people ]
[ Updated 11/12/2018: changed the script to check both likely install paths for the Android SDK before bailing out ]

Код:
@echo off
cls

setlocal enabledelayedexpansion

rem Set environment variables
rem *NOTE*: check these folders match your setup

set BDS=%ProgramFiles(x86)%\Embarcadero\Studio\20.0
set JAVA_PATH=%ProgramFiles%\Java\jdk1.8.0_60\bin
rem This is the default path for the Android SDK when installed from the .iso installer
set SDK_PATH=%PUBLIC%\Documents\Embarcadero\Studio\20.0\PlatformSDKs\android-sdk-windows
if not exist "%SDK_PATH%\" (
rem This is the default path for the Android SDK when installed from the web install (aka ESD install)
set SDK_PATH=%PUBLIC%\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidSDK-2525_20.0.32429.4364
)

rem Set more environment variables based on those above

set DX_PATH=%SDK_PATH%\build-tools\28.0.2
set ANDROID_JAR=%SDK_PATH%\platforms\android-26\android.jar
set BDS_LIB=%BDS%\lib
set BDS_DEBUG_LIB=%BDS%\lib\android\debug
set BDS_RELEASE_LIB=%BDS%\lib\android\release
set FMX_SRC_PATH=%BDS%\source\rtl\androiddex\java\fmx
set CLASS_PATH=%ANDROID_JAR%
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\android-support-v4.jar
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\cloud-messaging.jar
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\google-play-services-base-7.0.0.jar
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\google-play-services-maps-7.0.0.jar
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\google-play-services-ads-7.0.0.jar

echo.
echo Checking environment variables

if not exist "%BDS%\" (
echo Path used to set BDS environment variable does not exist^^! Is RAD Studio installed elsewhere?
goto :Error
)

if not exist "%JAVA_PATH%\" (
echo Path used to set JAVA_PATH environment variable does not exist^^! Is the JDK installed elsewhere?
goto :Error
)

if not exist "%SDK_PATH%\" (
echo Path used to set SDK_PATH environment variable does not exist^^! Is the Android SDK installed elsewhere?
goto :Error
)

if not exist "%ANDROID_JAR%" (
echo Path used to set ANDROID_JAR environment variable does not exist^^! Is your android.jar in a different platform folder?
goto :Error
)

echo.
echo Changing to the FMX source folder
echo.

pushd %FMX_SRC_PATH%

echo Getting fully qualified list of all Java source file we need to rebuild
echo.

if not exist bin\classes mkdir bin\classes
if not exist bin\debug mkdir bin\debug
if not exist bin\release mkdir bin\release
dir src\android\bluetooth\*.java /s /b > JavaSources.txt
dir src\android\telephony\*.java /s /b >> JavaSources.txt
dir src\com\*.java /s /b >> JavaSources.txt

echo Ensuring FMX source path ends in a '\'
echo.

set LAST_CHAR=%FMX_SRC_PATH:~-1%
if not "%LAST_CHAR%"=="\" set FMX_SRC_PATH=%FMX_SRC_PATH%\

echo Making Java source file paths relative to current directory
echo.

if exist JavaSources2.txt del JavaSources2.txt
for /F "tokens=*" %%A in (JavaSources.txt) do (
set STR=%%A
set "STR=!STR:%FMX_SRC_PATH%=!"
echo !STR!>>JavaSources2.txt
)

echo Compiling all the FMX Java code into class files with debug info
echo.

"%JAVA_PATH%"\javac -d bin\classes -classpath "%CLASS_PATH%" -encoding UTF-8 -g @JavaSources2.txt
if errorlevel 1 (
echo.
echo Problem encountered during Java compilation
goto :Error
)

echo.
echo Creating jar containing the new compiled FMX Java classes with debug info
echo.

"%JAVA_PATH%"\jar cf bin\debug\fmx.jar -C bin\classes .
if errorlevel 1 (
echo.
echo Problem encountered during Java archiving
goto :Error
)

echo Creating DEX jar containing the new compiled FMX Java classes with debug info
echo.

call %DX_PATH%\dx --dex --output=bin\debug\fmx.dex.jar --positions=lines bin\debug\fmx.jar
if errorlevel 1 (
echo.
echo Problem encountered during DEXing
goto :Error
)

echo Compiling all the FMX Java code into class files without debug info
echo.

"%JAVA_PATH%"\javac -d bin\classes -classpath "%CLASS_PATH%" -encoding UTF-8 @JavaSources2.txt
if errorlevel 1 (
echo.
echo Problem encountered during Java compilation
goto :Error
)

echo.
echo Creating jar containing the new compiled FMX Java classes without debug info
echo.

"%JAVA_PATH%"\jar cf bin\release\fmx.jar -C bin\classes .
if errorlevel 1 (
echo.
echo Problem encountered during Java archiving
goto :Error
)

echo Creating DEX jar containing the new compiled FMX Java classes without debug info
echo.

call %DX_PATH%\dx --dex --output=bin\release\fmx.dex.jar --positions=lines bin\release\fmx.jar
if errorlevel 1 (
echo.
echo Problem encountered during DEXing
goto :Error
)

copy bin\debug\* "%BDS_DEBUG_LIB%"
copy bin\release\* "%BDS_RELEASE_LIB%"

echo Tidying up...
echo.
if exist JavaSources.txt del JavaSources.txt
if exist JavaSources2.txt del JavaSources2.txt
rd /s /q bin

goto :End

:Error
echo.
echo Sorry, we had a problem :(
echo.

:End

echo Changing back to the folder we started in

popd

endlocal
[/SHOWTOGROUPS]