diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e112d6e68..1ee89ad22 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -53,6 +53,20 @@
android:label=""
android:configChanges="orientation|screenSize"
android:theme="@style/AppTheme.NoActionBar"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java b/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java
index 85110ac16..00fb2d45b 100644
--- a/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java
+++ b/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java
@@ -8,7 +8,7 @@ import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;
-class LoyaltyCardCursorAdapter extends CursorAdapter
+public class LoyaltyCardCursorAdapter extends CursorAdapter
{
public LoyaltyCardCursorAdapter(Context context, Cursor cursor)
{
diff --git a/app/src/main/java/protect/card_locker/appwidget/CardAppWidgetConfigure.java b/app/src/main/java/protect/card_locker/appwidget/CardAppWidgetConfigure.java
new file mode 100644
index 000000000..1f611876f
--- /dev/null
+++ b/app/src/main/java/protect/card_locker/appwidget/CardAppWidgetConfigure.java
@@ -0,0 +1,130 @@
+package protect.card_locker.appwidget;
+
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import protect.card_locker.DBHelper;
+import protect.card_locker.LoyaltyCard;
+import protect.card_locker.LoyaltyCardCursorAdapter;
+import protect.card_locker.R;
+
+/**
+ * The configuration screen for the CardAppWidgetProvider widget.
+ */
+public class CardAppWidgetConfigure extends AppCompatActivity
+{
+ static final String TAG = "LoyaltyCardLocker";
+
+ private static final String PREFS_NAME
+ = "protect.card_locker.appwidget.CardAppWidgetProvider";
+ private static final String PREF_PREFIX_KEY = "prefix_";
+
+ int appWidgetId_ = AppWidgetManager.INVALID_APPWIDGET_ID;
+
+ @Override
+ public void onCreate(Bundle bundle)
+ {
+ super.onCreate(bundle);
+
+ // Set the result to CANCELED. This will cause the widget host to cancel
+ // out of the widget placement if they press the back button.
+ setResult(RESULT_CANCELED);
+
+ setContentView(R.layout.main_activity);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ toolbar.setVisibility(View.GONE);
+
+ setTitle(R.string.selectCardTitle);
+
+ // Find the widget id from the intent.
+ Intent intent = getIntent();
+ Bundle extras = intent.getExtras();
+ if (extras != null)
+ {
+ appWidgetId_ = extras.getInt(
+ AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
+ }
+
+ // If they gave us an intent without the widget id, just bail.
+ if (appWidgetId_ == AppWidgetManager.INVALID_APPWIDGET_ID)
+ {
+ finish();
+ }
+
+ final DBHelper db = new DBHelper(this);
+
+ // If there are no cards, bail
+ if(db.getLoyaltyCardCount() == 0)
+ {
+ finish();
+ }
+
+ final ListView cardList = (ListView) findViewById(R.id.list);
+ cardList.setVisibility(View.VISIBLE);
+
+ Cursor cardCursor = db.getLoyaltyCardCursor();
+
+ final LoyaltyCardCursorAdapter adapter = new LoyaltyCardCursorAdapter(this, cardCursor);
+ cardList.setAdapter(adapter);
+
+ cardList.setOnItemClickListener(new AdapterView.OnItemClickListener()
+ {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id)
+ {
+ Context context = CardAppWidgetConfigure.this;
+ Cursor selected = (Cursor) parent.getItemAtPosition(position);
+ LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
+
+ Log.d(TAG, "Saving card " + loyaltyCard.store + "," + loyaltyCard.id + " at " + appWidgetId_);
+
+ // Save the association of the card to the widget
+ saveIdPref(context, appWidgetId_, loyaltyCard.id);
+
+ // Push widget update to surface with newly set association
+ AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+ CardAppWidgetProvider.updateAppWidget(context, appWidgetManager, appWidgetId_);
+
+ // Make sure we pass back the original appWidgetId
+ Intent resultValue = new Intent();
+ resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId_);
+ setResult(RESULT_OK, resultValue);
+ finish();
+ }
+ });
+ }
+
+ // Write the prefix to the SharedPreferences object for this widget
+ static void saveIdPref(Context context, int appWidgetId, int id)
+ {
+ SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
+ prefs.putInt(PREF_PREFIX_KEY + appWidgetId, id);
+ prefs.commit();
+ }
+
+ // Read the prefix from the SharedPreferences object for this widget.
+ // If there is no preference saved, get the default from a resource
+ static Integer loadIdPref(Context context, int appWidgetId)
+ {
+ SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
+ int id = prefs.getInt(PREF_PREFIX_KEY + appWidgetId, -1);
+ if(id >= 0)
+ {
+ return id;
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
diff --git a/app/src/main/java/protect/card_locker/appwidget/CardAppWidgetProvider.java b/app/src/main/java/protect/card_locker/appwidget/CardAppWidgetProvider.java
new file mode 100644
index 000000000..162e6ff90
--- /dev/null
+++ b/app/src/main/java/protect/card_locker/appwidget/CardAppWidgetProvider.java
@@ -0,0 +1,79 @@
+package protect.card_locker.appwidget;
+
+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 protect.card_locker.DBHelper;
+import protect.card_locker.LoyaltyCard;
+import protect.card_locker.LoyaltyCardViewActivity;
+import protect.card_locker.R;
+
+public class CardAppWidgetProvider extends AppWidgetProvider
+{
+ private static final String TAG = "LoyaltyCardLocker";
+
+ @Override
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
+ {
+ Log.d(TAG, "CardAppWidgetProvider onUpdate");
+ // For each widget that needs an update, get the text that we should display:
+ // - Create a RemoteViews object for it
+ // - Set the text in the RemoteViews object
+ // - Tell the AppWidgetManager to show that views object for the widget.
+ for (int appWidgetId : appWidgetIds)
+ {
+ updateAppWidget(context, appWidgetManager, appWidgetId);
+ }
+ }
+
+ static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId)
+ {
+ Log.d(TAG, "updateAppWidget appWidgetId=" + appWidgetId);
+
+ LoyaltyCard card = null;
+ DBHelper db = new DBHelper(context);
+
+ Integer id = CardAppWidgetConfigure.loadIdPref(context, appWidgetId);
+ if(id != null)
+ {
+ Log.d(TAG, "updateAppWidget Retrieved id " + id);
+ card = db.getLoyaltyCard(id);
+ }
+
+ if(card != null)
+ {
+ Log.d(TAG, "updateAppWidget Updating widget " + appWidgetId + " to load " + card.store);
+
+ // Construct the RemoteViews object. It takes the package name (in our case, it's our
+ // package, but it needs this because on the other side it's the widget host inflating
+ // the layout from our package).
+ RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider);
+ views.setTextViewText(R.id.title, card.store);
+
+ // Launch the view activity when clicked
+ Intent intent = new Intent(context, LoyaltyCardViewActivity.class);
+ Bundle extras = new Bundle();
+ extras.putInt("id", id);
+ extras.putBoolean("view", true);
+ intent.putExtras(extras);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
+ views.setOnClickPendingIntent(R.id.widget, pendingIntent);
+
+ // Tell the widget manager
+ appWidgetManager.updateAppWidget(appWidgetId, views);
+ }
+ else
+ {
+ Log.d(TAG, "updateAppWidget, no card ID associated with widget " + appWidgetId
+ + ", ignoring update");
+ }
+ }
+}
diff --git a/app/src/main/res/layout/appwidget_provider.xml b/app/src/main/res/layout/appwidget_provider.xml
new file mode 100644
index 000000000..1c8c550e4
--- /dev/null
+++ b/app/src/main/res/layout/appwidget_provider.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 628aab111..1f6d21eca 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -31,6 +31,7 @@
Add Loyalty Card
View Loyalty Card
Scan Card\'s Barcode
+ Select Card
Image of card\'s barcode
diff --git a/app/src/main/res/xml/appwidget_provider.xml b/app/src/main/res/xml/appwidget_provider.xml
new file mode 100644
index 000000000..24c3b655d
--- /dev/null
+++ b/app/src/main/res/xml/appwidget_provider.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file