前面6节介绍了Delphi中消息机制的基本原理,并通过一个演示程序进行实际演示。本节开始,我讲介绍Delphi开发Android系统时需要使用的一些特殊消息。以下所说系统,泛指Android系统。
一、问题的提出:
- App中主动调用android系统中蓝牙打开功能,如何知道用户是否真的打开了蓝牙?
- App运行的过程中,如何自动感知用户的某些操作,例如:打开或者关闭蓝牙功能、打开或者关闭WIFI功能等?
二、问题的解决:
首先我们解决第一个问题,App中主动调用android系统中蓝牙打开功能,如何知道用户是否真的打开了蓝牙?如下图,程序检测到系统没有打开蓝牙功能,用户按下【立即打开蓝牙功能】,系统会启动打开蓝牙功能的界面,就是下图中最下面的“APP_BOX应用,想要打开蓝牙”白色部分,因为打开蓝牙需要用户同意,所以系统会显示如下选择界面。请注意,下面的白色部分不是我们App显示的,是系统自己提示的。用户可以选择拒绝或者允许。问题来了,我们App如何获取用户的选择?如果我们能够获取到用户的选择结果,那么我们会根据用户的不同选择进行提示,这样是不是我们的App就会非常的友好?答案是当然的!(这个界面是小米手机 android 10版本的显示,不同的的android版本,界面可能略有不同,应该一看就明白)。
在解决第一个问题的时候,必须首先要解决的是如何在我们的App中发起系统打开蓝牙的功能,这个不是重点,所以只列出代码。
App打开蓝牙功能的代码:
uses
...
Androidapi.JNI.Bluetooth,
Androidapi.JNI.GraphicsContentViewText;
Intent := TJIntent.JavaClass.init(TJBluetoothAdapter.JavaClass.ACTION_REQUEST_ENABLE);
//打开设置界面
TAndroidHelper.Activity.startActivityForResult(intent, FS_BlueTooth_Code);
//TAndroidHelper.Activity.startActivity(Intent);
需要注意以上代码,我们使用的是startActivityForResult而不是startActivity,如果使用startActivity我们的App将无法获取到用户选择的结果。这两个函数有一个区别就是startActivityForResult 需要一个消息代码参数FS_BlueTooth_Code,这个参数就是我们需要接收android系统通知消息的关键,从这个参数我们就知道是打开蓝牙功能。
如果我们通过 startActivityForResult发起打开蓝牙调用,Android系统将会按照广播消息的机制把用户选择的结果通知到App,使用的是我们前面讲的RTL消息机制。非常关键的就是Android系统使用的一个在Androidapi.Helpers.pas单元中定义的专用消息类TMessageResultNotification。
{ TMessageResultNotification }
type
TMessageResultNotification = class(TMessage<JIntent>)
public
RequestCode: Integer;
ResultCode: Integer;
end;
其中RequestCode就是我们调用蓝牙打开功能时使用的FS_BlueTooth_Code。
//打开设置界面
TAndroidHelper.Activity.startActivityForResult(intent, FS_BlueTooth_Code);
ResultCode就表示用户最终选择的结果。通过以上的分析,现在如果需要获取用户的选择就很清楚了,我们注册一个TMessageResultNotification消息接收器,就可以接收到用户的选择了。
var
Intent : JIntent;
begin
//1. 注册消息接收
FS_FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage
(TMessageResultNotification, FS_HandleActivityMessage);
Intent := TJIntent.JavaClass.init(TJBluetoothAdapter.JavaClass.ACTION_REQUEST_ENABLE);
//2. 打开设置界面
TAndroidHelper.Activity.startActivityForResult(intent, FS_BlueTooth_Code);
//TAndroidHelper.Activity.startActivity(Intent);
end;
监听接收器处理函数:FS_HandleActivityMessage调用实际的处理函数FS_OnActivityResult
procedure TClassic_BlueTooth.FS_HandleActivityMessage(
const Sender: TObject; const M: TMessage);
begin
if M is TMessageResultNotification then
begin
FS_OnActivityResult(TMessageResultNotification(M).RequestCode,
TMessageResultNotification(M).ResultCode,
TMessageResultNotification(M).Value);
end;
end;
实际的处理函数:FS_OnActivityResult
function TClassic_BlueTooth.FS_OnActivityResult(RequestCode,
ResultCode: Integer; Data: JIntent): Boolean;
begin
//解除消息接收,因为已经得到结果了
TMessageManager.DefaultManager.Unsubscribe(TMessageResultNotification, FS_FMessageSubscriptionID);
FS_FMessageSubscriptionID := 0;
//这一句用来判断是不是我们发起的 Intent
if RequestCode <> FS_BlueTooth_Code then
Exit(False);
Result := ResultCode = TJActivity.JavaClass.RESULT_OK; //表示蓝牙打开
try
FBlueProc(Result);
except on E: Exception do
end;
end;
函数FS_OnActivityResult的执行结果True表示用户打开了蓝牙功能,False表示用户拒绝打开蓝牙功能。无论用户时选择拒绝还是不进行任何选择,结果都是False,只有用户点允许才会返回True。
总结:
- 调用系统功能使用startActivityForResult函数;
- 必须订阅(注册)TMessageResultNotification专用消息(用于Intent);
- 通过ResultCode = TJActivity.JavaClass.RESULT_OK来判断用户选择结果;
- 蓝牙功能是比较典型的,这里演示的是一个Intent消息;
- 只要系统的选择界面出现,如果用户不进行任何选择,我们的程序是失活的。
下一节:【Delphi】中使用消息Messages(八)Android 系统消息2
如果本文对你有帮助,请点赞👍👍! 如果有不明白的地方,可以与我交流,共同学习。