在Android Studio中用Java实现向Nominatim发送GET请求
解决方案
要向Nominatim发送GET请求,需注意Android禁止在主线程执行网络操作,必须通过异步任务实现。以下提供两种简单可行的方案:
方案一:原生HttpURLConnection + AsyncTask
无需额外依赖,使用Android原生API实现。
- 添加网络权限
在AndroidManifest.xml中添加互联网权限:
<uses-permission android:name="android.permission.INTERNET" />
- 实现异步任务类
在Player类内部添加用于执行网络请求的异步任务:
private class FetchLocationDetailsTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... urls) { String response = ""; HttpURLConnection urlConnection = null; try { URL url = new URL(urls[0]); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); urlConnection.setConnectTimeout(5000); urlConnection.setReadTimeout(5000); // 读取响应内容 InputStream in = new BufferedInputStream(urlConnection.getInputStream()); response = convertStreamToString(in); } catch (IOException e) { e.printStackTrace(); } finally { if (urlConnection != null) { urlConnection.disconnect(); } } return response; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); // 在主线程处理返回结果 if (!TextUtils.isEmpty(result)) { Log.d("Nominatim Response", result); // 此处可添加JSON解析逻辑,提取城市、地址等信息 } } // 将输入流转换为字符串工具方法 private String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line; try { while ((line = reader.readLine()) != null) { sb.append(line).append('\n'); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } }
- 启动异步请求
在onLocationChanged方法中调用异步任务发送请求:
@Override public void onLocationChanged(@NonNull Location location) { double lat = location.getLatitude(); Log.d("lat: ", ""+lat); double lng = location.getLongitude(); Log.d("lng: ", ""+lng); String path = "https://nominatim.openstreetmap.org/reverse?lat=" + lat + "&lon=" + lng + "&format=json&extratags=1"; // 启动异步任务 new FetchLocationDetailsTask().execute(path); }
方案二:OkHttp(更简洁)
使用第三方OkHttp库简化网络请求代码。
- 添加依赖
在模块级build.gradle的dependencies中添加OkHttp依赖:
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
- 实现请求方法
添加异步请求方法:
private void fetchLocationDetails(String url) { OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(5, TimeUnit.SECONDS) .readTimeout(5, TimeUnit.SECONDS) .build(); Request request = new Request.Builder() .url(url) .get() .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { e.printStackTrace(); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { if (response.isSuccessful() && response.body() != null) { final String responseData = response.body().string(); // 切换到主线程处理结果 runOnUiThread(() -> { Log.d("Nominatim Response", responseData); // 解析JSON数据 }); } } }); }
- 调用请求方法
在onLocationChanged中调用该方法:
@Override public void onLocationChanged(@NonNull Location location) { // ... 原有纬度、经度获取代码 String path = "https://nominatim.openstreetmap.org/reverse?lat=" + lat + "&lon=" + lng + "&format=json&extratags=1"; fetchLocationDetails(path); }
完整修改后的代码(方案一)
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.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.ImageButton; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import com.google.android.gms.maps.SupportMapFragment; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class Player extends AppCompatActivity { @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(R.layout.activity_client); Background_DoWork(); } private void Background_DoWork() { ImageButton imgbtnBack = findViewById(R.id.BackActivity); imgbtnBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); ActivityResultLauncher<String[]> locationPermissionRequest = registerForActivityResult(new ActivityResultContracts .RequestMultiplePermissions(), result -> { Boolean fineLocationGranted = result.getOrDefault( Manifest.permission.ACCESS_FINE_LOCATION, false); Boolean coarseLocationGranted = result.getOrDefault( Manifest.permission.ACCESS_COARSE_LOCATION, false); if ((fineLocationGranted != null && fineLocationGranted) || (coarseLocationGranted != null && coarseLocationGranted)) { LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } lm.requestSingleUpdate(LocationManager.GPS_PROVIDER, new LocationListener() { @Override public void onLocationChanged(@NonNull Location location) { double lat = location.getLatitude(); Log.d("lat: ", ""+lat); double lng = location.getLongitude(); Log.d("lng: ", ""+lng); String path = "https://nominatim.openstreetmap.org/reverse?lat=" + lat + "&lon=" + lng + "&format=json&extratags=1"; new FetchLocationDetailsTask().execute(path); } }, null); } }); locationPermissionRequest.launch(new String[] { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }); } private class FetchLocationDetailsTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... urls) { String response = ""; HttpURLConnection urlConnection = null; try { URL url = new URL(urls[0]); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); urlConnection.setConnectTimeout(5000); urlConnection.setReadTimeout(5000); InputStream in = new BufferedInputStream(urlConnection.getInputStream()); response = convertStreamToString(in); } catch (IOException e) { e.printStackTrace(); } finally { if (urlConnection != null) { urlConnection.disconnect(); } } return response; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); if (!TextUtils.isEmpty(result)) { Log.d("Nominatim Response", result); // 可在此添加JSON解析逻辑 } } private String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line; try { while ((line = reader.readLine()) != null) { sb.append(line).append('\n'); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } } }
注意事项
- 必须添加互联网权限才能正常发送网络请求
- Nominatim有请求频率限制,避免短时间内重复发送请求,建议添加缓存机制
- 可使用Gson等库解析返回的JSON数据,快速提取城市、地址等目标信息
内容的提问来源于stack exchange,提问作者Carl
相关产品推荐
相关产品推荐

