/*
* Copyright (c) 2015 Jonas Kalderstam.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nononsenseapps.notepad.ui.widget;
import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.RemoteViews;
import com.nononsenseapps.notepad.R;
import com.nononsenseapps.notepad.data.model.sql.Task;
import com.nononsenseapps.notepad.data.model.sql.TaskList;
import com.nononsenseapps.notepad.data.receiver.NotePadBroadcastReceiver;
import com.nononsenseapps.notepad.ui.editor.ActivityEditor;
import com.nononsenseapps.notepad.ui.editor.TaskDetailFragment;
import com.nononsenseapps.notepad.ui.list.ActivityList;
import com.nononsenseapps.notepad.util.Log;
/**
* Thewidget's AppWidgetProvider.
*/
public class ListWidgetProvider extends AppWidgetProvider {
// private static final String TAG = "WIDGETPROVIDER";
public static final String COMPLETE_ACTION = "com.nononsenseapps.notepad.widget.COMPLETE";
public static final String CLICK_ACTION = "com.nononsenseapps.notepad.widget.CLICK";
public static final String OPEN_ACTION = "com.nononsenseapps.notepad.widget.OPENAPP";
public static final String CONFIG_ACTION = "com.nononsenseapps.notepad.widget.CONFIG";
public static final String CREATE_ACTION = "com.nononsenseapps.notepad.widget.CREATE";
public static final String EXTRA_NOTE_ID = "com.nononsenseapps.notepad.widget.note_id";
public static final String EXTRA_LIST_ID = "com.nononsenseapps.notepad.widget.list_id";
public ListWidgetProvider() {
}
/**
* Complete note calls go here
*/
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Intent appIntent = new Intent();
appIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
if (action.equals(CLICK_ACTION)) {
Log.d("widgetwork", "CLICK ACTION RECEIVED");
long noteId = intent.getLongExtra(EXTRA_NOTE_ID, -1);
if (noteId > -1) {
appIntent
.setAction(Intent.ACTION_EDIT)
.setData(Task.getUri(noteId))
.putExtra(TaskDetailFragment.ARG_ITEM_LIST_ID,
intent.getLongExtra(EXTRA_LIST_ID, -1));
context.startActivity(appIntent);
}
}
else if (action.equals(COMPLETE_ACTION)) {
// Should send broadcast here
Log.d("widgetwork", "COMPLETE ACTION RECEIVED");
long noteId = intent.getLongExtra(EXTRA_NOTE_ID, -1);
// This will complete the note
if (noteId > -1) {
Intent bintent = new Intent(context,
NotePadBroadcastReceiver.class);
bintent.setAction(context
.getString(R.string.complete_note_broadcast_intent));
bintent.putExtra(Task.Columns._ID, noteId);
context.sendBroadcast(bintent);
}
}
super.onReceive(context, intent);
}
@Override
public void onEnabled(Context context) {
/*
* Register for external updates to the data to trigger an update of the
* widget. When using content providers, the data is often updated via a
* background service, or in response to user interaction in the main
* app. To ensure that the widget always reflects the current state of
* the data, we must listen for changes and update ourselves
* accordingly.
*/
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
Log.d("ListWidgetProvider", "onDeleted, appWidgetIds.length = "
+ String.valueOf(appWidgetIds.length));
for (int widgetId : appWidgetIds) {
WidgetPrefs.delete(context, widgetId);
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// This is not called on start up if we are using a configuration
// activity
// Update each of the widgets with the remote adapter
for (int i = 0; i < appWidgetIds.length; ++i) {
int widgetId = appWidgetIds[i];
// Load widget prefs
final WidgetPrefs prefs = new WidgetPrefs(context, widgetId);
// Build view update
RemoteViews updateViews = buildRemoteViews(context,
appWidgetManager, widgetId, prefs);
// Tell the AppWidgetManager to perform an update
appWidgetManager.updateAppWidget(widgetId, updateViews);
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static RemoteViews buildRemoteViews(final Context context,
final AppWidgetManager appWidgetManager, final int appWidgetId,
final WidgetPrefs settings) {
// Hack: We must set this widget's id in the URI to prevent the
// situation
// where the last widget added will be used for everything
final Uri data = Uri.withAppendedPath(Uri.parse("STUPIDWIDGETS"
+ "://widget/id/"), String.valueOf(appWidgetId));
boolean isKeyguard = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Bundle myOptions = appWidgetManager
.getAppWidgetOptions(appWidgetId);
// Get the value of OPTION_APPWIDGET_HOST_CATEGORY
int category = myOptions.getInt(
AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
// If the value is WIDGET_CATEGORY_KEYGUARD, it's a lockscreen
// widget
isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
}
if (isKeyguard) {
settings.putBoolean(ListWidgetConfig.KEY_LOCKSCREEN, true);
}
// Specify the service to provide data for the collection widget. Note
// that we need to
// embed the appWidgetId via the data otherwise it will be ignored.
final Intent intent = new Intent(context, ListWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews rv = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
rv.setRemoteAdapter(R.id.notesList, intent);
// Set the empty view to be displayed if the collection is empty. It
// must be a sibling
// view of the collection view.
rv.setEmptyView(R.id.notesList, R.id.empty_view);
final long listId = settings.getLong(ListWidgetConfig.KEY_LIST, -1);
final String listTitle = settings.getString(
ListWidgetConfig.KEY_LIST_TITLE,
context.getString(R.string.app_name));
rv.setTextViewText(R.id.titleButton, listTitle);
// Hide header if we should
rv.setViewVisibility(R.id.widgetHeader, settings.getBoolean(
ListWidgetConfig.KEY_HIDDENHEADER, false) ? View.GONE
: View.VISIBLE);
// Set background color
final int color = settings.getInt(ListWidgetConfig.KEY_SHADE_COLOR,
ListWidgetConfig.DEFAULT_SHADE);
rv.setInt(R.id.shade, "setBackgroundColor", color);
rv.setViewVisibility(R.id.shade, (color & 0xff000000) == 0 ? View.GONE
: View.VISIBLE);
/*
* Bind a click listener template for the contents of the list. Note
* that we need to update the intent's data if we set an extra, since
* the extras will be ignored otherwise.
*/
if (isKeyguard) {
final Intent itemIntent = new Intent(context, ActivityList.class);
itemIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent onClickPendingIntent = PendingIntent.getActivity(
context, 0, itemIntent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setPendingIntentTemplate(R.id.notesList, onClickPendingIntent);
}
else {
// To handle complete, we use broadcasts
Intent onClickIntent = new Intent(context, ListWidgetProvider.class);
onClickIntent
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
.putExtra(Task.Columns.DBLIST, listId).setData(data);
PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(
context, 0, onClickIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setPendingIntentTemplate(R.id.notesList, onClickPendingIntent);
}
final Intent appIntent = new Intent();
appIntent
.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK)
.setClass(context, ActivityList.class)
.setAction(Intent.ACTION_VIEW).setData(TaskList.getUri(listId));
PendingIntent openAppPendingIntent = PendingIntent.getActivity(context,
0, appIntent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.titleButton, openAppPendingIntent);
final Intent configIntent = new Intent();
configIntent
.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK)
.setClass(context, ListWidgetConfig.class).setData(data)
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent openConfigPendingIntent = PendingIntent.getActivity(
context, 0, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.widgetConfigButton,
openConfigPendingIntent);
final Intent createIntent = new Intent();
createIntent
.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK)
.setClass(context, ActivityEditor.class)
// Append a dummy path so we don't override this intent on 2nd, 3rd, etc, widgets.
.setAction(Intent.ACTION_INSERT).setData(Uri.withAppendedPath(Task.URI,
"/widget/" + appWidgetId + "/-1"))
.putExtra(TaskDetailFragment.ARG_ITEM_LIST_ID, listId);
PendingIntent createPendingIntent = PendingIntent.getActivity(context,
0, createIntent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.createNoteButton, createPendingIntent);
return rv;
}
}