Delphi 安卓手机获取GPS定位并显示在腾讯地图上

最近一直在学习DELPHI安卓的开发,在网上整理了一些资料,以下内容是关于手机定位与调用腾讯地图显示定位的方法。

大纲内容如下:
1.如何获取手机定位的GPS坐标
2.纠正GPS坐标符合腾讯地图
3.在地图中显示手机的位置
4.附上GPS坐标纠正的单元文件内容

注意事项:记住要对手机的权限进行申请,至于如何申请这里不过多描述,各位看倌可以上网查资料,或者我后面单独出一篇文章详细说明安卓权限申请的问题

废话不多说,直接开干

【1.获取手机定位坐标】
以下实现方式是将获取经度和纬度分开成两个函数,详见代码内容:
首先引用必要单元:

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,GetGPSOffset,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Sensors,FMX.WebBrowser,

  {$IFDEF ANDROID}
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.JavaTypes,
  FMX.Helpers.Android,
  Androidapi.Helpers,
  AndroidApi.Jni.App,
  Androidapi.JNIBridge,
  androidapi.Jni.Location,
  Androidapi.JNI.Telephony;
  {$ENDIF}

获取GPS经度坐标

{$REGION '获取定位坐标经度'}
function GetLatitude:Single;
var
  LocationManagerService: JObject;
  Location: JLocation;
  fLocationManager: JLocationManager;
begin
  if not assigned(fLocationManager) then
  begin
//获得Java对象
    LocationManagerService := sharedActivitycontext.getSystemService
      (TJcontext.JavaClass.LOCATION_SERVICE);
// 获得对象的java实例
    fLocationManager := tjlocationmanager.Wrap
      ((LocationManagerService as ILocalObject).GetObjectID);
     end;
//调用Java方法
  // use the gps provider to get current lat, long and altitude
  Location := fLocationManager.getLastKnownLocation
    (tjlocationmanager.JavaClass.GPS_PROVIDER);

 Result:=location.getLatitude;
end;
{$ENDREGION}

获取GPS纬度坐标

{$REGION '获取定位坐标纬度'}
function GetLongitude:Single;
var
  LocationManagerService: JObject;
  Location: JLocation;
  fLocationManager: JLocationManager;
begin
  if not assigned(fLocationManager) then
  begin
//获得Java对象
    LocationManagerService := sharedActivitycontext.getSystemService
      (TJcontext.JavaClass.LOCATION_SERVICE);
// 获得对象的java实例
    fLocationManager := tjlocationmanager.Wrap
      ((LocationManagerService as ILocalObject).GetObjectID);
     end;
//调用Java方法
  // use the gps provider to get current lat, long and altitude
  Location := fLocationManager.getLastKnownLocation
    (tjlocationmanager.JavaClass.GPS_PROVIDER);

 Result:=location.getLongitude;
end;
{$ENDREGION}

【2.纠正GPS坐标符合腾讯地图】
此处需要引用自制单元GetGPSOffset,单元文件内容在下面第4项全文附上,以下代码为调用单元函数纠正GPS坐标,使其在腾讯地图中定位准确
下面的过程有三个输入的参数,分别为:
ALatitude:此参数为经度,可使用前面的获取经度函数function GetLatitude:Single;
ALongitude:此参数为纬度,可使用前面的获取纬度函数function GetLongitude:Single;
AWeb:此参数为TWebBrowser控件的名称,调用时地图显示在TWebBrowser控件中,实际的控件名称在调用时输入在此

{$REGION '调用腾讯地图显示定位'}
procedure GetQQMapPosition(ALatitude,ALongitude:Double; AWeb:TWebBrowser);
const
   URLString:string = 'https://apis.map.qq.com/uri/v1/geocoder?coord=%s,%s';
begin
   GetGPSOffset.TGLGPSCorrect.GPS_to_Google(ALatitude, ALongitude);  //坐标纠偏,需引用GetGPSOffset单元
   AWeb.Navigate(Format(URLString, [FloatToStr(ALatitude), FloatToStr(ALongitude)]));
end;
{$ENDREGION}

【3.调用腾讯地图显示定位】

首先在界面中插入一个LocationSensor控件,一个TWebBrowser控件,一个TMemo控件,如下图

在这里插入图片描述

点击控件,选择LocationChange事件,如下图所示
在这里插入图片描述

然后输入如下代码:

procedure TForm1.LocationSensor1LocationChanged(Sender: TObject;
  const OldLocation, NewLocation: TLocationCoord2D);
begin
   Memo1.Lines.Add(DateTimeToStr(Now) + '     ' + FormatFloat('0.000000',GetLatitude) + ' , ' + FormatFloat('0.000000',GetLongitude) );
   GetQQMapPosition(GetLatitude,GetLongitude,WebBrowser1);
end;

好了,DEMO程序非常简单,只是演示了功能实现的基本操作,下面将GPS纠偏的单元文件内容附上,供大家参考

【4.GPS坐标纠正单元内容】

unit GetGPSOffset;


interface


