version:1.5.6

fix:
update:优化天气
This commit is contained in:
2025-04-28 09:31:23 +08:00
parent 167fee039a
commit a379ec9802
15 changed files with 529 additions and 107 deletions

View File

@@ -29,7 +29,6 @@ import com.xxpatx.os.R;
import com.xxpatx.os.base.mvvm.BaseMvvmActivity;
import com.xxpatx.os.config.CommonConfig;
import com.xxpatx.os.databinding.ActivityControlBinding;
import com.xxpatx.os.manager.AmapManager;
import com.xxpatx.os.utils.BrightnessUtils;
import java.lang.reflect.InvocationTargetException;
@@ -674,7 +673,7 @@ public class ControlActivity extends BaseMvvmActivity<ControlViewModel, Activity
mViewDataBinding.clLocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AmapManager.getInstance().startLocation();
// AmapManager.getInstance().startLocation();
}
});
}

View File

@@ -8,7 +8,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -72,7 +71,6 @@ import com.xxpatx.os.fragment.app.AppListFragment;
import com.xxpatx.os.fragment.contact.ContactFragment;
import com.xxpatx.os.fragment.home.HomeFragment;
import com.xxpatx.os.fragment.settings.SettingsFragment;
import com.xxpatx.os.manager.AmapManager;
import com.xxpatx.os.manager.DesktopIconManager;
import com.xxpatx.os.manager.SpeechManager;
import com.xxpatx.os.service.NotificationService;
@@ -709,9 +707,10 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
String tude = mMMKV.decodeString(CommonConfig.MANUALLY_SELECT_LOCATION_TUDE, CommonConfig.DEFAULT_LOCATION_TUDE);
if (!manual) {
LiveEventBus.get(CommonConfig.AMAP_LOCATION_MAP_BEAN, MapBean.class)
.observe(this, new Observer<MapBean>() {
.observeSticky(this, new Observer<MapBean>() {
@Override
public void onChanged(@Nullable MapBean mapBean) {
Log.e(TAG, "observeSticky onChanged: ");
mMMKV.encode(CommonConfig.MANUALLY_SELECT_LOCATION_DISTRICT, mapBean.getDistrict());
mMMKV.encode(CommonConfig.MANUALLY_SELECT_LOCATION_TUDE, mapBean.getLongitude() + "," + mapBean.getLatitude());
// mViewDataBinding.tvLocation.setText(mapBean.getDistrict());
@@ -725,9 +724,6 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
}
}
private ServiceConnection mAlarmServiceConnection;
public static void toggleNotificationListenerService(Context context) {
Log.e(TAG, "toggleNotificationListenerService");
PackageManager pm = context.getPackageManager();
@@ -1075,7 +1071,6 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
registNewAppReceiver();
registerSOSNumberReceiver();
registerUpdateDesktopReceiver();
registmUpdateAddressReceiver();
registerTimeReceiver();
registerMissCallReceiver();
registerPhoneStateReceiver();
@@ -1091,9 +1086,6 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
if (mUpdateDesktopReceiver != null) {
unregisterReceiver(mUpdateDesktopReceiver);
}
if (mUpdateAddressReceiver != null) {
unregisterReceiver(mUpdateAddressReceiver);
}
if (mTimeChangedReceiver != null) {
unregisterReceiver(mTimeChangedReceiver);
}
@@ -1178,25 +1170,6 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
}
}
private UpdateAddressReceiver mUpdateAddressReceiver;
private void registmUpdateAddressReceiver() {
mUpdateAddressReceiver = new UpdateAddressReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(CommonConfig.UIUIAIOS_UPDATE_ADDRESS_ACTION);
registerReceiver(mUpdateAddressReceiver, filter);
}
class UpdateAddressReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (CommonConfig.UIUIAIOS_UPDATE_ADDRESS_ACTION.equals(action)) {
AmapManager.getInstance().startLocation();
}
}
}
//监听时间和日期变化
public void registerTimeReceiver() {
mTimeChangedReceiver = new TimeChangedReceiver();

View File

@@ -39,6 +39,7 @@ import com.xxpatx.os.db.ContactCacheUtils;
import com.xxpatx.os.gson.GsonUtils;
import com.xxpatx.os.manager.AppManager;
import com.xxpatx.os.manager.ContactManager;
import com.xxpatx.os.manager.WeatherManager;
import com.xxpatx.os.network.NetInterfaceManager;
import com.xxpatx.os.service.main.MainService;
import com.xxpatx.os.utils.ActivationUtil;
@@ -92,14 +93,44 @@ public class MainViewModel extends BaseViewModel<ActivityMainBinding, ActivityEv
}
return;
}
getWeatherNow(location);
getWeather24Hourly(location);
getWeather7D(location);
WeatherManager weatherManager = new WeatherManager(getCtx());
weatherManager.getWeatherNow(location, new WeatherManager.WeatherNowCallback() {
@Override
public void onWeatherNow(WeatherNowBean.NowBaseBean nowBaseBean) {
LiveEventBus
.get("getWeatherNowKey")
.post(nowBaseBean);
}
});
// weatherManager.getWeather24Hourly(location, new WeatherManager.WeatherHourlyCallback() {
// @Override
// public void onWeatherHourly(List<WeatherHourlyBean.HourlyBean> hourlyBeanList) {
// if (hourlyBeanList != null && !hourlyBeanList.isEmpty()) {
// LiveEventBus
// .get("getWeather24HourlyKey")
// .post(hourlyBeanList.get(0));
// }
// }
// });
weatherManager.getWeather7Day(false, location, new WeatherManager.WeatherDailyCallback() {
@Override
public void onWeatherDaily(List<WeatherDailyBean.DailyBean> dailyBeanList) {
if (dailyBeanList != null && !dailyBeanList.isEmpty()) {
LiveEventBus
.get("getWeather7DKey")
.post(dailyBeanList.get(0));
}
}
});
// getWeatherNow(location);
// getWeather24Hourly(location);
// getWeather7D(location);
}
@Deprecated
private MutableLiveData<WeatherNowBean.NowBaseBean> mNowBaseBeanData = new MutableLiveData<>();
public void getWeatherNow(String location) {
Log.e(TAG, "getWeatherNow: " + location);
/**
@@ -136,9 +167,9 @@ public class MainViewModel extends BaseViewModel<ActivityMainBinding, ActivityEv
});
}
@Deprecated
private MutableLiveData<WeatherHourlyBean.HourlyBean> mHourlyBeanData = new MutableLiveData<>();
public void getWeather24Hourly(String location) {
QWeather.getWeather24Hourly(getCtx(), location, new QWeather.OnResultWeatherHourlyListener() {
@Override
@@ -167,9 +198,9 @@ public class MainViewModel extends BaseViewModel<ActivityMainBinding, ActivityEv
});
}
@Deprecated
private MutableLiveData<WeatherDailyBean.DailyBean> DailyBeanData = new MutableLiveData<>();
public void getWeather7D(String location) {
QWeather.getWeather7D(getCtx(), location, new QWeather.OnResultWeatherDailyListener() {
@Override

View File

@@ -159,7 +159,7 @@ public class WeatherActivity extends BaseMvvmActivity<WeatherViewModel, Activity
if (qweatherLocation != null) {
String tude = qweatherLocation.getLon() + "," + qweatherLocation.getLat();
mMMKV.encode(CommonConfig.MANUALLY_SELECT_LOCATION_TUDE, tude);
mViewModel.getWeather(tude);
mViewModel.getWeather(tude, true);
} else {
Toaster.show("获取位置信息失败");
}
@@ -204,13 +204,30 @@ public class WeatherActivity extends BaseMvvmActivity<WeatherViewModel, Activity
}
}
});
mViewModel.mNowBaseBeanMutableLiveData.observe(this, new Observer<WeatherNowBean.NowBaseBean>() {
@Override
public void onChanged(WeatherNowBean.NowBaseBean nowBaseBean) {
Log.d("getWeatherNowData: ", "onSuccess: now " + new Gson().toJson(nowBaseBean));
mViewDataBinding.setNowBaseBean(nowBaseBean);
Toaster.show("刷新成功");
}
});
mViewModel.mDailyBeanListMutableLiveData.observe(this, new Observer<List<WeatherDailyBean.DailyBean>>() {
@Override
public void onChanged(List<WeatherDailyBean.DailyBean> dailyBeanList) {
if (dailyBeanList != null) {
mWeatherDayApdapter.setDailyBeans(dailyBeanList);
WeatherDailyBean.DailyBean dailyBean = dailyBeanList.get(0);
mViewDataBinding.tvMinMax.setText(dailyBean.getTempMin() + "℃ - " + dailyBean.getTempMax() + "");
}
}
});
// mViewModel.loadProvince();
getWeather();
getWeather(false);
}
private void getWeather() {
private void getWeather(boolean refresh) {
// mViewModel.getWeatherCache();
String district = mMMKV.decodeString(CommonConfig.MANUALLY_SELECT_LOCATION_DISTRICT, CommonConfig.DEFAULT_LOCATION_DISTRICT);
String tude = mMMKV.decodeString(CommonConfig.MANUALLY_SELECT_LOCATION_TUDE, CommonConfig.DEFAULT_LOCATION_TUDE);
@@ -218,7 +235,7 @@ public class WeatherActivity extends BaseMvvmActivity<WeatherViewModel, Activity
mViewModel.getLocation();
} else {
mViewDataBinding.tvLocation.setText(district);
mViewModel.getWeather(tude);
mViewModel.getWeather(tude, refresh);
}
}
@@ -257,7 +274,7 @@ public class WeatherActivity extends BaseMvvmActivity<WeatherViewModel, Activity
mViewModel.getLocation();
} else {
mViewDataBinding.tvLocation.setText(district);
mViewModel.getWeather(tude);
mViewModel.getWeather(tude, true);
}
}
}

View File

@@ -23,6 +23,7 @@ import com.xxpatx.os.bean.QweatherLookup;
import com.xxpatx.os.config.CommonConfig;
import com.xxpatx.os.databinding.ActivityWeatherBinding;
import com.xxpatx.os.manager.AmapManager;
import com.xxpatx.os.manager.WeatherManager;
import com.xxpatx.os.network.NetInterfaceManager;
import com.xxpatx.os.utils.ActivationUtil;
import com.xxpatx.os.utils.WiFiUtils;
@@ -154,7 +155,9 @@ public class WeatherViewModel extends BaseViewModel<ActivityWeatherBinding, Acti
mLocationData.setValue(location);
}
public void getWeather(String location) {
public void getWeather(String location, boolean refresh) {
Log.e(TAG, "getweather: refresh = " + refresh);
if (getCtx() == null) {
return;
}
@@ -166,10 +169,28 @@ public class WeatherViewModel extends BaseViewModel<ActivityWeatherBinding, Acti
}
return;
}
getWeatherNow(location);
getWeather7D(location);
WeatherManager weatherManager = new WeatherManager(getCtx());
weatherManager.getWeatherNow(location, new WeatherManager.WeatherNowCallback() {
@Override
public void onWeatherNow(WeatherNowBean.NowBaseBean nowBaseBean) {
mNowBaseBeanMutableLiveData.setValue(nowBaseBean);
}
});
weatherManager.getWeather7Day(refresh, location, new WeatherManager.WeatherDailyCallback() {
@Override
public void onWeatherDaily(List<WeatherDailyBean.DailyBean> dailyBeanList) {
mDailyBeanListMutableLiveData.setValue(dailyBeanList);
}
});
// getWeatherNow(location);
// getWeather7D(location);
}
public MutableLiveData<WeatherNowBean.NowBaseBean> mNowBaseBeanMutableLiveData = new MutableLiveData<>();
public MutableLiveData<List<WeatherDailyBean.DailyBean>> mDailyBeanListMutableLiveData = new MutableLiveData<>();
public MutableLiveData<WeatherNowBean> mWeatherNowData = new MutableLiveData<>();
public void getWeatherNow(String locationTude) {

View File

@@ -13,6 +13,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.qweather.sdk.bean.weather.WeatherDailyBean;
import com.xxpatx.os.BuildConfig;
import com.xxpatx.os.R;
import java.text.ParseException;
@@ -71,7 +72,7 @@ public class WeatherDayApdapterPort extends RecyclerView.Adapter<WeatherDayApdap
}
private Drawable getWeatherDrawable(String iconName) {
int resID = mContext.getResources().getIdentifier("he" + iconName, "drawable", "com.uiui.aios");
int resID = mContext.getResources().getIdentifier("he" + iconName, "drawable", BuildConfig.APPLICATION_ID);
if (resID == 0) {
Log.e(TAG, "getView: not found src : " + iconName);
return mContext.getResources().getDrawable(R.drawable.he100);

View File

@@ -71,6 +71,7 @@ public class BaseApplication extends Application {
AmapManager.init(this);
HeConfig.init("HE2407111551551292", "28301b41b0ae42c2b6cecf12862ade1f");
// HeConfig.init("C8WJWM8CDT", "2d8650a095f54225bed52880f1edc3fb");
//切换至开发版服务
HeConfig.switchToDevService();

View File

@@ -38,6 +38,7 @@ public class CommonConfig {
public static final String DEFAULT_PASSWORD = "6666";
/*让桌面更新定位信息*/
@Deprecated
public static final String UIUIAIOS_UPDATE_ADDRESS_ACTION = "UIUIAIOS_UPDATE_ADDRESS";
/*桌面显示定位信息*/
public static final String UIUIAIOS_UPDATE_DESKTOP_LOCATION = "UIUIAIOS_UPDATE_DESKTOP_LOCATIO";
@@ -79,6 +80,8 @@ public class CommonConfig {
public static final String MANUALLY_SELECT_LOCATION_TUDE = "map_manually_select_tude";
/*默认北京原点*/
public static final String DEFAULT_LOCATION_TUDE = "116.40529,39.90499";
public static final String DEFAULT_LOCATION_LONGITUDE = "116.40529";
public static final String DEFAULT_LOCATION_LATITUDE = "39.90499";
/*默认地址id*/

View File

@@ -40,7 +40,6 @@ import com.xxpatx.os.base.mvvm.fragment.BaseMvvmFragment;
import com.xxpatx.os.bean.FamilyAddress;
import com.xxpatx.os.config.CommonConfig;
import com.xxpatx.os.databinding.FragmentControlBinding;
import com.xxpatx.os.manager.AmapManager;
import com.xxpatx.os.utils.BrightnessUtils;
import java.lang.reflect.InvocationTargetException;
@@ -830,7 +829,7 @@ public class ControlFragment extends BaseMvvmFragment<ControlViewModel, Fragment
mViewDataBinding.clLocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AmapManager.getInstance().startLocation();
// AmapManager.getInstance().startLocation();
}
});
}

