最近一直在学习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.