android-GoogleMap定位

通过 Google location 库 获取到 经纬度, 然后通过经纬度 请求 http api 获取到对应的地区


Android 经纬度获取

配置 AndroidManifest.xml, 增加权限

1
2
3
<!-- Google 定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

build.gradle 引入库

1
2
3
4
dependencies {
...
implementation 'com.google.android.gms:play-services-location:15.0.1' // Google 定位
}

相关代码 LocationHelper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
package com.yang.androidaar;

import android.Manifest;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import android.util.Log;

import androidx.annotation.NonNull;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.yang.androidaar.MyCode.ECode;
import com.yang.androidaar.MyCode.ERequestCode;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class LocationHelper {

static LocationHelper instance = null;

public static LocationHelper getIns() {
if (instance == null) {
instance = new LocationHelper();
}
return instance;
}

public class GeoPoint {
public double lat;
public double lon;
}

private final String TAG = "--- LocationHelper";
private String mJavaFunc = "";
private int mTotalCnt = 0;

private Runnable mTask = null;
private FusedLocationProviderClient mFusedLocationClient;
private LocationCallback mLocationCallback = null;
private List<GeoPoint> mPointList = null;

public LocationHelper() {
mJavaFunc = MainActivity.NativeFunc_GoogleLoc;
}

public void onPause() {
Log.d(TAG, "onPause");
// stopLoc();
}

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == ERequestCode.LocPermission && mTask != null) {
mTask.run();
}
}

protected void onAction(@ECode int errCode, final String javaFunc, final String msg) {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", errCode);
jsonObject.put("msg", msg);
MainActivity.callUnityFunc(javaFunc, jsonObject.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}

public void startLoc(final String jsonMsg) {
if (!Tools.checkIsSupportGoogle()) {
onAction(ECode.SupportError, mJavaFunc, "--- 不支持 Google 服务");
return;
}

checkPermission(new Runnable() {
@Override
public void run() {
Log.d(TAG, "startLoc 111");
mTask = null;
if (!MainActivity.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)
|| !MainActivity.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) {
Log.d(TAG, "startLoc: permission is not ok");
onAction(ECode.LocPermissionError, mJavaFunc, "--- startLoc, 定位授权失败");
} else {
if (!isLocationServiceEnable()) {
Log.d(TAG, "startLoc: locationService is not ok");
onAction(ECode.LocSericeError, mJavaFunc, "--- startLoc, 未开启定位服务");
} else {
initLoc();
if (mFusedLocationClient == null || mLocationCallback == null) {
onAction(ECode.LocInitError, mJavaFunc, "--- startLoc, 定位初始化失败");
} else {
LocationRequest locationRequest = getLocationRequest(jsonMsg);
if (locationRequest == null) {
onAction(ECode.JsonError, mJavaFunc, "--- startLoc, json 解析失败");
} else {
mPointList = new ArrayList<GeoPoint>();
mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, null);
}
}
}
}
}
});
}

public void stopLoc() {
mPointList = null;
if (mFusedLocationClient != null && mLocationCallback != null) {
Log.d(TAG, "stopLoc: ");
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
}

// private void checkValid(final Runnable task) {
// checkPermission(new Runnable() {
// @Override
// public void run() {
// checkLocService(new Runnable() {
// @Override
// public void run() {
// task.run();
// }
// });
// }
// });
// }

private void checkPermission(Runnable task) {
if (!MainActivity.checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)
|| !MainActivity.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) {
Log.d(TAG, "checkPermission: permission is not ok");
String[] myStringArray = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
};
mTask = task;
MainActivity.reqPermissions(myStringArray, ERequestCode.LocPermission);
} else {
Log.d(TAG, "checkPermission: permission is ok");
task.run();
}
}

// private void checkLocService(Runnable task) {
// if (!isLocationServiceEnable()) {
// Log.d(TAG, "checkValid: locationService is not ok");
// mTask = task;
// } else {
// task.run();
// }
// }

