目录

一、实现android广播消息事件绑定

二、在onReceive中实现接收系统广播消息处理:

三、注册(订阅)系统状态变化消息广播:

四、控件整体定义:


在上一节我提出了两个问题:

  1. App中主动调用android系统中蓝牙打开功能,如何知道用户是否真的打开了蓝牙?
  2. 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 系统消息感知相关推荐

  1. 【Delphi】中使用消息Messages(七)Android 系统消息

    前面6节介绍了Delphi中消息机制的基本原理,并通过一个演示程序进行实际演示.本节开始,我讲介绍Delphi开发Android系统时需要使用的一些特殊消息.以下所说系统,泛指Android系统. 一 ...

  2. 【Delphi】中使用消息Messages(五)Windows消息

    目录 Windows消息使用流程 Windows消息注意事项 Dispatch消息使用流程 Dispatch消息注意事项: 上一节讲述了RTL消息,本节讲述下Windows消息.首先看下演示程序如下: ...

  3. Delphi中对消息的处理

    Delphi中对消息的处理 刘文彦  张  翔  摘   要:本文对覆盖消息和自定义消息的处理方法进行讨论,总结出两类消息处理的步骤, 并通过例程加以实现. 关键词:Delphi; 消息; 通 ...

  4. DELPHI 中 Window 消息大全使用详解

    Window 消息大全使用详解 导读: Delphi是Borland公司的一种面向对象的可视化软件开发工具. Delphi集中了Visual C++和Visual Basic两者的优点:容易上手.功能 ...

  5. Delphi中的消息截获

    Windows是一个基于消息驱动的系统,因此,在很多时候,我们需要截获一些消息然后自己进行处理.而VCL系统又有一些特定的消息.下面对我所了解的delphi环境中截获消息进行一些总结.       就 ...

  6. 浅析Android中的消息机制

    在分析Android消息机制之前,我们先来看一段代码: [java] view plaincopy public class MainActivity extends Activity impleme ...

  7. 重温Android中的消息机制

    引入: 提到Android中的消息机制,大家应该都不陌生,我们在开发中不可避免的要和它打交道.从我们开发的角度来看,Handler是Android消息机制的上层接口.我们在平时的开发中只需要和Hand ...

  8. 【Android 异步操作】手写 Handler ( Message 消息 | ThreadLocal 线程本地变量 | Looper 中的消息队列 MessageQueue )

    文章目录 一.Message 消息 二.ThreadLocal 线程本地变量 三.Looper 中的消息队列 MessageQueue 一.Message 消息 模仿 Android 中的 Messa ...

  9. Android中的消息机制

    Android 中的消息机制其实就是指的是 Handler 消息机制以及附带的 Looper 和 MessageQueue 的工作流程. 1.Android 为什么提供Handler? 解决子线程不能 ...

最新文章

  1. Usage and Idioms——Categories
  2. OpenJDK 正式宣布AWT、2D、Swing等项目解散
  3. TP5 使用IN查询时如何限制条数
  4. J-4 Java语言基础
  5. Spring的事务控制-基于注解的方式
  6. php赋值boolean,php布尔类型(Boolean)
  7. SQL Server大数据表的分区存储
  8. 易语言 网页用什么编码_Plessey条码用的什么编码方式?
  9. eclipse import的项目报autowired cannot be resolved to a type的错误
  10. python访问oracle时的问题总结
  11. 【电机学】电机绕组方式
  12. CSS cursor鼠标样式一览表
  13. Latex 给参考文献添加doi号和超链接
  14. Internet Explorer无法打开Internet 站点的原因
  15. 【菜鸟学习论文】2020_Wasserstein Distances for Stereo Disparity Estimation
  16. “鲨鱼仿生学”iGame主板即将迎来新形象
  17. excel数据个数统计问题
  18. FX110网:鳄鱼线(Alligator)指标的操作应用
  19. daphile的dsd设置_小块头有大能量 篇二:JaguarBoard之Daphile HiFi 畅享
  20. ArrayBuffer DataView

热门文章

  1. QT——移植官方MQTT库
  2. 基于51单片机实现4位数码管动态显示
  3. Windows Mobile开发资源介绍
  4. 用glRotatef函数转动对象
  5. vue3实现主题切换功能
  6. 我学习编程的好的学习方法!
  7. 计算机二级试题word,计算机二级考试word试题及答案.doc
  8. 如何将试卷导入到mysql中,一种基于C#中将Word试题导入数据库实现方法.doc
  9. 黑群晖(DSM7)使用docker挂载zerotier one实现内网穿透
  10. java中堆和堆栈的区别