问题
I am in the process of upgrading from Delphi 10.2.3 to 10.3.3. My android apps are now not generating an OnKeyDown event from the virtual keyboard for the Return key. I have confirmed this using a very basic newly created project so it is nothing to do with the conversion from 10.2.3 it seems.
Any ideas would be appreciated.
QA at embarcadero have come back with the following response:
"According to this documentation - Handle keyboard actions or this - KeyEvent :
When handling keyboard events with the KeyEvent class and related APIs, you should expect that such keyboard events come only from a hardware keyboard. You should never rely on receiving key events for any key on a soft input method (an on-screen keyboard).
I think that using methods that fire up when text get changed is a sufficient workaround to this issue...
I think this Stackoverflow question and this Blogpost may be useful. "
The solution offered involves adding a TextListener to JFMXTextEditorProxy, and that latter interface has disappeared from delphi 10.3. I am currently attempting to implement something equivalent in 10.3, but would appreciate any guidance. BTW: Others will have different aims, but for my part all I want to see is the return key.
回答1:
Update: Originally this was assumed to be a bug. QA at embarcadero however take the view that it is not and one should not rely on the virtual keyboard to fire off keyboard events. But they offer no other viable alternatives. The blog post they cited is not suitable for 10.3, and it seems that it would never see the return key anyway.
I have stumbled across a workaround, which appears to work, though it too may be susceptible to future changes.
If one changes the ReturnKeyType of a Tedit to any of the values Go, Search or Send, the onkeydown event will fire for the return key. Another alternative would be to use the OnChange event. This does not fire for the return key, when the Tedit is set to Default ReturnKeyType either, but when set to any of the above values (plus Next also), it will fire. ReturnKeyType is available at design time, and can also be changed in code e.g.:
edit1.ReturnKeyType := TReturnKeyType.Go;
And if really desperate, I have observed that the OnChange event will fire if the contents of the edit have indeed changed and one uses the Android "back" button to dismiss the virtual keyboard.
回答2:
To address the various things that have come up in this discussion:
- RSP-27496 has been re-opened
- You can fix the issue by making an edit to C:\Program Files (x86)\Embarcadero\Studio\20.0\source\rtl\androiddex\java\fmx\src\com\embarcadero\firemonkey\text\FMXEditText.java and rebuilding the Java files required by Delphi Android apps. This allows the Return key to get
OnKeyDown
andOnKeyUp
events as required, without having to use TomB's workaround.
What edit to make to FMXEditText.java
In the method onEditorAction
, which has just an if statement with code in both the if and else branches, take the code out of the else branch and make it unconditional.
In other words, where it says (and I'm posting a representative code snippet rather than pasting the actual code to avoid being accused of doing 'naughty' things):
public void onEditorAction(int actionCode) {
if (condition) {
// if block
} else {
// else block
}
}
change it to say:
public void onEditorAction(int actionCode) {
if (condition) {
// if block
}
// else block
}
How to rebuild the Java RTL files
This bit is a little complicated to go into detail on here, but what you need is a command script that will basically do the job for you. For fixing a Java issue in 10.3.0 I had a command script available on a blog post here in amongst discussion of the issue being fixed, and for 10.3.3 a post solely for how to rebuild the Java files can be found here.
However, to avoid the comments about solutions on external links being inappropriate as those links may evaporate over time, here is the full command script. Check all the paths being plumbed into the variables are correct, store the script in a file called BuildFMX.cmd, run an administrative command prompt and invoke the script from there:
@echo off
cls
rem Android RTL Java files rebuilder for RAD Studio 10.3.3
setlocal enabledelayedexpansion
rem Set environment variables
rem *NOTE*: check these folders match your setup
set EMBT=Embarcadero\Studio\20.0
set BDS=%ProgramFiles(x86)%\%EMBT%
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\%EMBT%\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\%EMBT%\CatalogRepository\AndroidSDK-2525_20.0.36039.7899
)
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%\com-google-android-gms.play-services-base.16.0.1.jar
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\com-google-android-gms.play-services-maps.16.1.0.jar
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\debug\com-google-android-gms.play-services-ads.17.2.0.jar
rem For adListener
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\com-google-android-gms.play-services-ads-lite.17.2.0.jar
rem For AbstractSafeParcelable
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\com-google-android-gms.play-services-basement.16.2.0.jar
rem For ReflectedParcelable
set CLASS_PATH=%CLASS_PATH%;%BDS_DEBUG_LIB%\com-google-android-gms.play-services-basement.16.2.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 -g -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 -g:none -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
来源:https://stackoverflow.com/questions/59851405/no-onkeydown-event-for-return-key-on-delphi-android-10-3-3