Android Studio天气APP真机运行异常,模拟器正常求助
Android天气APP真机运行故障排查与修复
核心问题分析
模拟器正常、真机输入城市触发Volley错误提示,大概率是明文网络限制、请求参数编码问题或错误信息缺失导致,以下是针对性修复方案:
1. 修复明文HTTP请求被拦截问题(Android 9+)
Android 9及以上系统默认禁止明文HTTP请求,你的API链接用的是http://api.weatherapi.com,真机系统版本较高时会直接拦截请求,模拟器可能未启用严格模式所以正常。
解决方法:
- 方案一(推荐):改用HTTPS链接,把URL中的
http改成https:String url = "https://api.weatherapi.com/v1/forecast.json?key=978870d191bb464f997175225221411&q="+cityName+"&days=1&aqi=yes&alerts=yes"; - 方案二:如果必须用HTTP,在
res/xml目录下创建network_security_config.xml:
然后在<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">api.weatherapi.com</domain> </domain-config> </network-security-config>AndroidManifest.xml的application标签中添加:android:networkSecurityConfig="@xml/network_security_config"
2. 完善Volley错误信息,精准定位问题
当前错误监听只弹出固定Toast,无法知道具体错误原因(是网络不通、API密钥无效还是城市名称错误),修改getWeatherInfo中的错误监听:
new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { String errorMsg = "请求失败:"; if (error.networkResponse != null) { errorMsg += "状态码:" + error.networkResponse.statusCode; } else if (error.getMessage() != null) { errorMsg += error.getMessage(); } else { errorMsg += "未知错误"; } Toast.makeText(MainActivity.this, errorMsg, Toast.LENGTH_LONG).show(); Log.e("WeatherError", errorMsg, error); } }
这样可以在Logcat中看到详细错误日志,快速定位问题。
3. 修复城市名称URL编码问题
如果输入中文城市名称,直接拼接到URL中会出现乱码,导致API无法识别,需要对城市名称进行URL编码:
import java.net.URLEncoder; import java.nio.charset.StandardCharsets; // 在getWeatherInfo中修改URL拼接部分 String encodedCity = URLEncoder.encode(cityName, StandardCharsets.UTF_8.toString()); String url = "https://api.weatherapi.com/v1/forecast.json?key=978870d191bb464f997175225221411&q="+encodedCity+"&days=1&aqi=yes&alerts=yes";
4. 完善位置权限与定位逻辑
当前定位逻辑存在两个问题:
- 权限申请通过后没有重新获取位置,导致首次打开APP时如果用户刚授权,
location还是null - 仅依赖
GPS_PROVIDER,如果用户关闭GPS,会直接返回null
修改权限回调逻辑:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限通过后重新获取位置 Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location != null) { cityName = getCityName(location.getLongitude(), location.getLatitude()); getWeatherInfo(cityName); } else { // 尝试用网络定位 location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (location != null) { cityName = getCityName(location.getLongitude(), location.getLatitude()); getWeatherInfo(cityName); } else { Toast.makeText(this, "无法获取位置,请手动输入城市", Toast.LENGTH_SHORT).show(); } } } else { Toast.makeText(this, "请授予位置权限,否则无法自动获取城市", Toast.LENGTH_SHORT).show(); // 不要直接finish,让用户可以手动输入城市 // finish(); } } }
5. 检查API密钥有效性
虽然模拟器正常,但可能真机网络环境下API密钥触发了调用限制,登录WeatherAPI官网检查你的密钥是否有效、调用次数是否超限。
内容的提问来源于stack exchange,提问作者Eugenemad
相关产品推荐
相关产品推荐

