Skip to content

Instantly share code, notes, and snippets.

@pknujsp
Last active May 31, 2023 02:45
Show Gist options
  • Save pknujsp/25c2c11d6dae6138cd0bbd1b7d3f768d to your computer and use it in GitHub Desktop.
Save pknujsp/25c2c11d6dae6138cd0bbd1b7d3f768d to your computer and use it in GitHub Desktop.
Android app widget example
package com.lifedawn.bestweather.widget.creator;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.ArrayMap;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceManager;
import com.google.gson.JsonObject;
import com.lifedawn.bestweather.R;
import com.lifedawn.bestweather.commons.enums.IntentRequestCodes;
import com.lifedawn.bestweather.commons.enums.LocationType;
import com.lifedawn.bestweather.commons.enums.WeatherDataType;
import com.lifedawn.bestweather.commons.enums.ValueUnits;
import com.lifedawn.bestweather.commons.enums.WeatherProviderType;
import com.lifedawn.bestweather.forremoteviews.RemoteViewsUtil;
import com.lifedawn.bestweather.main.MyApplication;
import com.lifedawn.bestweather.retrofit.client.RetrofitClient;
import com.lifedawn.bestweather.retrofit.util.WeatherRestApiDownloader;
import com.lifedawn.bestweather.room.callback.DbQueryCallback;
import com.lifedawn.bestweather.room.dto.WidgetDto;
import com.lifedawn.bestweather.room.repository.WidgetRepository;
import com.lifedawn.bestweather.theme.AppTheme;
import com.lifedawn.bestweather.widget.DialogActivity;
import com.lifedawn.bestweather.widget.OnDrawBitmapCallback;
import com.lifedawn.bestweather.widget.widgetprovider.EighthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.EleventhWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.FifthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.FirstWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.FourthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.NinthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.SecondWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.SeventhWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.SixthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.TenthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.ThirdWidgetProvider;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import static android.view.View.MeasureSpec.EXACTLY;
public abstract class AbstractWidgetCreator {
protected final DateTimeFormatter refreshDateTimeFormatter = DateTimeFormatter.ofPattern("M.d E a h:mm");
protected final int appWidgetId;
protected final ValueUnits tempUnit;
protected final ValueUnits clockUnit;
protected final String tempDegree;
protected ZoneId zoneId;
protected Context context;
protected WidgetUpdateCallback widgetUpdateCallback;
protected WidgetDto widgetDto;
protected WidgetRepository widgetRepository;
protected AppWidgetManager appWidgetManager;
protected RemoteViewsCallback remoteViewsCallback;
public AbstractWidgetCreator setRemoteViewsCallback(RemoteViewsCallback remoteViewsCallback) {
this.remoteViewsCallback = remoteViewsCallback;
return this;
}
public AbstractWidgetCreator setWidgetDto(WidgetDto widgetDto) {
this.widgetDto = widgetDto;
return this;
}
public static AbstractWidgetCreator getInstance(AppWidgetManager appWidgetManager, Context context, int appWidgetId) {
AppWidgetProviderInfo appWidgetProviderInfo = appWidgetManager.getAppWidgetInfo(appWidgetId);
final String providerClassName = appWidgetProviderInfo.provider.getClassName();
if (providerClassName.equals(FirstWidgetProvider.class.getName())) {
return new FirstWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(SecondWidgetProvider.class.getName())) {
return new SecondWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(ThirdWidgetProvider.class.getName())) {
return new ThirdWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(FourthWidgetProvider.class.getName())) {
return new FourthWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(FifthWidgetProvider.class.getName())) {
return new FifthWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(SixthWidgetProvider.class.getName())) {
return new SixthWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(SeventhWidgetProvider.class.getName())) {
return new SeventhWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(EighthWidgetProvider.class.getName())) {
return new EighthWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(NinthWidgetProvider.class.getName())) {
return new NinthWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(TenthWidgetProvider.class.getName())) {
return new TenthWidgetCreator(context, null, appWidgetId);
} else if (providerClassName.equals(EleventhWidgetProvider.class.getName())) {
return new EleventhWidgetCreator(context, null, appWidgetId);
} else {
return null;
}
}
public abstract RemoteViews createTempViews(Integer parentWidth, Integer parentHeight);
public Context getContext() {
return context;
}
public AbstractWidgetCreator(Context context, WidgetUpdateCallback widgetUpdateCallback, int appWidgetId) {
this.context = context;
this.widgetUpdateCallback = widgetUpdateCallback;
this.appWidgetId = appWidgetId;
tempUnit = MyApplication.VALUE_UNIT_OBJ.getTempUnit();
clockUnit = MyApplication.VALUE_UNIT_OBJ.getClockUnit();
tempDegree = MyApplication.VALUE_UNIT_OBJ.getTempUnitText();
widgetRepository = WidgetRepository.getINSTANCE();
appWidgetManager = AppWidgetManager.getInstance(context);
}
public void setRefreshPendingIntent(RemoteViews remoteViews) {
remoteViews.setOnClickPendingIntent(R.id.refreshBtn, getRefreshPendingIntent());
}
public PendingIntent getRefreshPendingIntent() {
Intent refreshIntent = new Intent(context, FirstWidgetProvider.class);
refreshIntent.setAction(context.getString(R.string.com_lifedawn_bestweather_action_REFRESH));
return PendingIntent.getBroadcast(context, IntentRequestCodes.WIDGET_MANUALLY_REFRESH.requestCode, refreshIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
public WidgetDto loadDefaultSettings() {
widgetDto = new WidgetDto();
widgetDto.setAppWidgetId(appWidgetId);
widgetDto.setMultipleWeatherDataSource(false);
widgetDto.setWidgetProviderClassName(widgetProviderClass().getName());
widgetDto.setBackgroundAlpha(100);
widgetDto.setDisplayClock(true);
widgetDto.setDisplayLocalClock(false);
widgetDto.setLocationType(LocationType.CurrentLocation);
widgetDto.addWeatherProviderType(PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean(context.getString(R.string.pref_key_met), true) ?
WeatherProviderType.MET_NORWAY : WeatherProviderType.OWM_ONECALL);
widgetDto.setTextSizeAmount(0);
widgetDto.setTopPriorityKma(true);
if (getRequestWeatherDataTypeSet().contains(WeatherDataType.airQuality)) {
widgetDto.getWeatherProviderTypeSet().add(WeatherProviderType.AQICN);
}
return widgetDto;
}
public void loadSavedSettings(@Nullable DbQueryCallback<WidgetDto> callback) {
widgetRepository.get(appWidgetId, new DbQueryCallback<WidgetDto>() {
@Override
public void onResultSuccessful(WidgetDto result) {
widgetDto = result;
if (callback != null) {
callback.onResultSuccessful(widgetDto);
}
}
@Override
public void onResultNoData() {
}
});
}
public void saveSettings(WidgetDto widgetDto, @Nullable DbQueryCallback<WidgetDto> callback) {
widgetRepository.add(widgetDto, new DbQueryCallback<WidgetDto>() {
@Override
public void onResultSuccessful(WidgetDto result) {
if (callback != null) {
callback.onResultSuccessful(result);
}
}
@Override
public void onResultNoData() {
}
});
}
public void updateSettings(WidgetDto widgetDto, @Nullable DbQueryCallback<WidgetDto> callback) {
widgetRepository.update(widgetDto, new DbQueryCallback<WidgetDto>() {
@Override
public void onResultSuccessful(WidgetDto result) {
if (callback != null) {
callback.onResultSuccessful(result);
}
}
@Override
public void onResultNoData() {
}
});
}
protected void setBackgroundAlpha(RemoteViews remoteViews, int backgroundAlpha) {
float opacity = widgetDto.getBackgroundAlpha() / 100f;
int newBackgroundColor = (int) (opacity * 0xFF) << 24 | AppTheme.getColor(context, R.color.widgetBackgroundColor);
remoteViews.setInt(R.id.root_layout, "setBackgroundColor", newBackgroundColor);
}
public PendingIntent getOnClickedPendingIntent() {
Intent intent = new Intent(context, DialogActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Bundle bundle = new Bundle();
bundle.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtras(bundle);
return PendingIntent.getActivity(context, IntentRequestCodes.CLICK_WIDGET.requestCode, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
protected int getWidgetSizeInDp(AppWidgetManager appWidgetManager, String key) {
return appWidgetManager.getAppWidgetOptions(appWidgetId).getInt(key, 0);
}
/**
* @param
* @return {widgetWidthPx, widgetHeightPx} 반환
*/
public int[] getWidgetExactSizeInPx(AppWidgetManager appWidgetManager) {
int widgetWidth = 0;
int widgetHeight = 0;
int portrait = context.getResources().getConfiguration().orientation;
if (portrait == Configuration.ORIENTATION_PORTRAIT) {
widgetWidth = getWidgetSizeInDp(appWidgetManager, AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
widgetHeight = getWidgetSizeInDp(appWidgetManager, AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);
} else {
widgetWidth = getWidgetSizeInDp(appWidgetManager, AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
widgetHeight = getWidgetSizeInDp(appWidgetManager, AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
}
float density = context.getResources().getDisplayMetrics().density;
float widgetWidthPx = widgetWidth * density;
float widgetHeightPx = widgetHeight * density;
return new int[]{(int) widgetWidthPx, (int) widgetHeightPx};
}
public void makeResponseTextToJson(WeatherRestApiDownloader weatherRestApiDownloader, Set<WeatherDataType> weatherDataTypeSet,
Set<WeatherProviderType> weatherProviderTypeSet, WidgetDto widgetDto, ZoneOffset zoneOffset) {
//json형태로 저장
/*
examples :
{
"KMA":{
"ULTRA_SRT_NCST": ~~json text~~,
"ULTRA_SRT_FCST": ~~json text~~
},
"OPEN_WEATHER_MAP":{
"OWM_ONE_CALL": ~~json text~~
},
"zoneOffset": "09:00"
}
*/
Map<WeatherProviderType, ArrayMap<RetrofitClient.ServiceType, WeatherRestApiDownloader.ResponseResult>> arrayMap =
weatherRestApiDownloader.getResponseMap();
final JsonObject rootJsonObject = new JsonObject();
String text = null;
//owm이면 onecall이므로 한번만 수행
for (WeatherProviderType weatherProviderType : weatherProviderTypeSet) {
ArrayMap<RetrofitClient.ServiceType, WeatherRestApiDownloader.ResponseResult> requestWeatherSourceArr =
arrayMap.get(weatherProviderType);
if (weatherProviderType == WeatherProviderType.OWM_ONECALL) {
JsonObject owmJsonObject = new JsonObject();
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.OWM_ONE_CALL).getResponseText();
owmJsonObject.addProperty(RetrofitClient.ServiceType.OWM_ONE_CALL.name(), text);
rootJsonObject.add(weatherProviderType.name(), owmJsonObject);
} else if (weatherProviderType == WeatherProviderType.MET_NORWAY) {
JsonObject metNorwayJsonObject = new JsonObject();
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.MET_NORWAY_LOCATION_FORECAST).getResponseText();
metNorwayJsonObject.addProperty(RetrofitClient.ServiceType.MET_NORWAY_LOCATION_FORECAST.name(), text);
rootJsonObject.add(weatherProviderType.name(), metNorwayJsonObject);
} else if (weatherProviderType == WeatherProviderType.OWM_INDIVIDUAL) {
JsonObject owmIndividualJsonObject = new JsonObject();
if (weatherDataTypeSet.contains(WeatherDataType.currentConditions)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.OWM_CURRENT_CONDITIONS).getResponseText();
owmIndividualJsonObject.addProperty(RetrofitClient.ServiceType.OWM_CURRENT_CONDITIONS.name(), text);
}
if (weatherDataTypeSet.contains(WeatherDataType.hourlyForecast)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.OWM_HOURLY_FORECAST).getResponseText();
owmIndividualJsonObject.addProperty(RetrofitClient.ServiceType.OWM_HOURLY_FORECAST.name(), text);
}
if (weatherDataTypeSet.contains(WeatherDataType.dailyForecast)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.OWM_DAILY_FORECAST).getResponseText();
owmIndividualJsonObject.addProperty(RetrofitClient.ServiceType.OWM_DAILY_FORECAST.name(), text);
}
rootJsonObject.add(weatherProviderType.name(), owmIndividualJsonObject);
} else if (weatherProviderType == WeatherProviderType.KMA_API) {
JsonObject kmaJsonObject = new JsonObject();
if (weatherDataTypeSet.contains(WeatherDataType.currentConditions)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_ULTRA_SRT_NCST).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_ULTRA_SRT_NCST.name(), text);
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_ULTRA_SRT_FCST).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_ULTRA_SRT_FCST.name(), text);
}
if (weatherDataTypeSet.contains(WeatherDataType.hourlyForecast)) {
if (!kmaJsonObject.has(RetrofitClient.ServiceType.KMA_ULTRA_SRT_FCST.name())) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_ULTRA_SRT_FCST).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_ULTRA_SRT_FCST.name(), text);
}
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_VILAGE_FCST).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_VILAGE_FCST.name(), text);
}
if (weatherDataTypeSet.contains(WeatherDataType.dailyForecast)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_MID_TA_FCST).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_MID_TA_FCST.name(), text);
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_MID_LAND_FCST).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_MID_LAND_FCST.name(), text);
if (!kmaJsonObject.has(RetrofitClient.ServiceType.KMA_ULTRA_SRT_FCST.name())) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_ULTRA_SRT_FCST).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_ULTRA_SRT_FCST.name(), text);
}
if (!kmaJsonObject.has(RetrofitClient.ServiceType.KMA_VILAGE_FCST.name())) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_VILAGE_FCST).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_VILAGE_FCST.name(), text);
}
long tmFc = Long.parseLong(weatherRestApiDownloader.get("tmFc"));
kmaJsonObject.addProperty("tmFc", tmFc);
}
rootJsonObject.add(weatherProviderType.name(), kmaJsonObject);
} else if (weatherProviderType == WeatherProviderType.KMA_WEB) {
JsonObject kmaJsonObject = new JsonObject();
if (weatherDataTypeSet.contains(WeatherDataType.currentConditions)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_WEB_CURRENT_CONDITIONS).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_WEB_CURRENT_CONDITIONS.name(), text);
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_WEB_FORECASTS).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_WEB_FORECASTS.name(), text);
}
if (!kmaJsonObject.has(RetrofitClient.ServiceType.KMA_WEB_FORECASTS.name())) {
if (weatherDataTypeSet.contains(WeatherDataType.hourlyForecast) || weatherDataTypeSet.contains(WeatherDataType.dailyForecast)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.KMA_WEB_FORECASTS).getResponseText();
kmaJsonObject.addProperty(RetrofitClient.ServiceType.KMA_WEB_FORECASTS.name(), text);
}
}
rootJsonObject.add(weatherProviderType.name(), kmaJsonObject);
} else if (weatherProviderType == WeatherProviderType.ACCU_WEATHER) {
JsonObject accuJsonObject = new JsonObject();
if (weatherDataTypeSet.contains(WeatherDataType.currentConditions)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.ACCU_CURRENT_CONDITIONS).getResponseText();
accuJsonObject.addProperty(RetrofitClient.ServiceType.ACCU_CURRENT_CONDITIONS.name(), text);
}
if (weatherDataTypeSet.contains(WeatherDataType.hourlyForecast)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.ACCU_HOURLY_FORECAST).getResponseText();
accuJsonObject.addProperty(RetrofitClient.ServiceType.ACCU_HOURLY_FORECAST.name(), text);
}
if (weatherDataTypeSet.contains(WeatherDataType.dailyForecast)) {
text = requestWeatherSourceArr.get(RetrofitClient.ServiceType.ACCU_DAILY_FORECAST).getResponseText();
accuJsonObject.addProperty(RetrofitClient.ServiceType.ACCU_DAILY_FORECAST.name(), text);
}
rootJsonObject.add(weatherProviderType.name(), accuJsonObject);
} else if (weatherProviderType == WeatherProviderType.AQICN) {
JsonObject aqiCnJsonObject = new JsonObject();
if (weatherDataTypeSet.contains(WeatherDataType.airQuality)) {
text = arrayMap.get(WeatherProviderType.AQICN).get(RetrofitClient.ServiceType.AQICN_GEOLOCALIZED_FEED).getResponseText();
if (text != null && !text.equals("{}")) {
aqiCnJsonObject.addProperty(RetrofitClient.ServiceType.AQICN_GEOLOCALIZED_FEED.name(), text);
}
}
rootJsonObject.add(weatherProviderType.name(), aqiCnJsonObject);
}
}
if (zoneOffset != null) {
rootJsonObject.addProperty("zoneOffset", zoneOffset.getId());
}
rootJsonObject.addProperty("lastUpdatedDateTime", weatherRestApiDownloader.getRequestDateTime().toString());
widgetDto.setResponseText(rootJsonObject.toString());
}
protected final void drawBitmap(ViewGroup rootLayout, @Nullable OnDrawBitmapCallback onDrawBitmapCallback, RemoteViews remoteViews,
@Nullable Integer parentWidth, @Nullable Integer parentHeight) {
int widthSize = 0;
int heightSize = 0;
if (parentWidth == null || parentHeight == null) {
int[] widgetSize = getWidgetExactSizeInPx(AppWidgetManager.getInstance(context));
widthSize = widgetSize[0];
heightSize = widgetSize[1];
} else {
widthSize = parentWidth;
heightSize = parentHeight;
}
final float widgetPadding = context.getResources().getDimension(R.dimen.widget_padding);
final int widthSpec = View.MeasureSpec.makeMeasureSpec((int) (widthSize - widgetPadding * 2), EXACTLY);
final int heightSpec = View.MeasureSpec.makeMeasureSpec((int) (heightSize - widgetPadding * 2), EXACTLY);
rootLayout.measure(widthSpec, heightSpec);
Bitmap viewBmp = drawBitmap(rootLayout, remoteViews);
if (onDrawBitmapCallback != null) {
onDrawBitmapCallback.onCreatedBitmap(viewBmp);
}
}
protected final Bitmap drawBitmap(ViewGroup rootLayout, RemoteViews remoteViews) {
rootLayout.layout(0, 0, rootLayout.getMeasuredWidth(), rootLayout.getMeasuredHeight());
rootLayout.setDrawingCacheEnabled(false);
rootLayout.destroyDrawingCache();
rootLayout.setDrawingCacheEnabled(true);
rootLayout.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
rootLayout.buildDrawingCache();
Bitmap viewBmp = rootLayout.getDrawingCache();
remoteViews.setImageViewBitmap(R.id.bitmapValuesView, viewBmp);
return viewBmp;
}
protected final RemoteViews createBaseRemoteViews() {
return new RemoteViews(context.getPackageName(), R.layout.view_widget);
}
public void setResultViews(int appWidgetId,
@Nullable @org.jetbrains.annotations.Nullable WeatherRestApiDownloader weatherRestApiDownloader,
@Nullable ZoneId zoneId) {
if (!widgetDto.isInitialized())
widgetDto.setInitialized(true);
if (widgetDto.isLoadSuccessful()) {
widgetDto.setLastErrorType(null);
} else {
if (widgetDto.getLastErrorType() == null)
widgetDto.setLastErrorType(RemoteViewsUtil.ErrorType.FAILED_LOAD_WEATHER_DATA);
}
widgetRepository.update(widgetDto, new DbQueryCallback<WidgetDto>() {
@Override
public void onResultSuccessful(WidgetDto result) {
remoteViewsCallback.onResult(result.getAppWidgetId(), createRemoteViews());
}
@Override
public void onResultNoData() {
}
});
}
public RelativeLayout.LayoutParams getHeaderViewLayoutParams() {
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.bottomMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4f,
context.getResources().getDisplayMetrics());
return layoutParams;
}
protected View makeHeaderViews(LayoutInflater layoutInflater, String addressName, String lastRefreshDateTime) {
View view = layoutInflater.inflate(R.layout.header_view_in_widget, null, false);
((TextView) view.findViewById(R.id.address)).setText(addressName);
((TextView) view.findViewById(R.id.refresh)).setText(ZonedDateTime.parse(lastRefreshDateTime).format(refreshDateTimeFormatter));
return view;
}
public RemoteViews createRemoteViews() {
RemoteViews remoteViews = createBaseRemoteViews();
remoteViews.setOnClickPendingIntent(R.id.root_layout, getOnClickedPendingIntent());
return remoteViews;
}
abstract public Class<?> widgetProviderClass();
abstract public void setDisplayClock(boolean displayClock);
abstract public void setDataViewsOfSavedData();
abstract public Set<WeatherDataType> getRequestWeatherDataTypeSet();
public WidgetDto getWidgetDto() {
return widgetDto;
}
public int getAppWidgetId() {
return appWidgetId;
}
public interface WidgetUpdateCallback {
void updatePreview();
}
public static abstract class RemoteViewsCallback {
private final int requestCount;
private final AtomicInteger responseCount = new AtomicInteger(0);
private final Map<Integer, RemoteViews> remoteViewsMap = new ConcurrentHashMap<>();
public RemoteViewsCallback(int requestCount) {
this.requestCount = requestCount;
}
private void onResult(int id, RemoteViews remoteViews) {
remoteViewsMap.put(id, remoteViews);
if (responseCount.incrementAndGet() == requestCount)
onFinished(remoteViewsMap);
}
abstract protected void onFinished(Map<Integer, RemoteViews> remoteViewsMap);
}
}
package com.lifedawn.bestweather.widget.widgetprovider;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.RemoteViews;
import androidx.annotation.Nullable;
import androidx.work.Data;
import androidx.work.ExistingWorkPolicy;
import androidx.work.OneTimeWorkRequest;
import androidx.work.OutOfQuotaPolicy;
import androidx.work.WorkManager;
import com.lifedawn.bestweather.R;
import com.lifedawn.bestweather.commons.interfaces.BackgroundWorkCallback;
import com.lifedawn.bestweather.forremoteviews.RemoteViewsUtil;
import com.lifedawn.bestweather.main.MyApplication;
import com.lifedawn.bestweather.room.callback.DbQueryCallback;
import com.lifedawn.bestweather.room.dto.WidgetDto;
import com.lifedawn.bestweather.room.repository.WidgetRepository;
import com.lifedawn.bestweather.widget.WidgetHelper;
import com.lifedawn.bestweather.widget.creator.AbstractWidgetCreator;
import com.lifedawn.bestweather.widget.work.WidgetListenableWorker;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class BaseAppWidgetProvider extends AppWidgetProvider {
protected void drawWidgets(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Executors.newSingleThreadExecutor().submit(() -> {
final String className = getClass().getName();
final BackgroundWorkCallback backgroundWorkCallback = new BackgroundWorkCallback() {
final int requestCount = appWidgetIds.length;
final AtomicInteger responseCount = new AtomicInteger(0);
@Override
public void onFinished() {
int count = responseCount.incrementAndGet();
Log.e(className, "위젯 그리기 : " + Arrays.toString(appWidgetIds) + ", 요청 : " + requestCount + ", 응답 : " + count);
if (count == requestCount) {
Log.e(className, "위젯 그리기 완료 : " + Arrays.toString(appWidgetIds));
}
}
};
for (int appWidgetId : appWidgetIds) {
if (appWidgetManager.getAppWidgetInfo(appWidgetId) == null) {
backgroundWorkCallback.onFinished();
continue;
}
AbstractWidgetCreator widgetCreator = AbstractWidgetCreator.getInstance(appWidgetManager, context, appWidgetId);
widgetCreator.loadSavedSettings(new DbQueryCallback<WidgetDto>() {
@Override
public void onResultSuccessful(WidgetDto widgetDto) {
if (widgetDto != null) {
if (widgetDto.isInitialized()) {
if (widgetDto.isLoadSuccessful())
widgetCreator.setDataViewsOfSavedData();
else {
RemoteViews remoteViews = widgetCreator.createRemoteViews();
widgetCreator.setRefreshPendingIntent(remoteViews);
RemoteViewsUtil.onErrorProcess(remoteViews, context, widgetDto.getLastErrorType());
appWidgetManager.updateAppWidget(widgetCreator.getAppWidgetId(), remoteViews);
}
}
}
backgroundWorkCallback.onFinished();
}
@Override
public void onResultNoData() {
backgroundWorkCallback.onFinished();
}
});
}
});
}
@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.e(getClass().getName(), Arrays.toString(appWidgetIds));
if (!WidgetListenableWorker.processing.get())
drawWidgets(context, appWidgetManager, appWidgetIds);
}
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
}
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
final BackgroundWorkCallback backgroundWorkCallback = new BackgroundWorkCallback() {
final int allDeletedCount = appWidgetIds.length;
final AtomicInteger deletedCount = new AtomicInteger(0);
@Override
public void onFinished() {
if (deletedCount.incrementAndGet() == allDeletedCount) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
if (appWidgetManager.getInstalledProviders().isEmpty()) {
WidgetHelper widgetHelper = new WidgetHelper(context);
widgetHelper.cancelAutoRefresh();
}
}
}
};
WidgetRepository widgetRepository = WidgetRepository.getINSTANCE();
for (int appWidgetId : appWidgetIds)
widgetRepository.delete(appWidgetId, new DbQueryCallback<Boolean>() {
@Override
public void onResultSuccessful(Boolean result) {
backgroundWorkCallback.onFinished();
}
@Override
public void onResultNoData() {
}
});
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
final String action = intent.getAction();
Log.e(getClass().getName(), action);
if (action != null) {
Bundle bundle = intent.getExtras();
if (action.equals(context.getString(R.string.com_lifedawn_bestweather_action_INIT))) {
Data data = new Data.Builder().putInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
bundle.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID)).build();
startWork(context, action, data);
} else if (action.equals(context.getString(R.string.com_lifedawn_bestweather_action_REFRESH))) {
startWork(context, action, null);
} else if (action.equals(Intent.ACTION_BOOT_COMPLETED) || action.equals(Intent.ACTION_MY_PACKAGE_REPLACED)) {
WidgetHelper widgetHelper = new WidgetHelper(context);
widgetHelper.reDrawWidgets(null);
} else if (action.equals(context.getString(R.string.com_lifedawn_bestweather_action_REDRAW))) {
int[] arr = bundle.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
drawWidgets(context, AppWidgetManager.getInstance(context), arr);
}
}
}
protected void startWork(Context context, String action, @Nullable Data data) {
Data.Builder dataBuilder = new Data.Builder()
.putString("action", action);
if (data != null)
dataBuilder.putAll(data);
final String tag = "widget_" + action;
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(WidgetListenableWorker.class)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setInputData(dataBuilder.build())
.addTag(tag)
.build();
WorkManager workManager = WorkManager.getInstance(context);
workManager.enqueueUniqueWork(tag, ExistingWorkPolicy.REPLACE, request);
}
}
package com.lifedawn.bestweather.widget;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.app.WallpaperManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.RadioGroup;
import android.widget.RemoteViews;
import android.widget.SeekBar;
import android.widget.SpinnerAdapter;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.google.android.material.slider.Slider;
import com.lifedawn.bestweather.R;
import com.lifedawn.bestweather.commons.classes.MainThreadWorker;
import com.lifedawn.bestweather.commons.enums.BundleKey;
import com.lifedawn.bestweather.commons.enums.IntentRequestCodes;
import com.lifedawn.bestweather.commons.enums.LocationType;
import com.lifedawn.bestweather.commons.enums.WeatherProviderType;
import com.lifedawn.bestweather.databinding.ActivityConfigureWidgetBinding;
import com.lifedawn.bestweather.findaddress.map.MapFragment;
import com.lifedawn.bestweather.main.MyApplication;
import com.lifedawn.bestweather.room.callback.DbQueryCallback;
import com.lifedawn.bestweather.room.dto.FavoriteAddressDto;
import com.lifedawn.bestweather.room.dto.WidgetDto;
import com.lifedawn.bestweather.widget.creator.AbstractWidgetCreator;
import com.lifedawn.bestweather.widget.creator.EighthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.EleventhWidgetCreator;
import com.lifedawn.bestweather.widget.creator.FirstWidgetCreator;
import com.lifedawn.bestweather.widget.creator.NinthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.SecondWidgetCreator;
import com.lifedawn.bestweather.widget.creator.SeventhWidgetCreator;
import com.lifedawn.bestweather.widget.creator.SixthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.TenthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.ThirdWidgetCreator;
import com.lifedawn.bestweather.widget.creator.FourthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.FifthWidgetCreator;
import com.lifedawn.bestweather.widget.widgetprovider.EighthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.EleventhWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.FirstWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.NinthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.SecondWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.SeventhWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.SixthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.TenthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.ThirdWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.FourthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.FifthWidgetProvider;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class ConfigureWidgetActivity extends AppCompatActivity implements AbstractWidgetCreator.WidgetUpdateCallback {
private ActivityConfigureWidgetBinding binding;
private Integer appWidgetId;
private Integer layoutId;
private WidgetDto widgetDto;
private Long[] widgetRefreshIntervalValues;
private int originalWidgetRefreshIntervalValueIndex;
private int widgetRefreshIntervalValueIndex;
private int widgetHeight;
private int widgetWidth;
private FavoriteAddressDto newSelectedAddressDto;
private AbstractWidgetCreator widgetCreator;
private AppWidgetManager appWidgetManager;
private boolean selectedFavoriteLocation;
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (!getSupportFragmentManager().popBackStackImmediate()) {
setResult(RESULT_CANCELED);
finish();
}
}
};
private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks = new FragmentManager.FragmentLifecycleCallbacks() {
@Override
public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull Context context) {
super.onFragmentAttached(fm, f, context);
if (f instanceof MapFragment) {
binding.widgetSettingsContainer.setVisibility(View.GONE);
binding.fragmentContainer.setVisibility(View.VISIBLE);
}
}
@Override
public void onFragmentDestroyed(@NonNull @NotNull FragmentManager fm, @NonNull @NotNull Fragment f) {
super.onFragmentDestroyed(fm, f);
if (f instanceof MapFragment) {
binding.widgetSettingsContainer.setVisibility(View.VISIBLE);
binding.fragmentContainer.setVisibility(View.GONE);
}
}
};
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
boolean denied = false;
for (int result : grantResults) {
if (result == PackageManager.PERMISSION_DENIED) {
denied = true;
break;
}
}
if (denied) {
binding.loadingAnimation.setVisibility(View.GONE);
} else {
setBackgroundImg();
}
}
private void setBackgroundImg() {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
MyApplication.getExecutorService().submit(() -> {
WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
Drawable wallpaperDrawable = wallpaperManager.getDrawable();
if (!isFinishing()) {
MainThreadWorker.runOnUiThread(() -> {
Glide.with(ConfigureWidgetActivity.this).load(wallpaperDrawable).into(binding.wallpaper);
binding.loadingAnimation.setVisibility(View.GONE);
});
}
});
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 3);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityConfigureWidgetBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.displayDatetimeSwitch.setVisibility(View.GONE);
binding.displayLocalDatetimeSwitch.setVisibility(View.GONE);
getSupportFragmentManager().registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, false);
getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
appWidgetId = bundle.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
appWidgetManager = AppWidgetManager.getInstance(this);
final AppWidgetProviderInfo appWidgetProviderInfo = appWidgetManager.getAppWidgetInfo(appWidgetId);
layoutId = appWidgetProviderInfo.initialLayout;
ComponentName componentName = appWidgetProviderInfo.provider;
final String widgetProviderClassName = componentName.getClassName();
if (widgetProviderClassName.equals(FirstWidgetProvider.class.getName())) {
widgetCreator = new FirstWidgetCreator(getApplicationContext(), this, appWidgetId);
} else if (widgetProviderClassName.equals(SecondWidgetProvider.class.getName())) {
widgetCreator = new SecondWidgetCreator(getApplicationContext(), this, appWidgetId);
} else if (widgetProviderClassName.equals(ThirdWidgetProvider.class.getName())) {
widgetCreator = new ThirdWidgetCreator(getApplicationContext(), this, appWidgetId);
} else if (widgetProviderClassName.equals(FourthWidgetProvider.class.getName())) {
widgetCreator = new FourthWidgetCreator(getApplicationContext(), this, appWidgetId);
} else if (widgetProviderClassName.equals(FifthWidgetProvider.class.getName())) {
widgetCreator = new FifthWidgetCreator(getApplicationContext(), this, appWidgetId);
} else if (widgetProviderClassName.equals(SixthWidgetProvider.class.getName())) {
widgetCreator = new SixthWidgetCreator(getApplicationContext(), this, appWidgetId);
} else if (widgetProviderClassName.equals(SeventhWidgetProvider.class.getName())) {
widgetCreator = new SeventhWidgetCreator(getApplicationContext(), this, appWidgetId);
binding.weatherDataSourceLayout.setVisibility(View.GONE);
} else if (widgetProviderClassName.equals(EighthWidgetProvider.class.getName())) {
widgetCreator = new EighthWidgetCreator(getApplicationContext(), this, appWidgetId);
} else if (widgetProviderClassName.equals(NinthWidgetProvider.class.getName())) {
widgetCreator = new NinthWidgetCreator(getApplicationContext(), this, appWidgetId);
} else if (widgetProviderClassName.equals(TenthWidgetProvider.class.getName())) {
widgetCreator = new TenthWidgetCreator(getApplicationContext(), this, appWidgetId);
} else if (widgetProviderClassName.equals(EleventhWidgetProvider.class.getName())) {
widgetCreator = new EleventhWidgetCreator(getApplicationContext(), this, appWidgetId);
binding.kmaTopPrioritySwitch.setText(R.string.containsKma);
binding.weatherDataSourceLayout.setVisibility(View.GONE);
}
widgetDto = widgetCreator.loadDefaultSettings();
widgetHeight = (int) (appWidgetProviderInfo.minHeight * 1.9);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) binding.previewLayout.getLayoutParams();
layoutParams.topMargin = MyApplication.getStatusBarHeight() + (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16f,
getResources().getDisplayMetrics());
layoutParams.height = widgetHeight;
binding.previewLayout.setLayoutParams(layoutParams);
//위치, 날씨제공사, 대한민국 최우선, 자동 업데이트 간격, 날짜와 시각표시,
//현지 시각으로 표시, 글자크기, 배경 투명도
initLocation();
initWeatherProvider();
initAutoRefreshInterval();
initDisplayDateTime();
initTextSize();
initBackground();
setBackgroundImg();
binding.currentLocationRadio.setChecked(true);
binding.save.setOnClickListener(v -> widgetCreator.saveSettings(widgetDto, new DbQueryCallback<WidgetDto>() {
@Override
public void onResultSuccessful(WidgetDto result) {
MainThreadWorker.runOnUiThread(new Runnable() {
@Override
public void run() {
if (originalWidgetRefreshIntervalValueIndex != widgetRefreshIntervalValueIndex) {
PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
.edit().putLong(getString(R.string.pref_key_widget_refresh_interval),
widgetRefreshIntervalValues[widgetRefreshIntervalValueIndex]).commit();
WidgetHelper widgetHelper = new WidgetHelper(getApplicationContext());
widgetHelper.onSelectedAutoRefreshInterval(widgetRefreshIntervalValues[widgetRefreshIntervalValueIndex]);
}
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_OK, resultValue);
Bundle initBundle = new Bundle();
initBundle.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
Intent intent = new Intent(getApplicationContext(), widgetCreator.widgetProviderClass());
intent.setAction(getString(R.string.com_lifedawn_bestweather_action_INIT));
intent.putExtras(initBundle);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), IntentRequestCodes.WIDGET_MANUALLY_REFRESH.requestCode,
intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
try {
pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
finishAndRemoveTask();
}
});
}
@Override
public void onResultNoData() {
}
}));
binding.getRoot().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
binding.getRoot().getViewTreeObserver().removeOnGlobalLayoutListener(this);
widgetWidth = binding.previewLayout.getWidth();
updatePreview();
}
});
}
private void initBackground() {
binding.backgroundTransparencySlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
setBackgroundAlpha(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
setBackgroundAlpha(seekBar.getProgress());
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
setBackgroundAlpha(seekBar.getProgress());
}
});
}
private void initTextSize() {
binding.textSizeSlider.addOnSliderTouchListener(new Slider.OnSliderTouchListener() {
@SuppressLint("RestrictedApi")
@Override
public void onStartTrackingTouch(@NonNull Slider slider) {
setTextSizeInWidget((int) slider.getValue());
}
@SuppressLint("RestrictedApi")
@Override
public void onStopTrackingTouch(@NonNull Slider slider) {
setTextSizeInWidget((int) slider.getValue());
}
});
}
private void initDisplayDateTime() {
binding.displayDatetimeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
binding.displayLocalDatetimeSwitch.setVisibility(isChecked ? View.VISIBLE : View.GONE);
widgetDto.setDisplayClock(isChecked);
updatePreview();
}
});
binding.displayLocalDatetimeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
widgetDto.setDisplayLocalClock(isChecked);
}
});
}
private void initAutoRefreshInterval() {
final String[] intervalsDescription = getResources().getStringArray(R.array.AutoRefreshIntervals);
final String[] intervalsStr = getResources().getStringArray(R.array.AutoRefreshIntervalsLong);
widgetRefreshIntervalValues = new Long[intervalsStr.length];
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Long currentValue = sharedPreferences.getLong(getString(R.string.pref_key_widget_refresh_interval), 0L);
for (int i = 0; i < intervalsStr.length; i++) {
widgetRefreshIntervalValues[i] = Long.parseLong(intervalsStr[i]);
}
SpinnerAdapter spinnerAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, intervalsDescription);
binding.autoRefreshIntervalSpinner.setAdapter(spinnerAdapter);
binding.autoRefreshIntervalSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
widgetRefreshIntervalValueIndex = position;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
widgetRefreshIntervalValueIndex = 0;
for (String v : intervalsStr) {
if (currentValue.toString().equals(v)) {
break;
}
widgetRefreshIntervalValueIndex++;
}
originalWidgetRefreshIntervalValueIndex = widgetRefreshIntervalValueIndex;
binding.autoRefreshIntervalSpinner.setSelection(widgetRefreshIntervalValueIndex);
}
private void initWeatherProvider() {
binding.weatherDataSourceRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
widgetDto.addWeatherProviderType(checkedId == R.id.owm_radio ? WeatherProviderType.OWM_ONECALL : WeatherProviderType.MET_NORWAY);
}
});
binding.kmaTopPrioritySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
widgetDto.setTopPriorityKma(isChecked);
}
});
if (PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getBoolean(getString(R.string.pref_key_open_weather_map), false)) {
binding.owmRadio.setChecked(true);
} else {
binding.metNorwayRadio.setChecked(true);
}
}
private void initLocation() {
binding.changeAddressBtn.setVisibility(View.GONE);
binding.selectedAddressName.setVisibility(View.GONE);
binding.locationRadioGroup.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == binding.currentLocationRadio.getId() && binding.currentLocationRadio.isChecked()) {
binding.changeAddressBtn.setVisibility(View.GONE);
binding.selectedAddressName.setVisibility(View.GONE);
widgetDto.setLocationType(LocationType.CurrentLocation);
} else if (checkedId == binding.selectedLocationRadio.getId() && binding.selectedLocationRadio.isChecked()) {
binding.changeAddressBtn.setVisibility(View.VISIBLE);
binding.selectedAddressName.setVisibility(View.VISIBLE);
widgetDto.setLocationType(LocationType.SelectedAddress);
if (!selectedFavoriteLocation) {
openFavoritesFragment();
}
}
});
binding.changeAddressBtn.setOnClickListener(v -> openFavoritesFragment());
}
private void openFavoritesFragment() {
MapFragment mapFragment = new MapFragment();
Bundle bundle = new Bundle();
bundle.putString(BundleKey.RequestFragment.name(), ConfigureWidgetActivity.class.getName());
mapFragment.setArguments(bundle);
mapFragment.setOnResultFavoriteListener(new MapFragment.OnResultFavoriteListener() {
@Override
public void onAddedNewAddress(FavoriteAddressDto newFavoriteAddressDto, List<FavoriteAddressDto> favoriteAddressDtoList, boolean removed) {
onClickedAddress(newFavoriteAddressDto);
getSupportFragmentManager().popBackStack();
}
@Override
public void onResult(List<FavoriteAddressDto> favoriteAddressDtoList) {
}
@Override
public void onClickedAddress(@Nullable FavoriteAddressDto favoriteSelectedAddressDto) {
if (favoriteSelectedAddressDto == null) {
if (!selectedFavoriteLocation) {
Toast.makeText(getApplicationContext(), R.string.not_selected_address, Toast.LENGTH_SHORT).show();
binding.currentLocationRadio.setChecked(true);
}
} else {
selectedFavoriteLocation = true;
newSelectedAddressDto = favoriteSelectedAddressDto;
WidgetDto widgetDto = widgetCreator.getWidgetDto();
widgetDto.setAddressName(newSelectedAddressDto.getDisplayName());
widgetDto.setCountryCode(newSelectedAddressDto.getCountryCode());
widgetDto.setLatitude(Double.parseDouble(newSelectedAddressDto.getLatitude()));
widgetDto.setLongitude(Double.parseDouble(newSelectedAddressDto.getLongitude()));
widgetDto.setTimeZoneId(newSelectedAddressDto.getZoneId());
binding.selectedAddressName.setText(newSelectedAddressDto.getDisplayName());
getSupportFragmentManager().popBackStack();
}
}
});
String tag = com.lifedawn.bestweather.findaddress.map.MapFragment.class.getName();
getSupportFragmentManager().beginTransaction().add(binding.fragmentContainer.getId(), mapFragment, tag)
.addToBackStack(tag).commitAllowingStateLoss();
}
private void setTextSizeInWidget(int value) {
//widgetCreator.setTextSize(value);
//updatePreview();
}
private void setBackgroundAlpha(int alpha) {
widgetDto.setBackgroundAlpha(100 - alpha);
updatePreview();
}
@Override
public void updatePreview() {
binding.previewLayout.removeAllViews();
RemoteViews removeViews = widgetCreator.createTempViews(widgetWidth, widgetHeight);
View view = removeViews.apply(getApplicationContext(), binding.previewLayout);
binding.previewLayout.addView(view);
}
}
package com.lifedawn.bestweather.widget;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.PreferenceManager;
import android.app.Activity;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.widget.TextView;
import com.lifedawn.bestweather.R;
import com.lifedawn.bestweather.commons.classes.MainThreadWorker;
import com.lifedawn.bestweather.databinding.ActivityDialogBinding;
import com.lifedawn.bestweather.main.MainActivity;
import com.lifedawn.bestweather.room.callback.DbQueryCallback;
import com.lifedawn.bestweather.room.dto.WidgetDto;
import com.lifedawn.bestweather.widget.creator.AbstractWidgetCreator;
import com.lifedawn.bestweather.widget.creator.EighthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.EleventhWidgetCreator;
import com.lifedawn.bestweather.widget.creator.FirstWidgetCreator;
import com.lifedawn.bestweather.widget.creator.NinthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.SecondWidgetCreator;
import com.lifedawn.bestweather.widget.creator.SeventhWidgetCreator;
import com.lifedawn.bestweather.widget.creator.SixthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.TenthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.ThirdWidgetCreator;
import com.lifedawn.bestweather.widget.creator.FourthWidgetCreator;
import com.lifedawn.bestweather.widget.creator.FifthWidgetCreator;
import com.lifedawn.bestweather.widget.widgetprovider.EighthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.EleventhWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.FirstWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.NinthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.SecondWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.SeventhWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.SixthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.TenthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.ThirdWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.FourthWidgetProvider;
import com.lifedawn.bestweather.widget.widgetprovider.FifthWidgetProvider;
public class DialogActivity extends Activity {
private ActivityDialogBinding binding;
private int appWidgetId;
private AbstractWidgetCreator widgetCreator;
private AlertDialog alertDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setBackgroundDrawable(new ColorDrawable(0));
binding = ActivityDialogBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Bundle bundle = getIntent().getExtras();
appWidgetId = bundle.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
final AppWidgetProviderInfo appWidgetProviderInfo = appWidgetManager.getAppWidgetInfo(appWidgetId);
ComponentName componentName = appWidgetProviderInfo.provider;
final String providerClassName = componentName.getClassName();
if (providerClassName.equals(FirstWidgetProvider.class.getName())) {
widgetCreator = new FirstWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(SecondWidgetProvider.class.getName())) {
widgetCreator = new SecondWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(ThirdWidgetProvider.class.getName())) {
widgetCreator = new ThirdWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(FourthWidgetProvider.class.getName())) {
widgetCreator = new FourthWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(FifthWidgetProvider.class.getName())) {
widgetCreator = new FifthWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(SixthWidgetProvider.class.getName())) {
widgetCreator = new SixthWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(SeventhWidgetProvider.class.getName())) {
widgetCreator = new SeventhWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(EighthWidgetProvider.class.getName())) {
widgetCreator = new EighthWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(NinthWidgetProvider.class.getName())) {
widgetCreator = new NinthWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(TenthWidgetProvider.class.getName())) {
widgetCreator = new TenthWidgetCreator(getApplicationContext(), null, appWidgetId);
} else if (providerClassName.equals(EleventhWidgetProvider.class.getName())) {
widgetCreator = new EleventhWidgetCreator(getApplicationContext(), null, appWidgetId);
}
final Class<?> widgetProviderClass = widgetCreator.widgetProviderClass();
final View dialogView = getLayoutInflater().inflate(R.layout.view_widget_dialog, null);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
final Long refreshInterval = sharedPreferences.getLong(getString(R.string.pref_key_widget_refresh_interval), 0L);
String refreshIntervalText = null;
if (refreshInterval > 0) {
String[] autoRefreshIntervalsValue = getResources().getStringArray(R.array.AutoRefreshIntervalsLong);
String[] autoRefreshIntervalsText = getResources().getStringArray(R.array.AutoRefreshIntervals);
for (int i = 0; i < autoRefreshIntervalsValue.length; i++) {
if (refreshInterval.toString().equals(autoRefreshIntervalsValue[i])) {
refreshIntervalText = autoRefreshIntervalsText[i];
break;
}
}
} else {
refreshIntervalText = getString(R.string.disable_auto_refresh);
}
((TextView) dialogView.findViewById(R.id.auto_refresh_interval)).setText(refreshIntervalText);
((TextView) dialogView.findViewById(R.id.widgetTypeName)).setText(appWidgetProviderInfo.loadLabel(getPackageManager()));
((TextView) dialogView.findViewById(R.id.openAppBtn)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
alertDialog.dismiss();
startActivity(intent);
finish();
}
});
((TextView) dialogView.findViewById(R.id.updateBtn)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PendingIntent pendingIntent = widgetCreator.getRefreshPendingIntent();
try {
pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
alertDialog.dismiss();
finish();
}
});
((TextView) dialogView.findViewById(R.id.cancelBtn)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertDialog.dismiss();
finish();
}
});
widgetCreator.loadSavedSettings(new DbQueryCallback<WidgetDto>() {
@Override
public void onResultSuccessful(WidgetDto result) {
MainThreadWorker.runOnUiThread(new Runnable() {
@Override
public void run() {
if (DialogActivity.this.isFinishing() || DialogActivity.this.isDestroyed()) {
return;
}
alertDialog = new AlertDialog.Builder(new ContextThemeWrapper(DialogActivity.this,
R.style.Theme_AppCompat_Light_Dialog))
.setCancelable(true)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
dialog.dismiss();
finish();
}
})
.setView(dialogView)
.create();
alertDialog.show();
alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
});
}
@Override
public void onResultNoData() {
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:configure="com.lifedawn.bestweather.widget.ConfigureWidgetActivity"
android:initialLayout="@layout/view_widget"
android:minWidth="@dimen/ninthWidgetWidth"
android:minHeight="@dimen/ninthWidgetHeight"
android:minResizeWidth="@dimen/ninthWidgetWidth"
android:minResizeHeight="@dimen/ninthWidgetHeight"
android:previewImage="@drawable/widget_preview_9"
android:resizeMode="vertical|horizontal"
android:updatePeriodMillis="0"
android:widgetCategory="home_screen" />
package com.lifedawn.bestweather.widget.creator;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.lifedawn.bestweather.R;
import com.lifedawn.bestweather.commons.enums.WeatherProviderType;
import com.lifedawn.bestweather.commons.enums.WeatherDataType;
import com.lifedawn.bestweather.forremoteviews.RemoteViewsUtil;
import com.lifedawn.bestweather.retrofit.util.WeatherRestApiDownloader;
import com.lifedawn.bestweather.weathers.dataprocessing.response.WeatherResponseProcessor;
import com.lifedawn.bestweather.weathers.dataprocessing.util.WeatherRequestUtil;
import com.lifedawn.bestweather.weathers.models.HourlyForecastDto;
import com.lifedawn.bestweather.weathers.view.DetailSingleTemperatureView;
import com.lifedawn.bestweather.widget.OnDrawBitmapCallback;
import com.lifedawn.bestweather.widget.widgetprovider.NinthWidgetProvider;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class NinthWidgetCreator extends AbstractWidgetCreator {
private final int hourGap = 3;
private final int maxHoursCount = 13;
public NinthWidgetCreator(Context context, WidgetUpdateCallback widgetUpdateCallback, int appWidgetId) {
super(context, widgetUpdateCallback, appWidgetId);
}
@Override
public Set<WeatherDataType> getRequestWeatherDataTypeSet() {
Set<WeatherDataType> set = new HashSet<>();
set.add(WeatherDataType.hourlyForecast);
return set;
}
@Override
public RemoteViews createTempViews(Integer parentWidth, Integer parentHeight) {
RemoteViews remoteViews = createBaseRemoteViews();
RemoteViewsUtil.onSuccessfulProcess(remoteViews);
drawViews(remoteViews, context.getString(R.string.address_name), ZonedDateTime.now().toString(),
WeatherResponseProcessor.getTempHourlyForecastDtoList(context, 24),
null, parentWidth, parentHeight);
return remoteViews;
}
@Override
public Class<?> widgetProviderClass() {
return NinthWidgetProvider.class;
}
public void setDataViews(RemoteViews remoteViews, String addressName, String lastRefreshDateTime,
List<HourlyForecastDto> hourlyForecastDtoList, OnDrawBitmapCallback onDrawBitmapCallback) {
drawViews(remoteViews, addressName, lastRefreshDateTime, hourlyForecastDtoList, onDrawBitmapCallback, null, null);
}
private void drawViews(RemoteViews remoteViews, String addressName, String lastRefreshDateTime,
List<HourlyForecastDto> hourlyForecastDtoList, @Nullable OnDrawBitmapCallback onDrawBitmapCallback, @Nullable Integer parentWidth,
@Nullable Integer parentHeight) {
RelativeLayout rootLayout = new RelativeLayout(context);
LinearLayout hourAndIconLinearLayout = new LinearLayout(context);
hourAndIconLinearLayout.setId(R.id.hourAndIconView);
hourAndIconLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout.LayoutParams hourAndIconCellLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
hourAndIconCellLayoutParams.gravity = Gravity.CENTER;
hourAndIconCellLayoutParams.weight = 1;
LayoutInflater layoutInflater = LayoutInflater.from(context);
View headerView = makeHeaderViews(layoutInflater, addressName, lastRefreshDateTime);
headerView.setId(R.id.header);
List<Integer> tempList = new ArrayList<>();
final String degree = tempDegree;
DateTimeFormatter hour0Formatter = DateTimeFormatter.ofPattern("E\n0");
DateTimeFormatter hourFormatter = DateTimeFormatter.ofPattern("E\nH");
//강우, 강설 여부 확인
boolean haveSnowVolume = false;
boolean haveRainVolume = false;
int count = 1;
int cell = 0;
for (; cell < hourlyForecastDtoList.size(); cell = cell + hourGap) {
if (count > maxHoursCount) {
break;
}
if (hourlyForecastDtoList.get(cell).isHasSnow()) {
haveSnowVolume = true;
}
if (hourlyForecastDtoList.get(cell).isHasRain() || hourlyForecastDtoList.get(cell).isHasPrecipitation()) {
haveRainVolume = true;
}
count++;
}
count = 1;
for (cell = 0; cell < hourlyForecastDtoList.size(); cell = cell + hourGap) {
if (count++ > maxHoursCount) {
break;
}
View view = layoutInflater.inflate(R.layout.view_forecast_item_in_linear, null, false);
if (hourlyForecastDtoList.get(cell).getHours().getHour() == 0) {
((TextView) view.findViewById(R.id.dateTime)).setText(hourlyForecastDtoList.get(cell).getHours().format(hour0Formatter));
} else {
((TextView) view.findViewById(R.id.dateTime)).setText(hourlyForecastDtoList.get(cell).getHours().format(hourFormatter));
}
((ImageView) view.findViewById(R.id.leftIcon)).setImageResource(hourlyForecastDtoList.get(cell).getWeatherIcon());
view.findViewById(R.id.temperature).setVisibility(View.GONE);
view.findViewById(R.id.rightIcon).setVisibility(View.GONE);
view.findViewById(R.id.popLayout).setVisibility(View.GONE);
view.findViewById(R.id.rainVolumeLayout).setVisibility(View.GONE);
view.findViewById(R.id.snowVolumeLayout).setVisibility(View.GONE);
tempList.add(Integer.parseInt(hourlyForecastDtoList.get(cell).getTemp().replace(degree, "")));
hourAndIconLinearLayout.addView(view, hourAndIconCellLayoutParams);
}
RelativeLayout.LayoutParams headerViewLayoutParams = getHeaderViewLayoutParams();
RelativeLayout.LayoutParams hourAndIconRowLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
RelativeLayout.LayoutParams tempRowLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
headerViewLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
hourAndIconRowLayoutParams.addRule(RelativeLayout.BELOW, R.id.header);
tempRowLayoutParams.addRule(RelativeLayout.BELOW, R.id.hourAndIconView);
tempRowLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
DetailSingleTemperatureView detailSingleTemperatureView = new DetailSingleTemperatureView(context, tempList);
rootLayout.addView(headerView, headerViewLayoutParams);
rootLayout.addView(hourAndIconLinearLayout, hourAndIconRowLayoutParams);
rootLayout.addView(detailSingleTemperatureView, tempRowLayoutParams);
drawBitmap(rootLayout, onDrawBitmapCallback, remoteViews, parentWidth, parentHeight);
}
@Override
public void setDisplayClock(boolean displayClock) {
widgetDto.setDisplayClock(displayClock);
}
@Override
public void setDataViewsOfSavedData() {
WeatherProviderType weatherProviderType = WeatherResponseProcessor.getMainWeatherSourceType(widgetDto.getWeatherProviderTypeSet());
if (widgetDto.isTopPriorityKma() && widgetDto.getCountryCode().equals("KR")) {
weatherProviderType = WeatherProviderType.KMA_WEB;
}
WeatherRequestUtil.initWeatherSourceUniqueValues(weatherProviderType, true, context);
RemoteViews remoteViews = createRemoteViews();
zoneId = ZoneId.of(widgetDto.getTimeZoneId());
JsonObject jsonObject = (JsonObject) JsonParser.parseString(widgetDto.getResponseText());
WeatherRequestUtil.initWeatherSourceUniqueValues(weatherProviderType, false, context);
List<HourlyForecastDto> hourlyForecastDtoList = WeatherResponseProcessor.parseTextToHourlyForecastDtoList(context, jsonObject,
weatherProviderType, widgetDto.getLatitude(), widgetDto.getLongitude(), zoneId);
setDataViews(remoteViews, widgetDto.getAddressName(), widgetDto.getLastRefreshDateTime(),
hourlyForecastDtoList, null);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViewsUtil.onSuccessfulProcess(remoteViews);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
@Override
public void setResultViews(int appWidgetId, @Nullable @org.jetbrains.annotations.Nullable WeatherRestApiDownloader weatherRestApiDownloader, ZoneId zoneId) {
this.zoneId = zoneId;
final List<HourlyForecastDto> hourlyForecastDtoList = WeatherResponseProcessor.getHourlyForecastDtoList(context, weatherRestApiDownloader,
WeatherResponseProcessor.getMainWeatherSourceType(widgetDto.getWeatherProviderTypeSet()), zoneId);
final boolean successful = !hourlyForecastDtoList.isEmpty();
if (successful) {
ZoneOffset zoneOffset = hourlyForecastDtoList.get(0).getHours().getOffset();
widgetDto.setTimeZoneId(zoneId.getId());
widgetDto.setLastRefreshDateTime(weatherRestApiDownloader.getRequestDateTime().toString());
makeResponseTextToJson(weatherRestApiDownloader, getRequestWeatherDataTypeSet(), widgetDto.getWeatherProviderTypeSet(), widgetDto, zoneOffset);
}
widgetDto.setLoadSuccessful(successful);
super.setResultViews(appWidgetId, weatherRestApiDownloader, zoneId);
}
}
package com.lifedawn.bestweather.widget.widgetprovider;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
public class NinthWidgetProvider extends BaseAppWidgetProvider {
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
}
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout"
style="@style/WidgetBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:clickable="true"
android:focusable="true"
>
<FrameLayout
android:id="@+id/valuesLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:gravity="center"
android:visibility="gone"
>
<FrameLayout
android:id="@+id/noBitmapValuesView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
/>
<ImageView
android:id="@+id/bitmapValuesView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription"
/>
</FrameLayout>
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminate="true"
android:indeterminateTint="@color/blue"
/>
<include
layout="@layout/layout_warning_for_remoteviews"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"
/>
</RelativeLayout>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment