How to format an UTC-timecode in the listitems of a scrollable widget?

48 views
Skip to first unread message

arne...@gmail.com

unread,
Jun 24, 2012, 7:23:26 PM6/24/12
to android-appwid...@googlegroups.com
Hello,

I am trying to format an UTC-based time (milliseconds-value) from the database into a user-readable format and display it in our scrollable widget for each listitem.
The list and listitems are constructed using the v2 API and I am testing with Go Launcher EX which is apparently based on ADWlauncher2 (for which I have the source as reference).

The listitems are displaying the UTC-timecode, but I tried reformatting them in several ways:
  1. First, I tried subclassing BoundRemoteViews to override BindingAction.getValue, but this gives me a ClassNotFoundException during unmarshalling this subclass, and the launcher crashes constantly trying to update the appwidget.
  2. Then I looked into the ContentProvider-side and tried to modify the cursor by modifying its CursorWindow as described here but it doesnt change the displayed values.
I even thought about introducing a new DB-table or at least a new column in an existing table just to hold the display-values for this appwidget, but I hope there is a simpler, more straightforward way to do this.

If you know of any solution for this problem, please let me know.

Arne

Code of the subclass of BoundRemtoeViews:
public class OurBoundRemoteViews extends BoundRemoteViews {
    UpdateServiceDelegateCustom delegate;

    public OurBoundRemoteViews(int layoutId) {
        super(layoutId);
        delegate = new UpdateServiceDelegateCustom(ContextManager.getContext());
    }

    @Override
    public void setBoundCharSequence(int viewId, String methodName, int cursorIndex, int defaultResource) {
        addAction(new OurBindingAction(viewId, methodName, ReflectionAction.CHAR_SEQUENCE,
                                    cursorIndex, defaultResource));
    }

    protected class OurBindingAction extends BoundRemoteViews.BindingAction {
        public OurBindingAction(int viewId, String methodName, int type,
                int cursorIndex, int defaultResource) {
            super(viewId, methodName, type, cursorIndex, defaultResource);
        }

        @Override
        protected Object getValue(Context context) {
            Object value = super.getValue(context);

            if (this.viewId == R.id.task_due) {
                long millisDueDate = (Long) value;
                String relDateString = UpdateServiceDelegateCustom.getTaskRelativeDueDateFromMillis(context, millisDueDate);
                return relDateString;
            } else {
                return value;
            }
        }

        @Override
        public void apply(View root) {
            if (this.viewId == R.id.task_due) {
                TextView dueDateTextView = (TextView)root;
                long millisDueDate = (Long) super.getValue(root.getContext());
                if (Task.hasDueDate(millisDueDate)) {
                    int textcolor = OurBoundRemoteViews.this.delegate.getTaskDueDateTextColor(millisDueDate);
                    dueDateTextView.setVisibility(View.VISIBLE);
                    dueDateTextView.setTextColor(textcolor);
                } else {
                    dueDateTextView.setVisibility(View.VISIBLE);
                }
            }

            super.apply(root);
        }
    }
}

Code of attempt to modify the cursor:
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {

        Cursor cursor = database.rawQuery(selection, null);
        // modify the duedate-value for display in scrollable-widget in powerwidget for custom launchers
        if (uri.getPathSegments().contains("appwidgetid") && cursor instanceof AbstractDatabase.ModifiableCursor) {
            updateCursorDataForRelativeDueDate(cursor);
        }
        return cursor;
    }

    /**
     * @param cursor
     */
    void updateCursorDataForRelativeDueDate(Cursor cursor) {
        AbstractDatabase.ModifiableCursor modifiableCursor = (AbstractDatabase.ModifiableCursor) cursor;
        int colIndexDueDate = modifiableCursor.getColumnIndex(Task.DUE_DATE.name);
        if (colIndexDueDate == -1)
            return; // duedate-column is not in the query, abort
        // init the CursorWindow
        modifiableCursor.moveToFirst();
        if (modifiableCursor.getWindow() != null) {
            CursorWindow cursorWindow = modifiableCursor.getWindow();
            String overduePrefix = ContextManager.getResources().getString(R.string.PPW_past_due);
            int row = -1;
            while(!modifiableCursor.isAfterLast()) {
                row++;
                // get the value of the duedate
                long utcDueDateValue = modifiableCursor.getLong(colIndexDueDate);
                String relDateString = UpdateServiceDelegateCustom.getTaskRelativeDueDateFromMillis(ContextManager.getContext(), utcDueDateValue);
                if (utcDueDateValue > 0 && utcDueDateValue < DateUtilities.now())
                    relDateString = overduePrefix+" "+relDateString; // overdue
                cursorWindow.putString(relDateString, row, colIndexDueDate);
                modifiableCursor.moveToNext();
            }

        }
    }

Florian Sundermann

unread,
Jun 26, 2012, 3:28:35 AM6/26/12
to android-appwid...@googlegroups.com
Hi,

1) subclassing the BoundRemoteViews will not work cause the launcher
dosn't know your subclass and cant deserialize it. --> Crash
2) I would use a ExtMatrixCursor -->
http://code.google.com/p/scrollablecontacts/source/browse/trunk/src/com/boombuler/widgets/contacts/ExtMatrixCursor.java
which is like a MatrixCursor but bugfixed ;-)

So query your values from the database -> modify them to their display
values -> store them in the matrixcursor and then use the matrix
cursor instead of the sql cursor. (Which you shouldn't do in the first
place cause it might keep the cursor open for a long time)

Hope that helps.

Regards
Florian


2012/6/25 <arne...@gmail.com>:

Arne Jans

unread,
Jun 26, 2012, 3:38:59 AM6/26/12
to android-appwid...@googlegroups.com

I will try that, thanks!

I used the MatrixCursor on another occasion, how is it buggy?

Arne

Florian Sundermann

unread,
Jun 26, 2012, 3:53:36 AM6/26/12
to android-appwid...@googlegroups.com
Hi,

you can't pass byte[] from one process to another. it will just pass
"byte[].toString()" instead of the content of the array.

2012/6/26 Arne Jans <arne...@gmail.com>:

Arne Jans

unread,
Jul 4, 2012, 2:17:25 PM7/4/12
to android-appwid...@googlegroups.com
Hi,

to let your know, your suggestion worked great, thanks! I have another
problem, though, I post it in a new thread.

Thanks so far!

Arne

2012/6/26 Florian Sundermann <boom...@googlemail.com>:
Reply all
Reply to author
Forward
0 new messages