const
  PI = 3.14159265358979324;
  x_pi = 3.14159265358979324 * 3000.0 / 180.0;


type
  TGLGPSCorrect = class
  private
    class procedure delta(var lat, lng: Double);
    class function transformLon(lat, lng: Double): Double;
    class function transformlat(lat, lng: Double): Double;


    /// <remarks>
    /// GPS坐标转到 Google Map、高德、腾讯
    /// </remarks>
    class procedure WGS84_to_GCJ02(var lat, lng: Double);
    /// <remarks>
    /// 从Google Map、高德、腾讯转到GPS坐标
    /// </remarks>
    class procedure GCJ02_to_WGS84(var lat, lng: Double); // 粗略
    class procedure GCJ02_to_WGS84Ex(var lat, lng: Double); // 精确


    /// <remarks>
    /// 从Google Map、高德、腾讯转到百度坐标
    /// </remarks>
    class procedure GCJ02_to_BD09(var lat, lng: Double);
    /// <remarks>
    /// 从百度转到 Google Map、高德、腾讯坐标
    /// </remarks>
    class procedure BD09_to_GCJ02(var lat, lng: Double);
  public
    class function OutOfChina(lat, lng: Double): Boolean;
    class function Distance(latA, lngA, latB, lngB: Double): Double;
    class procedure GPS_to_Google(var lat, lng: Double);
    class procedure Google_to_GPS(var lat, lng: Double);
    class procedure Gps_to_Baidu(var lat, lng: Double);
    class procedure Baidu_to_Gps(var lat, lng: Double);
    class procedure Google_to_Baidu(var lat, lng: Double);
    class procedure Baidu_to_Google(var lat, lng: Double);
  end;


implementation


uses
  Math;


class procedure TGLGPSCorrect.Baidu_to_Google(var lat, lng: Double);
begin
  BD09_to_GCJ02(lat, lng);
end;


class procedure TGLGPSCorrect.Baidu_to_Gps(var lat, lng: Double);
begin
  BD09_to_GCJ02(lat, lng);
  GCJ02_to_WGS84Ex(lat, lng);
end;


class procedure TGLGPSCorrect.BD09_to_GCJ02(var lat, lng: Double);
var
  x, y, z, theta: Double;
begin
  x := lng - 0.0065;
  y := lat - 0.006;
  z := sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi);
  theta := ArcTan2(y, x) - 0.000003 * cos(x * x_pi);
  lng := z * cos(theta);
  lat := z * sin(theta);
end;


class procedure TGLGPSCorrect.delta(var lat, lng: Double);
const
  a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
  ee = 0.00669342162296594323; // ee: 椭球的偏心率。
var
  dLat, dLng, radLat, magic, sqrtMagic: Double;
