/* * 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; } }