About the author
When FireMonkey became available for Android, one of the things I looked at was how logging was done.
The API to Android logging are located in Androidapi.Log, and the primary logging API is declared as such:
function __android_log_write(Priority: android_LogPriority; const Tag, Text: MarshaledAString): Integer; cdecl; external AndroidLogLib name '__android_log_write';
There is then a few additional functions declared and written like so:
function LOGI(Text: MarshaledAString): Integer; function LOGW(Text: MarshaledAString): Integer; function LOGE(Text: MarshaledAString): Integer; function LOGF(Text: MarshaledAString): Integer; function LOGI(Text: MarshaledAString): Integer; begin Result := __android_log_write(android_LogPriority.ANDROID_LOG_INFO, 'info', Text); end; function LOGW(Text: MarshaledAString): Integer; begin Result := __android_log_write(android_LogPriority.ANDROID_LOG_WARN, 'warning', Text); end; function LOGE(Text: MarshaledAString): Integer; begin Result := __android_log_write(android_LogPriority.ANDROID_LOG_ERROR, 'error', Text); end; function LOGF(Text: MarshaledAString): Integer; begin Result := __android_log_write(android_LogPriority.ANDROID_LOG_FATAL, 'fatal', Text); end;
Examine them carefully, and you'll notice that the priority portion actually tells the Android log whether a message is to be classified as info, warning, error or fatal. But if you look at the second parameter, which is supposed to be Tag, the tag is supposed to help you filter out logs. It is an application-specific parameter.
Instead, the RAD Studio team filled them in with strings of 'info', 'warning', 'error' and 'fatal', duplicating the information that the first parameter already supplied. When this was introduced in XE1 or XE2, I filed a feature requests, informing R&D that this is a bug, unfortunately, it was closed as "as designed". Well, I call this a lousy design, because the Tag parameter is supposed to be an application specific string, like your app name, so that you can distinguish it from other applications, and filter out logs from other applications.This was the reason why FixAndroidLogger was created: to fix a mistake that the RAD Studio team refuses to fix since the Android platform was introduced in RAD Studio.In the FixAndroidLogger repository, once you add the FMX.Platform.Logger.Android.Fix unit to your project, your project will have the default DELPHIFMX tag if you log messages without using any tags. If you want to use tags, you can either use the following code:
var LLogService: IFMXLoggingService; var LLogPriority: IFMXTagPriority; if TPlatformServices.Current.SupportsPlatformService(IFMXLoggingService, LLogService) and Supports(LLogService, IFMXTagPriority, LLogPriority) then begin LLogPriority.i('TagName', 'LogMessage'); // info end;
or call the __android_log_write API directly. If you want it to be an error message, use LLogPriority.e instead of i. Similarly, for verbose, use LLogPriority.v. If you use the default FireMonkey log, whenever you call IFMXLoggingService.Log with, for example, the message "Hello", you'll get a log like such:
04-28 23:08:34.192 19280 19280 I info Hello
wherelse, if you use FixAndroidLogger, with the default tag, you'll get:
04-28 23:08:34.192 19280 19280 I DELPHIFMX Hello
With the first log, you can't even tell that it's from your application. With the log produced by FixAndroidLogger, you can tell it's from a Delphi FMX application. And if your application is the only active FMX application running, then you can tell that it's yours.
Continued discussion of undocumented Delphi 8 Property Access Specifiers, and other ways of adding and removing delegates / events handlers, including clearing the list of all the delegates / event handlers.
This article discusses the new Delphi 8 property access specifiers.
A method pointer is now the same as a global procedure, ie, procedure of object = procedure.