/*
* AndFHEM - Open Source Android application to control a FHEM home automation
* server.
*
* Copyright (c) 2011, Matthias Klass or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU GENERAL PUBLIC LICENSE, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU GENERAL PUBLIC LICENSE
* for more details.
*
* You should have received a copy of the GNU GENERAL PUBLIC LICENSE
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package li.klass.fhem.appwidget;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetHost;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import com.google.common.base.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import li.klass.fhem.appwidget.service.AppWidgetUpdateService;
import li.klass.fhem.appwidget.view.widget.base.AppWidgetView;
import li.klass.fhem.constants.Actions;
import li.klass.fhem.util.ApplicationProperties;
import li.klass.fhem.util.NetworkState;
import li.klass.fhem.util.preferences.SharedPreferencesService;
import static java.lang.Integer.parseInt;
import static li.klass.fhem.constants.BundleExtraKeys.ALLOW_REMOTE_UPDATES;
import static li.klass.fhem.constants.BundleExtraKeys.APP_WIDGET_ID;
import static li.klass.fhem.service.room.RoomListService.NEVER_UPDATE_PERIOD;
public class AppWidgetDataHolder {
private static final String WIDGET_UPDATE_INTERVAL_PREFERENCES_KEY_WLAN = "WIDGET_UPDATE_INTERVAL_WLAN";
private static final String WIDGET_UPDATE_INTERVAL_PREFERENCES_KEY_MOBILE = "WIDGET_UPDATE_INTERVAL_MOBILE";
static final String SAVE_PREFERENCE_NAME = AppWidgetDataHolder.class.getName();
public static final Logger LOG = LoggerFactory.getLogger(AppWidgetDataHolder.class);
@Inject
ApplicationProperties applicationProperties;
@Inject
SharedPreferencesService sharedPreferencesService;
@Inject
public AppWidgetDataHolder() {
}
public void updateAllWidgets(final Context context, final boolean allowRemoteUpdate) {
Set<String> appWidgetIds = getAllAppWidgetIds(context);
for (String appWidgetId : appWidgetIds) {
context.startService(getRedrawWidgetIntent(context, parseInt(appWidgetId), allowRemoteUpdate));
}
}
Set<String> getAllAppWidgetIds(Context context) {
SharedPreferences sharedPreferences = getSavedPreferences(context);
Map<String, ?> allEntries = sharedPreferences.getAll();
assert allEntries != null;
return allEntries.keySet();
}
private Intent getRedrawWidgetIntent(Context context, int appWidgetId, boolean allowRemoteUpdate) {
return new Intent(Actions.REDRAW_WIDGET)
.setClass(context, AppWidgetUpdateService.class)
.putExtra(APP_WIDGET_ID, appWidgetId)
.putExtra(ALLOW_REMOTE_UPDATES, allowRemoteUpdate);
}
private SharedPreferences getSavedPreferences(Context context) {
return sharedPreferencesService.getPreferences(SAVE_PREFERENCE_NAME, context);
}
public AppWidgetView getAppWidgetView(WidgetConfiguration configuration) {
return configuration.widgetType.widgetView;
}
public void deleteWidget(Context context, int appWidgetId) {
Log.d(AppWidgetDataHolder.class.getName(), String.format("deleting widget for id %d", appWidgetId));
SharedPreferences preferences = getSavedPreferences(context);
String key = String.valueOf(appWidgetId);
if (preferences.contains(key)) {
preferences.edit().remove(key).apply();
AppWidgetHost host = getAppWidgetHost(context);
host.deleteAppWidgetId(appWidgetId);
}
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
cancelUpdating(context, appWidgetId, alarmManager);
}
AppWidgetHost getAppWidgetHost(Context context) {
return new AppWidgetHost(context, 0);
}
private void cancelUpdating(Context context, int appWidgetId, AlarmManager alarmManager) {
PendingIntent updatePendingIntent = updatePendingIndentForWidgetId(context, appWidgetId);
alarmManager.cancel(updatePendingIntent);
}
public void scheduleUpdateIntent(Context context, WidgetConfiguration widgetConfiguration,
boolean updateImmediately, long widgetUpdateInterval) {
if (widgetUpdateInterval > 0) {
LOG.debug(String.format("scheduling widget update %s => %s ", widgetConfiguration.toString(), (widgetUpdateInterval / 1000) + "s"));
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = updatePendingIndentForWidgetId(context, widgetConfiguration.widgetId);
long now = System.currentTimeMillis();
long firstRun = updateImmediately ? now : now + widgetUpdateInterval;
cancelUpdating(context, widgetConfiguration.widgetId, alarmManager);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, firstRun, widgetUpdateInterval, pendingIntent);
}
}
private PendingIntent updatePendingIndentForWidgetId(Context context, int widgetId) {
Intent updateIntent = getRedrawWidgetIntent(context, widgetId, true);
return PendingIntent.getService(context, widgetId * (-1),
updateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public long getConnectionDependentUpdateInterval(Context context) {
long updateInterval;
if (!NetworkState.isConnected(context)) {
LOG.debug("getConnectionDependentUpdateInterval - no network connection");
updateInterval = NEVER_UPDATE_PERIOD;
} else if (NetworkState.isConnectedMobile(context)) {
LOG.debug("getConnectionDependentUpdateInterval - mobile connection");
updateInterval = getWidgetUpdateIntervalFor(WIDGET_UPDATE_INTERVAL_PREFERENCES_KEY_MOBILE, context);
} else {
LOG.debug("getConnectionDependentUpdateInterval - wlan connection");
updateInterval = getWidgetUpdateIntervalFor(WIDGET_UPDATE_INTERVAL_PREFERENCES_KEY_WLAN, context);
}
return updateInterval;
}
public Optional<WidgetConfiguration> getWidgetConfiguration(int widgetId, Context context) {
SharedPreferences sharedPreferences = getSavedPreferences(context);
String value = sharedPreferences.getString(String.valueOf(widgetId), null);
if (value == null) {
return Optional.absent();
} else {
return Optional.fromNullable(WidgetConfiguration.fromSaveString(value));
}
}
void saveWidgetConfigurationToPreferences(WidgetConfiguration widgetConfiguration, Context context) {
SharedPreferences.Editor edit = sharedPreferencesService.getSharedPreferencesEditor(SAVE_PREFERENCE_NAME, context);
String value = widgetConfiguration.toSaveString();
edit.putString(String.valueOf(widgetConfiguration.widgetId), value);
edit.apply();
}
private int getWidgetUpdateIntervalFor(String key, Context context) {
String value = applicationProperties.getStringSharedPreference(key, "3600", context);
int intValue = parseInt(value);
return intValue * 1000;
}
}