From a2287bccd1022254ea039ac8fd59bd8c7bd4e9c8 Mon Sep 17 00:00:00 2001 From: xiao12feng8 <16507319+xiao12feng8@user.noreply.gitee.com> Date: Tue, 6 Jan 2026 10:25:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86=EF=BC=9A=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E5=86=97=E4=BD=99=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/{wishtree.js => wishTree.js} | 0 .../location/TianDiTuLocationService.java | 360 ++++++++++++++++++ 2 files changed, 360 insertions(+) rename Zhibo/admin/src/api/{wishtree.js => wishTree.js} (100%) create mode 100644 android-app/app/src/main/java/com/example/livestreaming/location/TianDiTuLocationService.java diff --git a/Zhibo/admin/src/api/wishtree.js b/Zhibo/admin/src/api/wishTree.js similarity index 100% rename from Zhibo/admin/src/api/wishtree.js rename to Zhibo/admin/src/api/wishTree.js diff --git a/android-app/app/src/main/java/com/example/livestreaming/location/TianDiTuLocationService.java b/android-app/app/src/main/java/com/example/livestreaming/location/TianDiTuLocationService.java new file mode 100644 index 00000000..99ef0970 --- /dev/null +++ b/android-app/app/src/main/java/com/example/livestreaming/location/TianDiTuLocationService.java @@ -0,0 +1,360 @@ +package com.example.livestreaming.location; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Bundle; +import android.util.Log; + +import androidx.core.content.ContextCompat; + +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; + +/** + * 天地图定位服务 + * 使用Android原生定位获取经纬度,然后通过天地图API进行逆地理编码获取地址 + */ +public class TianDiTuLocationService { + + private static final String TAG = "TianDiTuLocation"; + + // 天地图API Key + private static final String TIANDITU_API_KEY = "1b337ad2535a95289c5b943858dd53ac"; + + // 天地图逆地理编码API + private static final String GEOCODE_API_URL = "http://api.tianditu.gov.cn/geocoder"; + + // 测试模式:如果为true,使用固定的中国坐标进行测试 + // 设置为false后,将使用真实的GPS定位 + // 注意:Android模拟器默认位置在美国,需要在模拟器中手动设置中国坐标 + // 或者开启测试模式进行开发测试 + private static final boolean TEST_MODE = false; // 关闭测试模式,使用真实GPS定位 + // private static final double TEST_LATITUDE = 22.5431; // 深圳纬度(仅测试模式使用) + // private static final double TEST_LONGITUDE = 114.0579; // 深圳经度(仅测试模式使用) + + private Context context; + private LocationManager locationManager; + private LocationListener locationListener; + private OnLocationResultListener resultListener; + + // 保存当前定位的经纬度 + private double currentLatitude; + private double currentLongitude; + + public interface OnLocationResultListener { + void onSuccess(String province, String city, String address, double latitude, double longitude); + void onError(String error); + } + + public TianDiTuLocationService(Context context) { + this.context = context.getApplicationContext(); + this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + } + + /** + * 开始定位 + */ + public void startLocation(OnLocationResultListener listener) { + this.resultListener = listener; + + // 测试模式:直接使用固定坐标(已禁用) + // if (TEST_MODE) { + // Log.d(TAG, "【测试模式】使用固定坐标 - 纬度: " + TEST_LATITUDE + ", 经度: " + TEST_LONGITUDE); + // reverseGeocode(TEST_LONGITUDE, TEST_LATITUDE); + // return; + // } + + // 检查权限 + if (!checkLocationPermission()) { + if (resultListener != null) { + resultListener.onError("缺少定位权限"); + } + return; + } + + // 检查定位服务是否开启 + if (!isLocationEnabled()) { + if (resultListener != null) { + resultListener.onError("请先开启定位服务"); + } + return; + } + + try { + // 创建位置监听器 + locationListener = new LocationListener() { + @Override + public void onLocationChanged(Location location) { + double lat = location.getLatitude(); + double lon = location.getLongitude(); + Log.d(TAG, "位置更新 - 纬度(Latitude): " + lat + ", 经度(Longitude): " + lon); + + // 获取到位置后,停止监听 + stopLocation(); + // 进行逆地理编码 + reverseGeocode(lon, lat); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + } + + @Override + public void onProviderEnabled(String provider) { + } + + @Override + public void onProviderDisabled(String provider) { + } + }; + + // 优先使用GPS定位 + if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + locationManager.requestLocationUpdates( + LocationManager.GPS_PROVIDER, + 0, + 0, + locationListener + ); + Log.d(TAG, "开始GPS定位"); + } + + // 同时使用网络定位作为备选 + if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { + locationManager.requestLocationUpdates( + LocationManager.NETWORK_PROVIDER, + 0, + 0, + locationListener + ); + Log.d(TAG, "开始网络定位"); + } + + // 尝试获取最后已知位置 + Location lastKnownLocation = getLastKnownLocation(); + if (lastKnownLocation != null) { + double lat = lastKnownLocation.getLatitude(); + double lon = lastKnownLocation.getLongitude(); + Log.d(TAG, "使用最后已知位置 - 纬度(Latitude): " + lat + ", 经度(Longitude): " + lon); + stopLocation(); + reverseGeocode(lon, lat); + } + + } catch (SecurityException e) { + Log.e(TAG, "定位权限异常", e); + if (resultListener != null) { + resultListener.onError("定位权限异常: " + e.getMessage()); + } + } + } + + /** + * 停止定位 + */ + public void stopLocation() { + if (locationManager != null && locationListener != null) { + try { + locationManager.removeUpdates(locationListener); + Log.d(TAG, "停止定位"); + } catch (SecurityException e) { + Log.e(TAG, "停止定位异常", e); + } + } + } + + /** + * 检查定位权限 + */ + private boolean checkLocationPermission() { + return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED + || ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) + == PackageManager.PERMISSION_GRANTED; + } + + /** + * 检查定位服务是否开启 + */ + private boolean isLocationEnabled() { + return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) + || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); + } + + /** + * 获取最后已知位置 + */ + private Location getLastKnownLocation() { + try { + Location gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + Location networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); + + if (gpsLocation != null && networkLocation != null) { + // 返回较新的位置 + return gpsLocation.getTime() > networkLocation.getTime() ? gpsLocation : networkLocation; + } else if (gpsLocation != null) { + return gpsLocation; + } else { + return networkLocation; + } + } catch (SecurityException e) { + Log.e(TAG, "获取最后已知位置异常", e); + return null; + } + } + + /** + * 逆地理编码 - 将经纬度转换为地址 + */ + private void reverseGeocode(final double longitude, final double latitude) { + // 保存经纬度 + this.currentLongitude = longitude; + this.currentLatitude = latitude; + + new Thread(() -> { + try { + Log.d(TAG, "开始逆地理编码 - 经度(Lon): " + longitude + ", 纬度(Lat): " + latitude); + + // 检查坐标是否在中国境内(粗略判断) + // 中国经度范围:73°E - 135°E,纬度范围:3°N - 53°N + if (longitude < 73 || longitude > 135 || latitude < 3 || latitude > 53) { + Log.w(TAG, "坐标不在中国境内 - 经度: " + longitude + " (应在73-135之间), 纬度: " + latitude + " (应在3-53之间)"); + if (resultListener != null) { + resultListener.onError("当前位置不在中国境内,天地图API仅支持中国地区\n坐标: " + latitude + ", " + longitude); + } + return; + } + + Log.d(TAG, "坐标检查通过,在中国境内"); + + // 构建请求URL + // 天地图逆地理编码API: http://api.tianditu.gov.cn/geocoder?postStr={'lon':116.397128,'lat':39.916527,'ver':1}&type=geocode&tk=您的密钥 + JSONObject postData = new JSONObject(); + postData.put("lon", longitude); + postData.put("lat", latitude); + postData.put("ver", 1); + + String urlString = GEOCODE_API_URL + "?postStr=" + URLEncoder.encode(postData.toString(), "UTF-8") + + "&type=geocode&tk=" + TIANDITU_API_KEY; + + Log.d(TAG, "逆地理编码请求: " + urlString); + + URL url = new URL(urlString); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + + int responseCode = connection.getResponseCode(); + Log.d(TAG, "响应码: " + responseCode); + + if (responseCode == HttpURLConnection.HTTP_OK) { + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + + String responseStr = response.toString(); + Log.d(TAG, "逆地理编码响应: " + responseStr); + + // 解析响应 + parseGeocodeResponse(responseStr); + } else { + Log.e(TAG, "逆地理编码失败,响应码: " + responseCode); + if (resultListener != null) { + resultListener.onError("获取地址失败,错误码: " + responseCode); + } + } + + connection.disconnect(); + + } catch (Exception e) { + Log.e(TAG, "逆地理编码异常", e); + if (resultListener != null) { + resultListener.onError("获取地址异常: " + e.getMessage()); + } + } + }).start(); + } + + /** + * 解析天地图逆地理编码响应 + */ + private void parseGeocodeResponse(String responseStr) { + try { + JSONObject json = new JSONObject(responseStr); + + // 检查状态 + String status = json.optString("status"); + Log.d(TAG, "API状态码: " + status); + + if (!"0".equals(status)) { + String msg = json.optString("msg", "未知错误"); + Log.e(TAG, "天地图API返回错误: status=" + status + ", msg=" + msg); + if (resultListener != null) { + resultListener.onError("获取地址失败: " + msg + " (状态码: " + status + ")"); + } + return; + } + + // 获取地址信息 + JSONObject result = json.optJSONObject("result"); + if (result != null) { + JSONObject addressComponent = result.optJSONObject("addressComponent"); + String formattedAddress = result.optString("formatted_address", ""); + + Log.d(TAG, "完整地址: " + formattedAddress); + + String province = ""; + String city = ""; + + if (addressComponent != null) { + province = addressComponent.optString("province", ""); + city = addressComponent.optString("city", ""); + String county = addressComponent.optString("county", ""); + + Log.d(TAG, "省份: " + province + ", 城市: " + city + ", 区县: " + county); + + // 如果city为空,尝试使用county + if (city.isEmpty()) { + city = county; + } + } + + // 如果省份和城市都为空,尝试使用完整地址 + if (province.isEmpty() && city.isEmpty() && !formattedAddress.isEmpty()) { + Log.d(TAG, "省份和城市为空,使用完整地址"); + province = formattedAddress; + } + + Log.d(TAG, "解析地址成功 - 省份: " + province + ", 城市: " + city + ", 完整地址: " + formattedAddress); + + if (resultListener != null) { + resultListener.onSuccess(province, city, formattedAddress, currentLatitude, currentLongitude); + } + } else { + Log.e(TAG, "响应中没有result字段"); + if (resultListener != null) { + resultListener.onError("地址解析失败:响应数据格式错误"); + } + } + + } catch (Exception e) { + Log.e(TAG, "解析响应异常", e); + if (resultListener != null) { + resultListener.onError("地址解析异常: " + e.getMessage()); + } + } + } +}