【Delphi】中使用消息Messages(八)Android 系统消息感知
目录
一、实现android广播消息事件绑定
二、在onReceive中实现接收系统广播消息处理:
三、注册(订阅)系统状态变化消息广播:
四、控件整体定义:
在上一节我提出了两个问题:
- App中主动调用android系统中蓝牙打开功能,如何知道用户是否真的打开了蓝牙?
- App运行的过程中,如何自动感知用户的某些操作,例如:打开或者关闭蓝牙功能、打开或者关闭WIFI功能等?
其中第一个问题在上一节我们已经解决,本节来我们解决第二个问题,就是实时感知Android系统的状态变化,通过实时感知可以是我们开发的App操作流程更友好,其中就使用到Delphi中的RTL消息机制。
android系统状态的变化包括病不限于:蓝牙状态变化、WI-FI状态变化、电源状态变化、网络状态变化、屏幕点亮和关闭等等。
要实现解决第二个问题,我们的思路步骤如下:
一、实现android广播消息事件绑定
uses...Androidapi.JNIBridge,Androidapi.JNI.Embarcadero,Androidapi.JNI.GraphicsContentViewText;type// 接收系统广播通知消息类TBroadcastReceiver = class(TJavaLocal, JFMXBroadcastReceiverListener)public// 实现接收事件procedure onReceive(context: JContext; intent: JIntent); cdecl;end;
二、在onReceive中实现接收系统广播消息处理:
onReceive函数返回两个参数,一个是context,第二个是intent。我们主要关注的是intent参数,在intent参数中携带有我们需要的信息。我们在onReceive中实现了蓝牙、WIFI、电源、网络状态变化的消息处理。注意在收到系统的广播消息后,我们通过
myMessage := TMessageNotification.Create(FmyMSG);
TMessageManager.DefaultManager.SendMessage(nil,myMessage,True);
也就是RTL消息机制发送给了外边的控件对象,实际上就是我们编写的(TReceiver_State)控件。
procedure TBroadcastReceiver.onReceive(context: JContext; intent: JIntent);
varaction,S: String;iState: Integer;FmyMSG: TmyMSG;myMessage : TMessage;jo : TJSONObject;B : Boolean;
beginaction := JStringToString( intent.getAction );//网络连接广播{ 'android.net.conn.CONNECTIVITY_CHANGE'}if action = JStringToString(TJConnectivityManager.JavaClass.CONNECTIVITY_ACTION) thenbeginiState := intent.getIntExtra( TJConnectivityManager.JavaClass.EXTRA_NETWORK_TYPE,0);FmyMSG.msg_State := iState;FmyMSG.msg_TYPE := TMsgType.mtNetConnectState;jo := TJSONObject.Create;try//1、获取网络类型iState := intent.getIntExtra( TJConnectivityManager.JavaClass.EXTRA_NETWORK_TYPE,0);case iState of0 : jo.AddPair('EXTRA_NETWORK_TYPE','Mobile'); //手机流量1 : jo.AddPair('EXTRA_NETWORK_TYPE','WIFI'); //WIFI7 : jo.AddPair('EXTRA_NETWORK_TYPE','BlueTooth'); //BlueToothelse //其它jo.AddPair('EXTRA_NETWORK_TYPE','Other');end;//2、获取网络信息S := JStringToString( intent.getStringExtra(TJConnectivityManager.JavaClass.EXTRA_EXTRA_INFO));jo.AddPair('EXTRA_EXTRA_INFO',S);//3、 EXTRA_NO_CONNECTIVITYB := intent.getBooleanExtra(TJConnectivityManager.JavaClass.EXTRA_NO_CONNECTIVITY,false);if B thenjo.AddPair('EXTRA_NO_CONNECTIVITY','true')elsejo.AddPair('EXTRA_NO_CONNECTIVITY','false');FmyMSG.msg_Content := jo.ToString;finallyjo.Free;end;myMessage := TMessage<TmyMSG>.Create(FmyMSG);TMessageManager.DefaultManager.SendMessage(nil,myMessage,True);Exit;end;//1. 处理蓝牙广播消息if action = JStringToString(TJBluetoothAdapter.JavaClass.ACTION_STATE_CHANGED) thenbegin//获取蓝牙状态iState := intent.getIntExtra( TJBluetoothAdapter.JavaClass.EXTRA_STATE ,0);FmyMSG.msg_State := iState;FmyMSG.msg_TYPE := TMsgType.mtBlueToothState;case FmyMSG.msg_State of2 : FmyMSG.msg_Content := 'STATE_CONNECTED'; //bts_STATE_CONNECTED 21 : FmyMSG.msg_Content := 'STATE_CONNECTING'; //bts_STATE_CONNECTING 10 : FmyMSG.msg_Content := 'STATE_DISCONNECTED'; //bts_STATE_DISCONNECTED 03 : FmyMSG.msg_Content := 'DISCONNECTING'; //bts_STATE_DISCONNECTING 310: FmyMSG.msg_Content := 'STATE_OFF'; //bts_STATE_OFF 1012: FmyMSG.msg_Content := 'STATE_ON'; //bts_STATE_ON 1213: FmyMSG.msg_Content := 'STATE_TURNING_OFF'; //bts_STATE_TURNING_OFF 1311: FmyMSG.msg_Content := 'STATE_TURNING_ON'; //bts_STATE_TURNING_ON 11end;//通知控件处理此事件myMessage := TMessage<TmyMSG>.Create(FmyMSG);TMessageManager.DefaultManager.SendMessage(nil,myMessage,True);Exit;end;//2. 处理WIFI广播消息if action = JStringToString(TJWifiManager.JavaClass.WIFI_STATE_CHANGED_ACTION) thenbegin//获取WIFI状态iState := intent.getIntExtra( TJWifiManager.JavaClass.EXTRA_WIFI_STATE ,0);FmyMSG.msg_State := iState;FmyMSG.msg_TYPE := TMsgType.mtWIFIState;case FmyMSG.msg_State of1: FmyMSG.msg_Content := 'WIFI_STATE_DISABLED'; // wfs_WIFI_STATE_DISABLED = 10: FmyMSG.msg_Content := 'WIFI_STATE_DISABLING'; // wfs_WIFI_STATE_DISABLING = 0,3: FmyMSG.msg_Content := 'WIFI_STATE_ENABLED'; // wfs_WIFI_STATE_ENABLED = 3,2: FmyMSG.msg_Content := 'WIFI_STATE_ENABLING'; // wfs_WIFI_STATE_ENABLING = 2,4: FmyMSG.msg_Content := 'WIFI_STATE_UNKNOWN'; // wfs_WIFI_STATE_UNKNOWN = 4end;//通知控件处理此事件myMessage := TMessage<TmyMSG>.Create(FmyMSG);TMessageManager.DefaultManager.SendMessage(nil,myMessage,True);Exit;end;//3. 处理电源变化if action = 'android.intent.action.BATTERY_CHANGED' thenbeginFmyMSG.msg_TYPE := mtPowerState;jo := TJSONObject.Create;try//获取电源电量 参考:http://www.android-doc.com/reference/android/os/BatteryManager.html#EXTRA_LEVELiState := intent.getIntExtra(StringToJString('level') ,0);jo.AddPair('level',iState.ToString);//是否插上电源, 0 means it is on battery, other constants are different types of power sources.iState := intent.getIntExtra(StringToJString('plugged') ,0);if iState <> 0 thenjo.AddPair('plugged','true')elsejo.AddPair('plugged','false');//是否是电池供电//iState := intent.getIntExtra(StringToJString('present') ,0);//jo.AddPair('present',iState);//电池温度//iState := intent.getIntExtra(StringToJString('temperature') ,0);//jo.AddPair('temperature',iState);//电池电压iState := intent.getIntExtra(StringToJString('voltage') ,0);jo.AddPair('voltage',iState.ToString);FmyMSG.msg_Content := jo.ToString;finallyjo.Free;end;iState := intent.getIntExtra(StringToJString('level') ,0);FmyMSG.msg_State := iState;//通知控件处理此事件myMessage := TMessage<TmyMSG>.Create(FmyMSG);TMessageManager.DefaultManager.SendMessage(nil,myMessage,True);Exit;end;
end;
三、注册(订阅)系统状态变化消息广播:
我们需要接收(监听)什么状态,我们就注册什么状态,这样注册后的项目如果状态发生变化,我们就能够在第二步定义的onReceive事件中收到消息。在注册系统广播消息的时候,我们提前d订阅了一个我们自己的消息接收器FMessageSubscriptionID。
function TReceiver_State.Register_Reveiver(var errmsg: string): Boolean;
begin//如果集合为空,表示没有选择if FmsgTypes = [] thenbeginerrmsg := '至少需要选择一个监测项!';Exit(False);end;// 注册状态变化消息接收系统//1. 注册消息接收{$IFDEF android}FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage(TMessage<TmyMSG>, ProcessMsgEvent);//初始化 过滤器FFilter := TJIntentFilter.JavaClass.init;//监听蓝牙消息if mtBlueToothState in FMsgTypes thenbeginFFilter.addAction(TJBluetoothAdapter.JavaClass.ACTION_STATE_CHANGED);//ShowMessage('mtBlueToothState');end;//监听WIFI状态if mtWIFIState in FMsgTypes thenbeginFFilter.addAction(TJWifiManager.JavaClass.WIFI_STATE_CHANGED_ACTION);//ShowMessage('mtWIFIState');end;//监听电源变化if mtPowerState in FMsgTypes thenbeginFFilter.addAction(StringToJString('android.intent.action.BATTERY_CHANGED'));//ShowMessage('mtPowerState');end;//网络状态变化广播if mtNetConnectState in FMsgTypes thenFFilter.addAction(TJConnectivityManager.JavaClass.CONNECTIVITY_ACTION);{'android.net.conn.CONNECTIVITY_CHANGE'}//加入通用类别FFilter.addCategory(StringToJString('android.intent.category.DEFAULT'));//1. 动态注册广播接受者tryTAndroidHelper.Context.registerReceiver(FReceiver, FFilter);Result := True;//ShowMessage('OK');except on E: Exception dobeginerrmsg := E.Message;Result := False;end;end;//内部记录是否处于监测状体 True 表示是处于监测状态FOpened := Result;{$ENDIF}
end;
上述代码也许一下看不明白,因为我把android系统状态变化封装成了一个控件(TReceiver_State),这样使用起来将会非常方便。
四、控件整体定义:
事实上我们需要解决的是 TBroadcastReceiver 和控件TReceiver_State之间的消息传递,使用的是RTL跨平台的消息机制。从而实现控件TReceiver_State的事件(OnStateChange)触发。
TReceiver_State = class(TComponent)private{ Private declarations }{$IFDEF android}FListener: TBroadcastReceiver;FReceiver: JFMXBroadcastReceiver;FFilter : JIntentFilter;{$ENDIF}FMsgTypes : TMsgTypes;FOpened : Boolean; //是否处于监听状态, True 是,否则 FalseFOnStateChange : TOnStateChange;FMessageSubscriptionID : Integer; //接收消息IDprocedure SetMsgTypes(value : TMsgTypes); //属性设置过程protected{ Protected declarations }procedure ProcessMsgEvent(const Sender: TObject; const M: TMessage);public{ Public declarations }constructor Create(AOwner: TComponent); override;destructor Destroy; override;procedure Loaded;override;//注册广播监听function Register_Reveiver(var errmsg : string) : Boolean;//取消广播监听procedure UnRegister_Reveiver;published{ Published declarations }property OnStateChange: TOnStateChange read FOnStateChange write FOnStateChange;property Receivers : TMsgTypes read FMsgTypes write SetMsgTypes; // default [TMsgType.mtBlueToothState,TMsgType.mtWIFIState]; //默认监测蓝牙选项end;constructor TReceiver_State.Create;
begininherited;FOpened := False; //默认是没有打开监听//FMsgTypes := [TMsgType.mtBlueToothState];{$IFDEF android}//1. 创建系统消息接收者FListener := TBroadcastReceiver.Create;//2. 初始化注册接收器FReceiver := TJFMXBroadcastReceiver.JavaClass.init(FListener);{$ENDIF}
end;destructor TReceiver_State.Destroy;
begin//解除广播消息接收{$IFDEF android}TAndroidHelper.Context.unregisterReceiver(FReceiver);{$ENDIF}UnRegister_Reveiver;inherited;
end;procedure TReceiver_State.Loaded;
begininherited;//FMsgTypes := [TMsgType.mtBlueToothState];
end;
Delphi Message 系列文章到此全部结束!
【Delphi】中使用消息Messages(八)Android 系统消息感知相关推荐
- 【Delphi】中使用消息Messages(七)Android 系统消息
前面6节介绍了Delphi中消息机制的基本原理,并通过一个演示程序进行实际演示.本节开始,我讲介绍Delphi开发Android系统时需要使用的一些特殊消息.以下所说系统,泛指Android系统. 一 ...
- 【Delphi】中使用消息Messages(五)Windows消息
目录 Windows消息使用流程 Windows消息注意事项 Dispatch消息使用流程 Dispatch消息注意事项: 上一节讲述了RTL消息,本节讲述下Windows消息.首先看下演示程序如下: ...
- Delphi中对消息的处理
Delphi中对消息的处理 刘文彦 张 翔 摘 要:本文对覆盖消息和自定义消息的处理方法进行讨论,总结出两类消息处理的步骤, 并通过例程加以实现. 关键词:Delphi; 消息; 通 ...
- DELPHI 中 Window 消息大全使用详解
Window 消息大全使用详解 导读: Delphi是Borland公司的一种面向对象的可视化软件开发工具. Delphi集中了Visual C++和Visual Basic两者的优点:容易上手.功能 ...
- Delphi中的消息截获
Windows是一个基于消息驱动的系统,因此,在很多时候,我们需要截获一些消息然后自己进行处理.而VCL系统又有一些特定的消息.下面对我所了解的delphi环境中截获消息进行一些总结. 就 ...
- 浅析Android中的消息机制
在分析Android消息机制之前,我们先来看一段代码: [java] view plaincopy public class MainActivity extends Activity impleme ...
- 重温Android中的消息机制
引入: 提到Android中的消息机制,大家应该都不陌生,我们在开发中不可避免的要和它打交道.从我们开发的角度来看,Handler是Android消息机制的上层接口.我们在平时的开发中只需要和Hand ...
- 【Android 异步操作】手写 Handler ( Message 消息 | ThreadLocal 线程本地变量 | Looper 中的消息队列 MessageQueue )
文章目录 一.Message 消息 二.ThreadLocal 线程本地变量 三.Looper 中的消息队列 MessageQueue 一.Message 消息 模仿 Android 中的 Messa ...
- Android中的消息机制
Android 中的消息机制其实就是指的是 Handler 消息机制以及附带的 Looper 和 MessageQueue 的工作流程. 1.Android 为什么提供Handler? 解决子线程不能 ...
最新文章
- Usage and Idioms——Categories
- OpenJDK 正式宣布AWT、2D、Swing等项目解散
- TP5 使用IN查询时如何限制条数
- J-4 Java语言基础
- Spring的事务控制-基于注解的方式
- php赋值boolean,php布尔类型(Boolean)
- SQL Server大数据表的分区存储
- 易语言 网页用什么编码_Plessey条码用的什么编码方式?
- eclipse import的项目报autowired cannot be resolved to a type的错误
- python访问oracle时的问题总结
- 【电机学】电机绕组方式
- CSS cursor鼠标样式一览表
- Latex 给参考文献添加doi号和超链接
- Internet Explorer无法打开Internet 站点的原因
- 【菜鸟学习论文】2020_Wasserstein Distances for Stereo Disparity Estimation
- “鲨鱼仿生学”iGame主板即将迎来新形象
- excel数据个数统计问题
- FX110网:鳄鱼线(Alligator)指标的操作应用
- daphile的dsd设置_小块头有大能量 篇二:JaguarBoard之Daphile HiFi 畅享
- ArrayBuffer DataView