private LocationRequest getLocationRequest(final String jsonMsg) {
LocationRequest locationRequest = null;
try {
JSONObject jsonObject = new JSONObject(jsonMsg);
int interval = jsonObject.getInt("interval");
int fastestInterval = jsonObject.getInt("fastestInterval");
int accuracy = jsonObject.getInt("accuracy");
mTotalCnt = jsonObject.getInt("cnt");
mTotalCnt = mTotalCnt == 0 ? 3 : mTotalCnt;
Log.d(TAG, "mTotalCnt: " + mTotalCnt);
accuracy = accuracy == 0 ? LocationRequest.PRIORITY_HIGH_ACCURACY : accuracy;
locationRequest = new LocationRequest();
locationRequest.setInterval(interval);
locationRequest.setFastestInterval(fastestInterval);
locationRequest.setPriority(accuracy);
} catch (Exception e) {
e.printStackTrace();
}
return locationRequest;
}

private boolean isLocationServiceEnable() {
LocationManager locationManager = (LocationManager) MainActivity.Instance.getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}

private void initLoc() {
if (mFusedLocationClient == null) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainActivity.Instance);
}

if (mLocationCallback == null) {
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
Log.d(TAG, "--- onLocationResult: locationResult == null");
return;
}
for (Location location : locationResult.getLocations()) {
onLoc(location);
}
}
};
}
}

private void onLoc(Location location) {
Log.d(TAG, String.format("--- onLocationResult, lat:%.6f, lon:%.6f", location.getLatitude(), location.getLongitude()));
GeoPoint gp = new GeoPoint();
gp.lat = location.getLatitude();
gp.lon = location.getLongitude();
mPointList.add(gp);

if (mPointList.size() >= mTotalCnt) {
try {
JSONArray array = new JSONArray();
for (GeoPoint point : mPointList) {
JSONObject object = new JSONObject();
object.put("lat", point.lat);
object.put("lon", point.lon);
array.put(object);
}
onAction(ECode.Ok, mJavaFunc, array.toString());
} catch (JSONException e) {
e.printStackTrace();
onAction(ECode.JsonError, mJavaFunc, "--- json error");
} finally {
stopLoc();
}
}
}
}

开启 Geocoding API 服务

  1. api 和 服务 -> 库

  2. 进入 https://console.developers.google.com/apis/library, 搜索 geo

  3. 启用


关联结算账号

因为调用这个 api 是由有限制的, 超过限制需要付费, 但是没有升级账号不会主动扣钱, 但还是要关联上才能有一定得免费配额


根据经纬度请求 api

  • 请求网页地址

    1
    https://maps.googleapis.com/maps/api/geocode/json?language=en-us&latlng=18.104137,79.002457&key=aaa
    • 18.104137,79.002457 : 纬度,经度, 这个是 印度 Telangana 地区

    • aaa : api key

    • 返回信息

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      {
      "plus_code" : {
      "compound_code" : "4232+MX Rampur, Telangana, India",
      "global_code" : "7JCX4232+MX"
      },
      "results" : [
      {
      "address_components" : [
      {
      "long_name" : "502375",
      "short_name" : "502375",
      "types" : [ "postal_code" ]
      },
      {
      "long_name" : "Telangana",
      "short_name" : "Telangana",
      "types" : [ "administrative_area_level_1", "political" ]
      },
      {
      "long_name" : "India",
      "short_name" : "IN",
      "types" : [ "country", "political" ]
      }
      ],
      "formatted_address" : "Telangana 502375, India",
      "geometry" : {
      "bounds" : {
      "northeast" : {
      "lat" : 18.1415713,
      "lng" : 79.03566619999999
      },
      "southwest" : {
      "lat" : 18.0040363,
      "lng" : 78.86245129999999
      }
      },
      "location" : {
      "lat" : 18.0851522,
      "lng" : 78.95145099999999
      },
      "location_type" : "APPROXIMATE",
      "viewport" : {
      "northeast" : {
      "lat" : 18.1415713,
      "lng" : 79.03566619999999
      },
      "southwest" : {
      "lat" : 18.0040363,
      "lng" : 78.86245129999999
      }
      }
      },
      "place_id" : "ChIJzyLKe42UzDsRTR-SRNKmqRI",
      "types" : [ "postal_code" ]
      },
      ...
      ],
      "status" : "OK"
      }

踩坑

请求 http api 报错: This API project is not authorized to use this API

参考: https://stackoverflow.com/questions/32994634/this-api-project-is-not-authorized-to-use-this-api-please-ensure-that-this-api

未启用服务 或 未授权

参考: [开启 Geocoding API 服务](#开启 Geocoding API 服务) 和 关联结算账号