begin
  dLat := transformlat(lng - 105.0, lat - 35.0);
  dLng := transformLon(lng - 105.0, lat - 35.0);
  radLat := lat / 180.0 * PI;
  magic := sin(radLat);
  magic := 1 - ee * magic * magic;
  sqrtMagic := sqrt(magic);
  dLat := (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
  dLng := (dLng * 180.0) / (a / sqrtMagic * cos(radLat) * PI);


  lat := dLat;
  lng := dLng;
end;


class function TGLGPSCorrect.Distance(latA, lngA, latB, lngB: Double): Double;
const
  earthR = 6371000.0;
var
  x, y, s, alpha: Double;
begin
  x := cos(latA * PI / 180.0) * cos(latB * PI / 180.0) *
    cos((lngA - lngB) * PI / 180);
  y := sin(latA * PI / 180.0) * sin(latB * PI / 180.0);
  s := x + y;
  if (s > 1) then
    s := 1;
  if (s < -1) then
    s := -1;
  alpha := ArcCos(s);
  result := alpha * earthR;
end;


class procedure TGLGPSCorrect.GCJ02_to_BD09(var lat, lng: Double);
var
  x, y, z, theta: Double;
begin
  x := lng;
  y := lat;
  z := sqrt(x * x + y * y) + 0.00002 * sin(y * x_pi);
  theta := ArcTan2(y, x) + 0.000003 * cos(x * x_pi);
  lng := z * cos(theta) + 0.0065;
  lat := z * sin(theta) + 0.006;
end;


class procedure TGLGPSCorrect.GCJ02_to_WGS84(var lat, lng: Double);
var
  deltalat, delatlng: Double;
begin
  if OutOfChina(lat, lng) then
    exit;


  deltalat := lat;
  delatlng := lng;
  delta(deltalat, delatlng);


  lat := lat - deltalat;
  lng := lng - delatlng;
end;


class procedure TGLGPSCorrect.GCJ02_to_WGS84Ex(var lat, lng: Double);
const
  initDelta = 0.01;
  threshold = 0.000000001;
var
  dLat, dLon, mLat, mLon, pLat, pLon, wgsLat, wgsLon: Double;
  i: integer;
begin
  dLat := initDelta;
  dLon := initDelta;
  mLat := lat - dLat;
  mLon := lng - dLon;
  pLat := lat + dLat;
  pLon := lng + dLon;
  i := 0;
  while true do
  begin
    wgsLat := (mLat + pLat) / 2;
    wgsLon := (mLon + pLon) / 2;
    WGS84_to_GCJ02(wgsLat, wgsLon);
    dLat := wgsLat - lat;
    dLon := wgsLon - lng;
    if ((abs(dLat) < threshold) and (abs(dLon) < threshold)) then
      break;


    if (dLat > 0) then
      pLat := wgsLat
    else
      mLat := wgsLat;
    if (dLon > 0) then
      pLon := wgsLon
    else
      mLon := wgsLon;
    Inc(i);
    if i > 10000 then
      break;
  end;
  lat := wgsLat;
  lng := wgsLon;
end;


class procedure TGLGPSCorrect.Google_to_Baidu(var lat, lng: Double);
begin
  GCJ02_to_BD09(lat, lng);
end;


class procedure TGLGPSCorrect.Google_to_GPS(var lat, lng: Double);
begin
  GCJ02_to_WGS84Ex(lat, lng);
end;


class procedure TGLGPSCorrect.Gps_to_Baidu(var lat, lng: Double);
begin
  WGS84_to_GCJ02(lat, lng);
  GCJ02_to_BD09(lat, lng);
end;


class procedure TGLGPSCorrect.GPS_to_Google(var lat, lng: Double);
begin
  WGS84_to_GCJ02(lat, lng);
end;


class function TGLGPSCorrect.OutOfChina(lat, lng: Double): Boolean;
begin
  result := False;
  if (lng < 72.004) or (lng > 137.8347) then
    result := true;
  if (lat < 0.8293) or (lat > 55.8271) then
    result := true;
end;


class function TGLGPSCorrect.transformlat(lat, lng: Double): Double;
begin
  result := -100.0 + 2.0 * lat + 3.0 * lng + 0.2 * lng * lng + 0.1 * lat * lng +
    0.2 * sqrt(abs(lat));
  result := result + (20.0 * sin(6.0 * lat * PI) + 20.0 * sin(2.0 * lat * PI)) *
    2.0 / 3.0;
  result := result + (20.0 * sin(lng * PI) + 40.0 * sin(lng / 3.0 * PI)) *
    2.0 / 3.0;
  result := result + (160.0 * sin(lng / 12.0 * PI) + 320 * sin(lng * PI / 30.0))
    * 2.0 / 3.0;
end;


class function TGLGPSCorrect.transformLon(lat, lng: Double): Double;
begin
  result := 300.0 + lat + 2.0 * lng + 0.1 * lat * lat + 0.1 * lat * lng + 0.1 *
    sqrt(abs(lat));
  result := result + (20.0 * sin(6.0 * lat * PI) + 20.0 * sin(2.0 * lat * PI)) *
    2.0 / 3.0;
  result := result + (20.0 * sin(lat * PI) + 40.0 * sin(lat / 3.0 * PI)) *
    2.0 / 3.0;
  result := result + (150.0 * sin(lat / 12.0 * PI) + 300.0 *
    sin(lat / 30.0 * PI)) * 2.0 / 3.0;
end;


class procedure TGLGPSCorrect.WGS84_to_GCJ02(var lat, lng: Double);
var
  deltalat, delatlng: Double;
begin
  if (OutOfChina(lat, lng)) then
    exit;


  deltalat := lat;
  delatlng := lng;
  delta(deltalat, delatlng);
  lat := lat + deltalat;
  lng := lng + delatlng;
end;

end.
  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Delphi WebBrowser 控件是 Delphi 的一个重要组件,它可以嵌入在 Delphi 窗体中,用于显示和操作 Web 内容。在使用 Delphi WebBrowser 控件加载腾讯地图时,可以实现在 Delphi 窗体中显示腾讯地图,并与之交互。 要加载腾讯地图,首先需要在 Delphi 窗体中添加一个 TWebBrowser 组件,然后设置其属性来指定加载的网页地址为腾讯地图的网址。例如,可以将其 URL 属性设置为 "https://map.qq.com",即可加载腾讯地图。 加载腾讯地图后,可以通过 Delphi WebBrowser 控件的内置方法和属性来与地图进行交互。可以使用 Navigate 方法来导航到指定的地图页面,可以使用 Document 属性来访问网页的 DOM 结构,可以使用 ExecuteScript 方法来执行 JavaScript 脚本等。 通过 Delphi WebBrowser 控件,可以实现腾讯地图的各种功能,如搜索位置、标注标记、切换图层、放大缩小地图等。可以根据地图的 JavaScript API 文档来编写相应的代码,通过调用 JavaScript 函数实现特定的地图操作。 同时,Delphi WebBrowser 控件还支持事件处理,可以通过编写事件处理程序来响应地图的交互动作,如点击地图、拖动地图等。可以通过 OnDocumentComplete 和 OnClick 等事件来实现相应的处理逻辑。 总之,借助 Delphi WebBrowser 控件,我们可以很方便地实现在 Delphi 窗体中加载和操作腾讯地图,从而为用户提供更加丰富和交互性强的地图功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值