package co.sfng.calendarwidget;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Events;
import android.text.format.DateFormat;
import android.widget.RemoteViews;
import java.util.Calendar;
import java.util.List;
public class CalendarWidgetProvider extends AppWidgetProvider {
private static final String ACTION_PREVIOUS_MONTH =
"co.sfng.calendarwidget.ACTION_PREVIOUS_MONTH";
private static final String ACTION_NEXT_MONTH = "co.sfng.calendarwidget.ACTION_NEXT_MONTH";
private static final String ACTION_TODAY = "co.sfng.calendarwidget.ACTION_TODAY";
private static final String ACTION_DATE_CLICK = "co.sfng.calendarwidget.ACTION_DATE_CLICK";
private static final String EXTRA_YEAR = "co.sfng.calendarwidget.EXTRA_YEAR";
private static final String EXTRA_MONTH = "co.sfng.calendarwidget.EXTRA_MONTH";
private static final String EXTRA_DATE = "co.sfng.calendarwidget.EXTRA_DATE";
private static final String PREFERENCE_FILE =
"co.sfng.calendarwidget.PREFERENCE_WIDGET_";
private static final String PREF_SELECTED_TIME = "selected_time";
private static final String PREF_IS_WIDE = "is_wide";
// Constants for Date click actions.
private static final int VIEW_CALENDAR = 1;
private static final int CREATE_EVENT = 2;
private static final int WEEKS = 6;
@Override
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
// Obtain widget width and set flag in SharePreferences.
Bundle bundle = appWidgetManager.getAppWidgetOptions(appWidgetId);
if (bundle != null) {
int minWidth = bundle.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
Resources res = context.getResources();
boolean isWide = minWidth > res.getInteger(R.integer.minimum_wide_width);
SharedPreferences pref = context.getSharedPreferences(
getPreferenceFileName(appWidgetId), Context.MODE_PRIVATE);
pref.edit().putBoolean(PREF_IS_WIDE, isWide).apply();
}
render(context, appWidgetId, getTheme(context), getWeekStartDay(context));
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
int theme = getTheme(context);
int weekStartDay = getWeekStartDay(context);
for (int appWidgetId: appWidgetIds) {
render(context, appWidgetId, theme, weekStartDay);
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
for (int appWidgetId: appWidgetIds) {
SharedPreferences pref = context.getSharedPreferences(
getPreferenceFileName(appWidgetId), Context.MODE_PRIVATE);
pref.edit().clear().apply();
}
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
String action = intent.getAction();
int appWidgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if (ACTION_PREVIOUS_MONTH.equals(action)) {
previousMonth(context, appWidgetManager, appWidgetId);
} else if (ACTION_NEXT_MONTH.equals(action)) {
nextMonth(context, appWidgetManager, appWidgetId);
} else if (ACTION_TODAY.equals(action)) {
today(context, appWidgetManager, appWidgetId);
} else if (ACTION_DATE_CLICK.equals(action)) {
int onDateClickAction = getOnDateClickAction(context);
if (onDateClickAction == VIEW_CALENDAR) {
// View calendar
Calendar cal = Calendar.getInstance();
cal.set(intent.getIntExtra(EXTRA_YEAR, -1), intent.getIntExtra(EXTRA_MONTH, -1),
intent.getIntExtra(EXTRA_DATE, -1));
Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
builder.appendPath("time");
ContentUris.appendId(builder, cal.getTimeInMillis());
Intent calIntent = new Intent(Intent.ACTION_VIEW).setData(builder.build());
calIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(calIntent);
} else if (onDateClickAction == CREATE_EVENT) {
// Create new event.
Calendar cal = Calendar.getInstance();
cal.set(intent.getIntExtra(EXTRA_YEAR, -1), intent.getIntExtra(EXTRA_MONTH, -1),
intent.getIntExtra(EXTRA_DATE, -1));
Intent calIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
calIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, cal.getTimeInMillis());
calIntent.putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY);
calIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(calIntent);
}
}
}
private void previousMonth(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
SharedPreferences pref = context.getSharedPreferences(
getPreferenceFileName(appWidgetId), Context.MODE_PRIVATE);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(pref.getLong(PREF_SELECTED_TIME, cal.getTimeInMillis()));
cal.set(Calendar.DATE, 1);
cal.add(Calendar.MONTH, -1);
pref.edit().putLong(PREF_SELECTED_TIME, cal.getTimeInMillis()).apply();
render(context, appWidgetId, getTheme(context), getWeekStartDay(context));
}
private void nextMonth(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
SharedPreferences pref = context.getSharedPreferences(
getPreferenceFileName(appWidgetId), Context.MODE_PRIVATE);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(pref.getLong(PREF_SELECTED_TIME, cal.getTimeInMillis()));
cal.set(Calendar.DATE, 1);
cal.add(Calendar.MONTH, 1);
pref.edit().putLong(PREF_SELECTED_TIME, cal.getTimeInMillis()).apply();
render(context, appWidgetId, getTheme(context), getWeekStartDay(context));
}
private void today(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
SharedPreferences pref = context.getSharedPreferences(
getPreferenceFileName(appWidgetId), Context.MODE_PRIVATE);
pref.edit().remove(PREF_SELECTED_TIME).apply();
render(context, appWidgetId, getTheme(context), getWeekStartDay(context));
}
private String getPreferenceFileName(int appWidgetId) {
return PREFERENCE_FILE + appWidgetId;
}
private int getTheme(Context context) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
return Integer.parseInt(pref.getString(SettingsFragment.PREF_THEME, "0"));
}
private int getWeekStartDay(Context context) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
String s = pref.getString(SettingsFragment.PREF_WEEK_START_DAY,
String.valueOf(Calendar.SUNDAY));
return Integer.parseInt(s);
}
private int getOnDateClickAction(Context context) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
String s = pref.getString(SettingsFragment.PREF_ON_DAY_CLICK, "0");
return Integer.parseInt(s);
}
private void render(Context context, int appWidgetId, int theme, int weekStartDay) {
Calendar cal = Calendar.getInstance();
int todayDate = cal.get(Calendar.DATE);
int todayMonth = cal.get(Calendar.MONTH);
int todayYear = cal.get(Calendar.YEAR);
// Obtain last selected time from SharedPreferences.
SharedPreferences pref = context.getSharedPreferences(
getPreferenceFileName(appWidgetId), Context.MODE_PRIVATE);
long selectedTime = pref.getLong(PREF_SELECTED_TIME, cal.getTimeInMillis());
cal.setTimeInMillis(selectedTime);
String pkgName = context.getPackageName();
RemoteViews widgetView = new RemoteViews(pkgName, ResourceHelper.layoutWidget(theme));
widgetView.removeAllViews(R.id.calendar);
// Set month label.
String fmt = pref.getBoolean(PREF_IS_WIDE, false) ? "MMMM yyyy" : "MMM yyyy";
widgetView.setTextViewText(R.id.month_year_label, DateFormat.format(fmt, cal));
// Render day of week.
renderDayOfWeek(widgetView, weekStartDay);
int selectedMonth = cal.get(Calendar.MONTH);
cal.set(Calendar.DATE, 1);
cal.add(Calendar.DATE, weekStartDay - cal.get(Calendar.DAY_OF_WEEK));
for (int i = 0; i < WEEKS; i++) {
RemoteViews rowView = new RemoteViews(pkgName, R.layout.row_week);
for (int j = 0; j < 7; j++) {
int date = cal.get(Calendar.DATE);
int month = cal.get(Calendar.MONTH);
int year = cal.get(Calendar.YEAR);
boolean isWithinMonth = month == selectedMonth;
boolean isToday = date == todayDate && month == todayMonth && year == todayYear;
int layoutId = ResourceHelper.layoutCellDay(theme);
if (isToday && isWithinMonth) {
layoutId = ResourceHelper.layoutCellToday(theme);
} else if (isWithinMonth) {
layoutId = ResourceHelper.layoutCellInMonth(theme);
}
RemoteViews dateView = new RemoteViews(pkgName, layoutId);
dateView.setTextViewText(android.R.id.text1, Integer.toString(date));
dateView.setOnClickPendingIntent(
android.R.id.text1,
createDateClickPendingIntent(context, appWidgetId, year, month, date));
rowView.addView(R.id.row_week, dateView);
cal.add(Calendar.DATE, 1);
}
widgetView.addView(R.id.calendar, rowView);
}
// Attach action to buttons.
widgetView.setOnClickPendingIntent(R.id.previous_month_button,
createPendingIntent(context, appWidgetId, ACTION_PREVIOUS_MONTH));
widgetView.setOnClickPendingIntent(R.id.next_month_button,
createPendingIntent(context, appWidgetId, ACTION_NEXT_MONTH));
widgetView.setOnClickPendingIntent(R.id.month_year_label,
createPendingIntent(context, appWidgetId, ACTION_TODAY));
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
appWidgetManager.updateAppWidget(appWidgetId, widgetView);
}
private void renderDayOfWeek(RemoteViews rv, int weekStartDay) {
List<String> list = DayOfWeekHelper.getDayOfWeek(weekStartDay);
rv.setTextViewText(R.id.day_of_week0, list.get(0));
rv.setTextViewText(R.id.day_of_week1, list.get(1));
rv.setTextViewText(R.id.day_of_week2, list.get(2));
rv.setTextViewText(R.id.day_of_week3, list.get(3));
rv.setTextViewText(R.id.day_of_week4, list.get(4));
rv.setTextViewText(R.id.day_of_week5, list.get(5));
rv.setTextViewText(R.id.day_of_week6, list.get(6));
}
private PendingIntent createPendingIntent(Context context, int appWidgetId, String action) {
Intent intent = new Intent(context, CalendarWidgetProvider.class);
intent.setAction(action);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
return PendingIntent.getBroadcast(context, appWidgetId, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
private PendingIntent createDateClickPendingIntent(Context context, int appWidgetId, int year,
int month, int date) {
Intent intent = new Intent(context, CalendarWidgetProvider.class);
intent.setAction(ACTION_DATE_CLICK);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(EXTRA_YEAR, year);
intent.putExtra(EXTRA_MONTH, month);
intent.putExtra(EXTRA_DATE, date);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
return PendingIntent.getBroadcast(
context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
}