Android天气APP改造:基于GPS定位调用OpenWeatherMap显示天气
改造天气APP以使用GPS获取当前位置
Hey there! Let's get your weather app updated to use GPS for the current location instead of those fixed coordinates. Here's a step-by-step guide to make that happen:
1. 添加必要权限到AndroidManifest.xml
首先,我们需要声明访问位置数据和互联网的权限(因为要调用OpenWeatherMap接口)。在你的manifest标签内添加这些代码:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" />
2. 在MainActivity.java中实现GPS位置逻辑
我们将使用谷歌推荐的FusedLocationProviderClient来获取用户的当前坐标。下面是修改你的Activity代码的具体步骤:
2.1 添加必要的导入
在MainActivity.java顶部添加这些导入语句:
import android.Manifest; import android.content.pm.PackageManager; import android.location.Location; import androidx.core.app.ActivityCompat; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationServices; import com.google.android.gms.tasks.OnSuccessListener;
2.2 添加成员变量
在MainActivity类内部添加这些变量:
private FusedLocationProviderClient fusedLocationClient; private static final int LOCATION_PERMISSION_REQUEST_CODE = 100;
2.3 初始化位置客户端并检查权限
更新你的onCreate方法,设置位置客户端并检查权限:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getSupportActionBar().hide(); setContentView(R.layout.activity_main); // 初始化位置客户端 fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); // 你原有的字体和视图绑定代码 weatherFont = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/weathericons-regular-webfont.ttf"); cityField = findViewById(R.id.city_field); updatedField = findViewById(R.id.updated_field); detailsField = findViewById(R.id.details_field); currentTemperatureField = findViewById(R.id.current_temperature_field); humidity_field = findViewById(R.id.humidity_field); pressure_field = findViewById(R.id.pressure_field); weatherIcon = findViewById(R.id.weather_icon); weatherIcon.setTypeface(weatherFont); // 检查是否拥有位置权限 checkLocationPermission(); }
2.4 实现权限检查和请求方法
添加这些方法来处理权限请求:
private void checkLocationPermission() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // 向用户请求位置权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE); return; } // 权限已授予,获取当前位置 getCurrentLocation(); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 用户允许权限,获取位置 getCurrentLocation(); } else { // 用户拒绝权限,使用原固定坐标作为备选方案 executeWeatherTask("23.8315", "91.2868"); } } }
2.5 获取当前位置并触发天气API调用
添加这个方法来获取用户位置,并将坐标传递给你已有的AsyncTask:
private void getCurrentLocation() { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } // 获取最后已知的位置 fusedLocationClient.getLastLocation() .addOnSuccessListener(this, new OnSuccessListener<Location>() { @Override public void onSuccess(Location location) { if (location != null) { // 将坐标转换为字符串并传递给天气任务 String latitude = String.valueOf(location.getLatitude()); String longitude = String.valueOf(location.getLongitude()); executeWeatherTask(latitude, longitude); } else { // 无法获取位置,使用备选坐标 executeWeatherTask("23.8315", "91.2868"); } } }); } // 封装方法来运行你的天气AsyncTask private void executeWeatherTask(String lat, String lon) { Function.placeIdTask asyncTask = new Function.placeIdTask(new Function.AsyncResponse() { @Override public void processFinish(String weather_city, String weather_description, String weather_temperature, String weather_humidity, String weather_pressure, String weather_iconText, String updatedOn) { // 更新UI显示天气数据 cityField.setText(weather_city); updatedField.setText(updatedOn); detailsField.setText(weather_description); currentTemperatureField.setText(weather_temperature); humidity_field.setText("Humidity: " + weather_humidity); pressure_field.setText("Pressure: " + weather_pressure); weatherIcon.setText(Html.fromHtml(weather_iconText)); } }); asyncTask.execute(lat, lon); }
3. 最终配置:添加谷歌Play服务依赖
确保你的项目包含位置服务依赖。在**模块级build.gradle**的dependencies块中添加这行代码:
implementation 'com.google.android.gms:play-services-location:21.0.1'
关键注意事项
- 备选方案:如果用户拒绝权限或设备无法获取位置,我们会回退到你原来的固定坐标——你也可以添加一个Toast提示用户。
- 实时更新:如果需要持续更新位置(比如用户移动时),可以使用
fusedLocationClient.requestLocationUpdates()代替getLastLocation()。 - 位置精度:
ACCESS_FINE_LOCATION使用GPS获取精确坐标,ACCESS_COARSE_LOCATION使用Wi-Fi/基站获取大致位置——我们同时添加两者以提升兼容性。
内容的提问来源于stack exchange,提问作者Arno Wensler
相关产品推荐
相关产品推荐