View File

@@ -215,7 +215,7 @@ public class HomeFragment extends BaseMvvmFragment<HomeViewModel, FragmentHomeBi
});
LiveEventBus
.get("getWeatherNowKey", WeatherNowBean.NowBaseBean.class)
.observe(this, new Observer<WeatherNowBean.NowBaseBean>() {
.observeSticky(this, new Observer<WeatherNowBean.NowBaseBean>() {
@Override
public void onChanged(@Nullable WeatherNowBean.NowBaseBean nowBaseBean) {
mViewDataBinding.tvTemp.setText(nowBaseBean.getTemp() + "");
@@ -262,7 +262,7 @@ public class HomeFragment extends BaseMvvmFragment<HomeViewModel, FragmentHomeBi
LiveEventBus
.get("getWeather7DKey", WeatherDailyBean.DailyBean.class)
.observe(this, new Observer<WeatherDailyBean.DailyBean>() {
.observeSticky(this, new Observer<WeatherDailyBean.DailyBean>() {
@Override
public void onChanged(@Nullable WeatherDailyBean.DailyBean dailyBean) {
mViewDataBinding.tvWeather.setText(dailyBean.getTempMin() + "℃ - " + dailyBean.getTempMax() + "");
@@ -442,7 +442,7 @@ public class HomeFragment extends BaseMvvmFragment<HomeViewModel, FragmentHomeBi
boolean manual = mMMKV.decodeBool(CommonConfig.MANUALLY_SELECT_LOCATION_KEY, false);
if (!manual) {
LiveEventBus.get(CommonConfig.AMAP_LOCATION_MAP_BEAN, MapBean.class)
.observe(this, new Observer<MapBean>() {
.observeSticky(this, new Observer<MapBean>() {
@Override
public void onChanged(@Nullable MapBean mapBean) {
mViewDataBinding.tvLocation.setText(mapBean.getDistrict());

View File

@@ -117,7 +117,7 @@ public class SettingsFragment extends BaseMvvmFragment<SettingsViewModel, Fragme
protected void initData(Bundle savedInstanceState) {
LiveEventBus
.get("getWeatherNowKey", WeatherNowBean.NowBaseBean.class)
.observe(this, new Observer<WeatherNowBean.NowBaseBean>() {
.observeSticky(this, new Observer<WeatherNowBean.NowBaseBean>() {
@Override
public void onChanged(@Nullable WeatherNowBean.NowBaseBean nowBaseBean) {
mViewDataBinding.tvTemp.setText(nowBaseBean.getTemp() + "");
@@ -164,7 +164,7 @@ public class SettingsFragment extends BaseMvvmFragment<SettingsViewModel, Fragme
LiveEventBus
.get("getWeather7DKey", WeatherDailyBean.DailyBean.class)
.observe(this, new Observer<WeatherDailyBean.DailyBean>() {
.observeSticky(this, new Observer<WeatherDailyBean.DailyBean>() {
@Override
public void onChanged(@Nullable WeatherDailyBean.DailyBean dailyBean) {
mViewDataBinding.tvWeather.setText(dailyBean.getTempMin() + "℃ - " + dailyBean.getTempMax() + "");
@@ -199,7 +199,7 @@ public class SettingsFragment extends BaseMvvmFragment<SettingsViewModel, Fragme
});
LiveEventBus.get(CommonConfig.AMAP_LOCATION_MAP_BEAN, MapBean.class)
.observe(this, new Observer<MapBean>() {
.observeSticky(this, new Observer<MapBean>() {
@Override
public void onChanged(@Nullable MapBean mapBean) {
mViewDataBinding.tvLocation2.setText(mapBean.getAddress());

View File

@@ -145,8 +145,7 @@ public class AmapManager {
private void updateAddress(AMapLocation aMapLocation) {
NetInterfaceManager.getInstance().getUpdateAddressObservable(aMapLocation.getAddress()
, aMapLocation.getLongitude(), aMapLocation.getLatitude()
)
, aMapLocation.getLongitude(), aMapLocation.getLatitude())
.subscribe(new Observer<BaseResponse>() {
@Override
public void onSubscribe(@NonNull Disposable d) {

View File

@@ -0,0 +1,215 @@
package com.xxpatx.os.manager;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.qweather.sdk.bean.base.Code;
import com.qweather.sdk.bean.base.Lang;
import com.qweather.sdk.bean.base.Unit;
import com.qweather.sdk.bean.weather.WeatherDailyBean;
import com.qweather.sdk.bean.weather.WeatherHourlyBean;
import com.qweather.sdk.bean.weather.WeatherNowBean;
import com.qweather.sdk.view.QWeather;
import com.tencent.mmkv.MMKV;
import com.xxpatx.os.config.CommonConfig;
import com.xxpatx.os.gson.GsonUtils;
import java.lang.reflect.Type;
import java.util.List;
public class WeatherManager {
private static final String TAG = "WeatherManager";
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
private Context mContext;
private Gson mGson;
/**
* 上次获取实时天气时间戳 3小时更新
*/
private static final String GET_WEATHER_NOW_LAST_TIME_KEY = "get_weather_now_last_time_key";
/**
* 上次获取24小时天气时间戳 8小时更新
*/
private static final String GET_WEATHER_24_HOURLY_LAST_TIME_KEY = "get_weather_24_hourly_last_time_key";
/**
* 上次获取7天天气时间戳 24小时更新
*/
private static final String GET_WEATHER_7_DAY_LAST_TIME_KEY = "get_weather_7_day_last_time_key";
/*实时天气缓存*/
private static final String CACHE_WEATHER_NOW_BEAN_KEY = "cache_weather_now_bean_key";
/*24小时天气缓存*/
private static final String CACHE_WEATHER_HOURLY_BEAN_KEY = "cache_weather_hourly_bean_key";
/*7天天气缓存*/
private static final String CACHE_WEATHER_DAILY_BEAN_KEY = "cache_weather_daily_bean_key";
private static final long MINUTE_1_INTERVAL_MS = 60 * 1000; // 1分钟毫秒数
private static final long HOURLY_3_INTERVAL_MS = 3 * 60 * 60 * 1000; // 3小时毫秒数
private static final long HOURLY_8_INTERVAL_MS = 8 * 60 * 60 * 1000; // 8小时毫秒数
private static final long HOURLY_24_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24小时毫秒数
public WeatherManager(Context context) {
this.mContext = context;
mGson = new Gson();
}
public interface WeatherNowCallback {
void onWeatherNow(WeatherNowBean.NowBaseBean nowBaseBean);
}
public synchronized void getWeatherNow(String location, WeatherNowCallback weatherNowCallback) {
long lastTime = mMMKV.decodeLong(GET_WEATHER_NOW_LAST_TIME_KEY, 0);
Log.e(TAG, "getWeatherNow: lastTime = " + lastTime);
String jsonString = mMMKV.decodeString(CACHE_WEATHER_NOW_BEAN_KEY, "");
long time = System.currentTimeMillis();
if (lastTime == 0 || TextUtils.isEmpty(jsonString) || time - lastTime > HOURLY_3_INTERVAL_MS) {
Log.e(TAG, "getWeatherNow: get data");
QWeather.getWeatherNow(mContext, location, Lang.ZH_HANS, Unit.METRIC, new QWeather.OnResultWeatherNowListener() {
@Override
public void onError(Throwable e) {
mMMKV.encode(GET_WEATHER_NOW_LAST_TIME_KEY, System.currentTimeMillis());
Log.e("getWeatherNow", "onError: " + e);
}
@Override
public void onSuccess(WeatherNowBean weatherBean) {
mMMKV.encode(GET_WEATHER_NOW_LAST_TIME_KEY, System.currentTimeMillis());
Log.e("getWeatherNow", "onSuccess: ");
//先判断返回的status是否正确当status正确时获取数据若status不正确可查看status对应的Code值找到原因
if (Code.OK == weatherBean.getCode()) {
WeatherNowBean.NowBaseBean now = weatherBean.getNow();
mMMKV.encode(CACHE_WEATHER_NOW_BEAN_KEY, GsonUtils.toJSONString(now));
if (weatherNowCallback != null) weatherNowCallback.onWeatherNow(now);
} else {
//在此查看返回数据失败的原因
Code code = weatherBean.getCode();
Log.d("getWeatherNow", "onSuccess: failed code: " + code);
}
}
});
} else {
Log.e(TAG, "getWeatherNow: get cache");
try {
WeatherNowBean.NowBaseBean now = GsonUtils.toJavaObject(jsonString, WeatherNowBean.NowBaseBean.class);
if (weatherNowCallback != null) weatherNowCallback.onWeatherNow(now);
} catch (Exception e) {
Log.e(TAG, "getWeatherNow: " + e.getMessage());
mMMKV.remove(CACHE_WEATHER_NOW_BEAN_KEY);
}
}
}
public interface WeatherHourlyCallback {
void onWeatherHourly(List<WeatherHourlyBean.HourlyBean> hourlyBeanList);
}
public synchronized void getWeather24Hourly(String location, WeatherHourlyCallback weatherHourlyCallback) {
long lastTime = mMMKV.decodeLong(GET_WEATHER_24_HOURLY_LAST_TIME_KEY, 0);
Log.e(TAG, "getWeather24Hourly: lastTime = " + lastTime);
String jsonString = mMMKV.decodeString(CACHE_WEATHER_HOURLY_BEAN_KEY, "");
long time = System.currentTimeMillis();
if (lastTime == 0 || TextUtils.isEmpty(jsonString) || time - lastTime > HOURLY_8_INTERVAL_MS) {
Log.e(TAG, "getWeather24Hourly: get data");
QWeather.getWeather24Hourly(mContext, location, new QWeather.OnResultWeatherHourlyListener() {
@Override
public void onError(Throwable throwable) {
mMMKV.encode(GET_WEATHER_24_HOURLY_LAST_TIME_KEY, System.currentTimeMillis());
Log.e("getWeather24Hourly", "onError: " + throwable);
}
@Override
public void onSuccess(WeatherHourlyBean weatherHourlyBean) {
mMMKV.encode(GET_WEATHER_24_HOURLY_LAST_TIME_KEY, System.currentTimeMillis());
Log.e("getWeather24Hourly", "onSuccess: ");
if (Code.OK == weatherHourlyBean.getCode()) {
List<WeatherHourlyBean.HourlyBean> hourly = weatherHourlyBean.getHourly();
mMMKV.encode(CACHE_WEATHER_HOURLY_BEAN_KEY, GsonUtils.toJSONString(hourly));
if (weatherHourlyCallback != null)
weatherHourlyCallback.onWeatherHourly(hourly);
} else {
//在此查看返回数据失败的原因
Code code = weatherHourlyBean.getCode();
Log.e("getWeather24Hourly", "failed code: " + code);
}
}
});
} else {
Log.e(TAG, "getWeather24Hourly: get cache");
try {
Type type = new TypeToken<List<WeatherHourlyBean.HourlyBean>>() {
}.getType();
List<WeatherHourlyBean.HourlyBean> hourly = mGson.fromJson(jsonString, type);
if (weatherHourlyCallback != null) weatherHourlyCallback.onWeatherHourly(hourly);
} catch (Exception e) {
Log.e(TAG, "getWeather24Hourly: " + e.getMessage());
mMMKV.remove(CACHE_WEATHER_HOURLY_BEAN_KEY);
}
}
}
public interface WeatherDailyCallback {
void onWeatherDaily(List<WeatherDailyBean.DailyBean> dailyBeanList);
}
public synchronized void getWeather7Day(boolean refresh, String location, WeatherDailyCallback weatherDailyCallback) {
Log.e(TAG, "getWeather7Day: refresh = " + refresh);
long lastTime = mMMKV.decodeLong(GET_WEATHER_7_DAY_LAST_TIME_KEY, 0);
Log.e(TAG, "getWeather7Day: lastTime = " + lastTime);
String jsonString = mMMKV.decodeString(CACHE_WEATHER_DAILY_BEAN_KEY, "");
long time = System.currentTimeMillis();
if (lastTime == 0 || TextUtils.isEmpty(jsonString) || refresh ? time - lastTime > MINUTE_1_INTERVAL_MS : time - lastTime > HOURLY_24_INTERVAL_MS) {
Log.e(TAG, "getWeather7Day: get data");
QWeather.getWeather7D(mContext, location, new QWeather.OnResultWeatherDailyListener() {
@Override
public void onError(Throwable throwable) {
mMMKV.encode(GET_WEATHER_7_DAY_LAST_TIME_KEY, System.currentTimeMillis());
Log.e("getWeather7Day", "onError: " + throwable.getMessage());
}
@Override
public void onSuccess(WeatherDailyBean weatherDailyBean) {
mMMKV.encode(GET_WEATHER_7_DAY_LAST_TIME_KEY, System.currentTimeMillis());
Log.e("getWeather7Day", "onSuccess: ");
if (Code.OK == weatherDailyBean.getCode()) {
List<WeatherDailyBean.DailyBean> dailyBeans = weatherDailyBean.getDaily();
mMMKV.encode(CACHE_WEATHER_DAILY_BEAN_KEY, GsonUtils.toJSONString(dailyBeans));
if (weatherDailyCallback != null)
weatherDailyCallback.onWeatherDaily(dailyBeans);
} else {
//在此查看返回数据失败的原因
Code code = weatherDailyBean.getCode();
Log.e("getWeather7Day", "failed code: " + code);
}
}
});
} else {
Log.e(TAG, "getWeather7Day: get cache");
try {
Type type = new TypeToken<List<WeatherDailyBean.DailyBean>>() {
}.getType();
List<WeatherDailyBean.DailyBean> dailyBeans = mGson.fromJson(jsonString, type);
if (weatherDailyCallback != null) weatherDailyCallback.onWeatherDaily(dailyBeans);
} catch (Exception e) {
Log.e(TAG, "getWeather7Day: " + e.getMessage());
mMMKV.remove(CACHE_WEATHER_DAILY_BEAN_KEY);
}
}
}
}

View File

@@ -18,7 +18,6 @@ import com.bumptech.glide.Glide;
import com.tencent.mmkv.MMKV;
import com.xxpatx.os.R;
import com.xxpatx.os.bean.Contact;
import com.xxpatx.os.bean.ContactId;
import com.xxpatx.os.config.CommonConfig;
import java.io.ByteArrayOutputStream;
@@ -26,8 +25,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.Objects;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observable;
@@ -191,26 +189,31 @@ public class ContactsUtils {
}
public static void updateContactPhone(Context context, Contact contact, Bitmap bitmap) {
long rawContactId = ContactsUtils.getRawContactId(context, contact.getMobile());
Log.e(TAG, "updateContactPhone: rawContactId = " + rawContactId);
ContentResolver resolver = context.getContentResolver();
String name = getContactNameFromNumber(context, contact.getMobile());
Log.e(TAG, "updateContactPhone: " + name);
if (!Objects.equals(name, contact.getName())) {
long rawContactId = ContactsUtils.getRawContactId(context, contact.getMobile());
Log.e(TAG, "updateContactPhone: rawContactId = " + rawContactId);
updateContactNameByNumber(context, contact.getMobile(), contact.getName());
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, contact.getName());
resolver.insert(ContactsContract.Data.CONTENT_URI, values);
ContentResolver resolver = context.getContentResolver();
values.clear();
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, contact.getName());
resolver.insert(ContactsContract.Data.CONTENT_URI, values);
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, out.toByteArray());
resolver.insert(ContactsContract.Data.CONTENT_URI, values);
values.clear();
values.clear();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, out.toByteArray());
resolver.insert(ContactsContract.Data.CONTENT_URI, values);
values.clear();
// values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
// values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
@@ -230,7 +233,85 @@ public class ContactsUtils {
// values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);
// values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone);
// Log.d("updateContact", "values已经产生");
// int result = resolver.update(ContactsContract.Data.CONTENT_URI, values, ContactsContract.Data.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(bean.getId())});
// int result = resolver.update(ContactsContract.Data.CONTENT_URI, values, ContactsContract.Data.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)});
// Log.e(TAG, "updateContactPhone: " + result);
} else {
Log.e(TAG, "updateContactPhone: same contact info");
}
}
private static String getContactNameFromNumber(Context context, String phoneNumber) {
String contactName = null;
Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
String[] projection = {ContactsContract.PhoneLookup.DISPLAY_NAME};
try (Cursor cursor = context.getContentResolver().query(lookupUri, projection, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
}
} catch (Exception e) {
Log.e("ContactQuery", "查询失败", e);
}
return contactName != null ? contactName : "未知号码";
}
public static void editContactPhone(Context context, long contactId, Contact contact) {
if (contactId == -1) {
saveContactPhone(context, contact);
} else {
// 2. 获取所有关联的RawContact ID
List<Long> rawContactIds = getRawContactIds(context, contactId);
if (rawContactIds.isEmpty()) {
Log.e("UpdateContact", "rawContactIds is empty");
return;
}
// 3. 构建批量操作
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
for (Long rawId : rawContactIds) {
// 更新现有姓名(如果存在)
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(
ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
ContactsContract.Data.MIMETYPE + "=?",
new String[]{String.valueOf(rawId), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}
)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getName())
.build());
// 插入新姓名(如果原数据不存在)
// ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
// .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawId)
// .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
// .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getName())
// .withYieldAllowed(true)
// .build());
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(
ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
ContactsContract.Data.MIMETYPE + "=? AND " +
ContactsContract.CommonDataKinds.Phone.TYPE + "=?",
new String[]{
String.valueOf(rawId),
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
}
)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, contact.getMobile())
.build());
}
// 4. 执行修改
try {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
context.getContentResolver().notifyChange(ContactsContract.Data.CONTENT_URI, null); // 通知数据变更
Log.i("UpdateContact", "姓名已更新为: " + contact.getName());
} catch (Exception e) {
Log.e("UpdateContact", "修改失败", e);
}
}
}
public static void updateContactPhone(Context context, Contact contact) {
@@ -245,6 +326,90 @@ public class ContactsUtils {
resolver.insert(ContactsContract.Data.CONTENT_URI, values);
}
private static void updateContactNameByNumber(Context context, String phoneNumber, String newName) {
// 1. 根据号码查找联系人ID
long contactId = findContactIdByPhoneNumber(context, phoneNumber);
if (contactId == -1) {
Log.e("UpdateContact", "未找到匹配的联系人");
return;
}
// 2. 获取所有关联的RawContact ID
List<Long> rawContactIds = getRawContactIds(context, contactId);
if (rawContactIds.isEmpty()) {
Log.e("UpdateContact", "rawContactIds is empty");
return;
}
// 3. 构建批量操作
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
for (Long rawId : rawContactIds) {
// 更新现有姓名(如果存在)
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(
ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
ContactsContract.Data.MIMETYPE + "=?",
new String[]{String.valueOf(rawId), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}
)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, newName)
.build());
// 插入新姓名(如果原数据不存在)
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawId)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, newName)
.withYieldAllowed(true)
.build());
}
// 4. 执行修改
try {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
context.getContentResolver().notifyChange(ContactsContract.Data.CONTENT_URI, null); // 通知数据变更
Log.i("UpdateContact", "姓名已更新为: " + newName);
} catch (Exception e) {
Log.e("UpdateContact", "修改失败", e);
}
}
// 根据号码查询联系人ID
public static long findContactIdByPhoneNumber(Context context, String phoneNumber) {
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Cursor cursor = context.getContentResolver().query(
uri,
new String[]{ContactsContract.PhoneLookup._ID},
null, null, null
);
if (cursor != null && cursor.moveToFirst()) {
long contactId = cursor.getLong(0);
cursor.close();
return contactId;
}
return -1;
}
// 获取联系人所有RawContact ID
private static List<Long> getRawContactIds(Context context, long contactId) {
List<Long> rawIds = new ArrayList<>();
Cursor cursor = context.getContentResolver().query(
ContactsContract.RawContacts.CONTENT_URI,
new String[]{ContactsContract.RawContacts._ID},
ContactsContract.RawContacts.CONTACT_ID + "=?",
new String[]{String.valueOf(contactId)},
null
);
if (cursor != null) {
while (cursor.moveToNext()) {
rawIds.add(cursor.getLong(0));
}
cursor.close();
}
return rawIds;
}
public static void update(Context context, Contact contact, Bitmap bitmap) {
long rawContactId = ContactsUtils.getRawContactId(context, contact.getMobile());
@@ -395,6 +560,32 @@ public class ContactsUtils {
return -1;
}
public static String getRawContactName(Context context, String phoneNum) {
ContentResolver resolver = context.getContentResolver();
Cursor cursor = null;
try {
cursor = resolver.query(ContactsContract.Data.CONTENT_URI,
new String[]{ContactsContract.Data.RAW_CONTACT_ID, ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME},
ContactsContract.CommonDataKinds.Phone.NUMBER + "=?", new String[]{phoneNum}, null);
if (cursor.moveToFirst()) {
String displayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME));
Log.e(TAG, "getRawContactName: displayName = " + displayName);
String name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
Log.e(TAG, "getRawContactName: rawName = " + name);
return name;
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "getRawContactName: " + e.getMessage());
} finally {
if (cursor != null) {
cursor.close();
}
}
return "";
}
/**
* 添加联系人信息
*/
@@ -559,33 +750,6 @@ public class ContactsUtils {
// cursor.close();
}
@Deprecated
public static List<ContactId> getLocalContacts(Context context) {
ContentResolver resolver = context.getContentResolver();
Uri uri = ContactsContract.Contacts.CONTENT_URI;
Cursor cursor = resolver.query(uri, null, null, null, null);
List<ContactId> contactIds = new ArrayList<>();
while (cursor.moveToNext()) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow("name_raw_contact_id"));
int in_phone = cursor.getInt(cursor.getColumnIndexOrThrow("indicate_phone_or_sim_contact"));
String display_name = cursor.getString(cursor.getColumnIndexOrThrow("display_name"));
String photo_uri = cursor.getString(cursor.getColumnIndexOrThrow("photo_uri"));
ContactId contactId = new ContactId(id, in_phone, display_name, photo_uri);
contactIds.add(contactId);
}
cursor.close();
List<ContactId> filter = contactIds.stream().filter(new Predicate<ContactId>() {
@Override
public boolean test(ContactId contactId) {
return contactId.getInPhone() == -1;
}
}).collect(Collectors.toList());
Log.e(TAG, "getLocalContacts: " + filter);
return filter;
}
/**
* 判断某个手机号是否存在
*/
@@ -672,4 +836,3 @@ public class ContactsUtils {
return contactList;
}
}