[FMX] 在应用中检测是否已经联网

好吧,我这人实在是懒,不想装组件,而且也不关心太复杂的功能,就是想让用户在使用软件之前,检查下网络是否连接了,所以查找资料写了一个函数。

首先加一个简单的说明:

  • 联网只代表联网,并不代表你一定能够访问指定的网址。比如你虽然连接了 Wifi,但无线路由器却没有连接到 Internet,函数会返回已经联网,但是你实际上还是访问不了。
  • 只支持 Android、iOS 和 Windows 平台,到于 OSX 我大略搜索下,没找到资料,而时间又不太允许细研究,所以大家就暂时忽略吧,在 OSX 中始终返回 true(假设苹果用户都有良好的联网习惯)。
  • iOS 的用户,需要引用 iOSapi.SystemConfiguration 单元,点右边的链接直接下载。当然如果下一版 Delphi 直接带的话,您可以忽略它。注意由于用 SDKTransform 翻译后,我只改动了用到的东西,有可能有些翻译仍然不太对的,我没改,大家用到自己对比 Objective C 的原始声明改下吧。
  • 已知在 iOS 模拟器中,会出现AV错误,但实机测试不会
  • Android 的用户,请打开读取网络状态的权限,否则会出异常提示你打开。
uses System.Classes{$IFDEF MSWINDOWS}, Wininet{$ENDIF}{$IFDEF ANDROID},
  Androidapi.Helpers, Androidapi.JNI.Net, Androidapi.JNI.JavaTypes,
  Androidapi.JNI.GraphicsContentViewText, Androidapi.JNIBridge{$ENDIF}
{$IFDEF IOS}, Posix.syssocket, iOSapi.SystemConfiguration,
  Macapi.CoreFoundation{$ENDIF};
{$IFDEF ANDROID}

function ConnectivityManager: JConnectivityManager;
var
  AObj: JObject;
begin
  AObj := TAndroidHelper.Context.getSystemService
    (TJContext.JavaClass.CONNECTIVITY_SERVICE);
  if Assigned(AObj) then
    Result := TJConnectivityManager.Wrap((AObj as ILocalObject).GetObjectID)
  else
    Result := nil;
end;

{$ENDIF}
{$IFDEF IOS}

function ConnectionReachabilityFlags: Cardinal;
var
  addr: sockaddr;
  reachable: SCNetworkReachabilityRef;
begin
  Result := 0;
  FillChar(addr, SizeOf(addr), 0);
  addr.sa_len := SizeOf(addr);
  addr.sa_family := AF_INET;
  reachable := SCNetworkReachabilityCreateWithAddress
    (kCFAllocatorDefault, @addr);
  if Assigned(reachable) then
  begin
    SCNetworkReachabilityGetFlags(reachable, Result);
    CFRelease(reachable);
  end;
end;

{$ENDIF}

function IsInternetConnected: Boolean;
{$IFDEF ANDROID}
  function CheckConnected: Boolean;
  var
    AMgr: JConnectivityManager;
    ANetwork: JNetworkInfo;
  begin
    Result := false;
    AMgr := ConnectivityManager;
    if Assigned(AMgr) then
    begin
      ANetwork := AMgr.getActiveNetworkInfo;
      if Assigned(ANetwork) then
        Result := ANetwork.isConnected;
    end;
  end;
{$ENDIF}
{$IFDEF IOS}
  function CheckConnected: Boolean;
  begin
    Result := (ConnectionReachabilityFlags and
      kSCNetworkReachabilityFlagsReachable) <> 0;
  end;
{$ENDIF}
{$IFDEF MSWINDOWS}
  function CheckConnected: Boolean;
  var
    AFlags:DWORD;
  begin
    AFlags:=0;
    Result :=  InternetGetConnectedState(@AFlags,0);
  end;
{$ENDIF}
{$IFDEF OSX}
  function CheckConnected: Boolean;
  begin
    Result := true;
    // 我不知道怎么去检测,如果你知道,请告诉我改进
  end;
{$ENDIF}

begin
  Result := CheckConnected;
end;

在 Android 和 iOS 下,稍微改进下还可以检查是否是 Wifi 或移动网络连接,这个大家自己去扩展吧。

分享到: