我要做一个基于Android studio的多城市切换+短时预警天气预报app,我的天气API是在https://www.seniverse.com/products这个网站中获取的,其中我的密钥(私钥)是SH8NroqLlNNwwg323,但是我运行之后没有获取到实时数据,我要怎么做,请给我完整代码及完善步骤
这个是我的接口ApiService代码
package com.example.myapplication.network;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface ApiService {
// 心知天气API基础地址
String BASE_URL = "https://api.seniverse.com/v3/";
// 图片中的API密钥(公钥+私钥)
String PUBLIC_KEY = "PVKLD84OHMbGx9iQG";
String PRIVATE_KEY = "SH8NroqLINNwg323";
/**
* 获取实时天气
* @param location 城市名称/ID(如:beijing、101010100)
* @param language 语言(zh-Hans=中文)
* @param unit 单位(c=摄氏度)
* @param key 公钥
* @return 实时天气响应
*/
@GET("weather/now.json")
Call<RealTimeResponse> getRealTimeWeather(
@Query("location") String location,
@Query("language") String language,
@Query("unit") String unit,
@Query("key") String key
);
/**
* 获取7天预报
* @param location 城市名称/ID
* @param language 语言
* @param unit 单位
* @param key 公钥
* @return 7天预报响应
*/
@GET("weather/daily.json")
Call<DailyForecastResponse> get7DayForecast(
@Query("location") String location,
@Query("language") String language,
@Query("unit") String unit,
@Query("key") String key,
@Query("start") int start, // 开始天数(0=今天)
@Query("days") int days // 预报天数(7=7天)
);
// 实时天气响应模型
class RealTimeResponse {
private Results[] results;
public Results[] getResults() { return results; }
public static class Results {
private Location location;
private Now now;
private String last_update;
public Location getLocation() { return location; }
public Now getNow() { return now; }
public String getLast_update() { return last_update; }
}
public static class Location {
private String id;
private String name;
private String country;
private String path;
public String getId() { return id; }
public String getName() { return name; }
public String getCountry() { return country; }
public String getPath() { return path; }
}
public static class Now {
private String text;
private String code;
private String temperature;
private String humidity;
private String wind_direction;
private String wind_speed;
private String wind_scale;
public String getText() { return text; }
public String getCode() { return code; }
public String getTemperature() { return temperature; }
public String getHumidity() { return humidity; }
public String getWind_direction() { return wind_direction; }
public String getWind_speed() { return wind_speed; }
public String getWind_scale() { return wind_scale; }
}
}
// 7天预报响应模型
class DailyForecastResponse {
private Results[] results;
public Results[] getResults() { return results; }
public static class Results {
private Location location;
private Daily[] daily;
private String last_update;
public Location getLocation() { return location; }
public Daily[] getDaily() { return daily; }
public String getLast_update() { return last_update; }
}
public static class Location {
private String id;
private String name;
public String getId() { return id; }
public String getName() { return name; }
}
public static class Daily {
private String date;
private String text_day;
private String code_day;
private String text_night;
private String code_night;
private String high;
private String low;
private String wind_direction;
private String wind_scale;
public String getDate() { return date; }
public String getText_day() { return text_day; }
public String getCode_day() { return code_day; }
public String getText_night() { return text_night; }
public String getCode_night() { return code_night; }
public String getHigh() { return high; }
public String getLow() { return low; }
public String getWind_direction() { return wind_direction; }
public String getWind_scale() { return wind_scale; }
}
}
}
这个是我的RetrofitClient类代码
package com.example.myapplication.network;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient {
private static RetrofitClient instance;
private final ApiService apiService;
private RetrofitClient() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiService = retrofit.create(ApiService.class);
}
public static synchronized RetrofitClient getInstance() {
if (instance == null) {
instance = new RetrofitClient();
}
return instance;
}
public ApiService getApiService() {
return apiService;
}
}
这个是我的MainActivity.java代码
package com.example.myapplication;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.example.myapplication.adapter.ForecastAdapter;
import com.example.myapplication.model.Weather;
import com.example.myapplication.network.ApiService;
import com.example.myapplication.network.RetrofitClient;
import com.example.myapplication.utils.NetworkUtils;
import com.example.myapplication.utils.SPUtils;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "SeniverseWeather";
private SwipeRefreshLayout swipeRefreshLayout;
private TextView tvCity, tvTemperature, tvWeather, tvHumidity, tvWind, tvUpdateTime;
private ImageView ivWeatherIcon;
private RecyclerView rvForecast;
private ForecastAdapter forecastAdapter;
private List<Weather.DailyForecast> forecastList = new ArrayList<>();
private String currentLocation = "beijing"; // 心知天气支持城市名(英文/中文)或ID
private String currentCityName = "北京";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SPUtils.init(this);
// 加载保存的城市
String savedLocation = SPUtils.getString("current_location", "beijing");
String savedCityName = SPUtils.getString("current_city_name", "北京");
if (savedLocation != null && !savedLocation.isEmpty()) {
currentLocation = savedLocation;
currentCityName = savedCityName;
}
initView();
setupClickListeners();
loadRealTimeWeather();
load7DayForecast();
}
private void initView() {
swipeRefreshLayout = findViewById(R.id.swipe_refresh_layout);
tvCity = findViewById(R.id.tv_city);
tvTemperature = findViewById(R.id.tv_temperature);
tvWeather = findViewById(R.id.tv_weather);
tvHumidity = findViewById(R.id.tv_humidity);
tvWind = findViewById(R.id.tv_wind);
tvUpdateTime = findViewById(R.id.tv_update_time);
ivWeatherIcon = findViewById(R.id.iv_weather_icon);
rvForecast = findViewById(R.id.rv_forecast);
swipeRefreshLayout.setColorSchemeResources(R.color.primary);
swipeRefreshLayout.setOnRefreshListener(() -> {
loadRealTimeWeather();
load7DayForecast();
});
forecastAdapter = new ForecastAdapter(forecastList);
rvForecast.setLayoutManager(new LinearLayoutManager(this));
rvForecast.setAdapter(forecastAdapter);
}
private void setupClickListeners() {
Button btnCityManager = findViewById(R.id.btn_city_manager);
Button btnRefresh = findViewById(R.id.btn_refresh);
btnCityManager.setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, CityManagerActivity.class);
startActivityForResult(intent, 1);
});
btnRefresh.setOnClickListener(v -> {
if (NetworkUtils.isNetworkAvailable(this)) {
loadRealTimeWeather();
load7DayForecast();
Toast.makeText(this, "刷新中...", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "无网络连接", Toast.LENGTH_SHORT).show();
}
});
}
// 加载实时天气
private void loadRealTimeWeather() {
Log.d(TAG, "加载实时天气,城市: " + currentLocation);
swipeRefreshLayout.setRefreshing(true);
if (!NetworkUtils.isNetworkAvailable(this)) {
swipeRefreshLayout.setRefreshing(false);
Toast.makeText(this, "网络不可用", Toast.LENGTH_SHORT).show();
showMockData();
return;
}
ApiService apiService = RetrofitClient.getInstance().getApiService();
Call<ApiService.RealTimeResponse> call = apiService.getRealTimeWeather(
currentLocation,
"zh-Hans",
"c",
ApiService.PUBLIC_KEY
);
call.enqueue(new Callback<ApiService.RealTimeResponse>() {
@Override
public void onResponse(Call<ApiService.RealTimeResponse> call, Response<ApiService.RealTimeResponse> response) {
swipeRefreshLayout.setRefreshing(false);
if (response.isSuccessful() && response.body() != null && response.body().getResults() != null) {
ApiService.RealTimeResponse.Results result = response.body().getResults()[0];
updateRealWeatherUI(result);
} else {
String errorMsg = "实时天气获取失败: " + response.code();
Log.e(TAG, errorMsg);
Toast.makeText(MainActivity.this, errorMsg, Toast.LENGTH_SHORT).show();
showMockData();
}
}
@Override
public void onFailure(Call<ApiService.RealTimeResponse> call, Throwable t) {
swipeRefreshLayout.setRefreshing(false);
Log.e(TAG, "实时天气请求失败", t);
Toast.makeText(MainActivity.this, "请求失败: " + t.getMessage(), Toast.LENGTH_SHORT).show();
showMockData();
}
});
}
// 加载7天预报
private void load7DayForecast() {
Log.d(TAG, "加载7天预报,城市: " + currentLocation);
if (!NetworkUtils.isNetworkAvailable(this)) {
Toast.makeText(this, "网络不可用", Toast.LENGTH_SHORT).show();
return;
}
ApiService apiService = RetrofitClient.getInstance().getApiService();
Call<ApiService.DailyForecastResponse> call = apiService.get7DayForecast(
currentLocation,
"zh-Hans",
"c",
ApiService.PUBLIC_KEY,
0, // 从今天开始
7 // 7天预报
);
call.enqueue(new Callback<ApiService.DailyForecastResponse>() {
@Override
public void onResponse(Call<ApiService.DailyForecastResponse> call, Response<ApiService.DailyForecastResponse> response) {
if (response.isSuccessful() && response.body() != null && response.body().getResults() != null) {
ApiService.DailyForecastResponse.Daily[] dailyList = response.body().getResults()[0].getDaily();
updateForecastUI(dailyList);
} else {
Log.e(TAG, "预报获取失败: " + response.code());
Toast.makeText(MainActivity.this, "预报获取失败", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<ApiService.DailyForecastResponse> call, Throwable t) {
Log.e(TAG, "预报请求失败", t);
Toast.makeText(MainActivity.this, "预报请求失败", Toast.LENGTH_SHORT).show();
}
});
}
private void updateRealWeatherUI(ApiService.RealTimeResponse.Results result) {
runOnUiThread(() -> {
try {
ApiService.RealTimeResponse.Now now = result.getNow();
tvCity.setText(result.getLocation().getName());
tvTemperature.setText(now.getTemperature() + "°C");
tvWeather.setText(now.getText());
tvHumidity.setText("湿度: " + now.getHumidity() + "%");
tvWind.setText(now.getWind_direction() + " " + now.getWind_scale() + "级");
// 格式化更新时间(如:2025-12-08T15:44:00+08:00 → 15:44)
String updateTime = result.getLast_update().split("T")[1].split("\\+")[0];
tvUpdateTime.setText("更新于: " + updateTime);
setWeatherIcon(now.getText());
} catch (Exception e) {
Log.e(TAG, "UI更新异常", e);
showMockData();
}
});
}
private void updateForecastUI(ApiService.DailyForecastResponse.Daily[] dailyList) {
runOnUiThread(() -> {
forecastList.clear();
if (dailyList == null || dailyList.length == 0) {
Toast.makeText(this, "无预报数据", Toast.LENGTH_SHORT).show();
return;
}
for (ApiService.DailyForecastResponse.Daily daily : dailyList) {
Weather.DailyForecast forecast = new Weather.DailyForecast();
forecast.setDate(formatDate(daily.getDate()));
forecast.setTmp_max(daily.getHigh());
forecast.setTmp_min(daily.getLow());
forecast.setCond_txt_d(daily.getText_day());
forecast.setWind_dir(daily.getWind_direction() + " " + daily.getWind_scale() + "级");
forecastList.add(forecast);
}
forecastAdapter.notifyDataSetChanged();
});
}
private void setWeatherIcon(String weatherText) {
int iconResId = R.drawable.weather_sunny;
if (weatherText == null) {
ivWeatherIcon.setImageResource(iconResId);
return;
}
if (weatherText.contains("晴")) iconResId = R.drawable.weather_sunny;
else if (weatherText.contains("云") || weatherText.contains("阴")) iconResId = R.drawable.weather_cloudy;
else if (weatherText.contains("雨")) iconResId = R.drawable.weather_rainy;
else if (weatherText.contains("雪")) iconResId = R.drawable.weather_snowy;
else if (weatherText.contains("雾") || weatherText.contains("霾")) iconResId = R.drawable.weather_foggy;
ivWeatherIcon.setImageResource(iconResId);
}
private String formatDate(String dateStr) {
try {
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
SimpleDateFormat outputFormat = new SimpleDateFormat("MM/dd E", Locale.CHINA);
Date date = inputFormat.parse(dateStr);
return outputFormat.format(date);
} catch (Exception e) {
return dateStr;
}
}
private void showMockData() {
runOnUiThread(() -> {
tvCity.setText(currentCityName);
tvTemperature.setText("25°C");
tvWeather.setText("晴");
tvHumidity.setText("湿度: 60%");
tvWind.setText("东南风3级");
tvUpdateTime.setText("更新于: 模拟数据");
forecastList.clear();
String[] days = {"12/08 周一", "12/09 周二", "12/10 周三"};
String[] tempsMax = {"28", "26", "24"};
String[] tempsMin = {"22", "20", "18"};
String[] weathers = {"晴", "多云", "小雨"};
String[] winds = {"东南风3级", "东风2级", "北风4级"};
for (int i = 0; i < 3; i++) {
Weather.DailyForecast forecast = new Weather.DailyForecast();
forecast.setDate(days[i]);
forecast.setTmp_max(tempsMax[i]);
forecast.setTmp_min(tempsMin[i]);
forecast.setCond_txt_d(weathers[i]);
forecast.setWind_dir(winds[i]);
forecastList.add(forecast);
}
forecastAdapter.notifyDataSetChanged();
ivWeatherIcon.setImageResource(R.drawable.weather_sunny);
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == RESULT_OK && data != null) {
String selectedLocation = data.getStringExtra("selected_location");
String selectedCityName = data.getStringExtra("selected_city_name");
if (selectedLocation != null && !selectedLocation.equals(currentLocation)) {
currentLocation = selectedLocation;
currentCityName = selectedCityName;
SPUtils.putString("current_location", currentLocation);
SPUtils.putString("current_city_name", currentCityName);
loadRealTimeWeather();
load7DayForecast();
}
}
}
@Override
protected void onResume() {
super.onResume();
loadRealTimeWeather();
load7DayForecast();
}
}
最新发布