com.joulespersecond.seattlebusbot.tripservice.NotifierTask.java Source code

Java tutorial

Introduction

Here is the source code for com.joulespersecond.seattlebusbot.tripservice.NotifierTask.java

Source

/*
 * Copyright (C) 2010 Paul Watts (paulcwatts@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.joulespersecond.seattlebusbot.tripservice;

import android.app.Notification;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;

import com.joulespersecond.oba.provider.ObaContract;
import com.joulespersecond.oba.provider.ObaContract.TripAlerts;
import com.joulespersecond.oba.provider.ObaContract.Trips;
import com.joulespersecond.seattlebusbot.ArrivalsListActivity;
import com.joulespersecond.seattlebusbot.R;
import com.joulespersecond.seattlebusbot.TripService;
import com.joulespersecond.seattlebusbot.util.UIHelp;

/**
 * @author paulw
 */
public final class NotifierTask implements Runnable {
    //private static final String TAG = "NotifierTask";

    private static final long ONE_MINUTE = 60 * 1000;

    private static final String[] ALERT_PROJECTION = { ObaContract.TripAlerts._ID, ObaContract.TripAlerts.TRIP_ID,
            ObaContract.TripAlerts.STOP_ID, ObaContract.TripAlerts.STATE, };

    private static final int COL_ID = 0;

    private static final int COL_TRIP_ID = 1;

    private static final int COL_STOP_ID = 2;

    private static final int COL_STATE = 3;

    private final Context mContext;

    private final TaskContext mTaskContext;

    private final ContentResolver mCR;

    private final Uri mUri;

    private long mTimeDiff;

    public NotifierTask(Context context, TaskContext taskContext, Uri uri, long timeDiff) {
        mContext = context;
        mTaskContext = taskContext;
        mCR = mContext.getContentResolver();
        mUri = uri;
        mTimeDiff = timeDiff;
    }

    @Override
    public void run() {
        Cursor c = mCR.query(mUri, ALERT_PROJECTION, null, null, null);

        try {
            if (c != null) {
                while (c.moveToNext()) {
                    notify(c);
                }
            }
        } finally {
            if (c != null) {
                c.close();
            }
            mTaskContext.taskComplete();
        }
    }

    private void notify(Cursor c) {
        final int id = c.getInt(COL_ID);
        final String tripId = c.getString(COL_TRIP_ID);
        final String stopId = c.getString(COL_STOP_ID);
        final int state = c.getInt(COL_STATE);
        if (state == TripAlerts.STATE_CANCELLED) {
            return;
        }
        final Uri tripUri = ObaContract.Trips.buildUri(tripId, stopId);
        final String routeId = UIHelp.stringForQuery(mContext, tripUri, Trips.ROUTE_ID);

        // Set our state to notified
        Notification notification = mTaskContext.getNotification(id);

        // #104 - Instantiate the deleteIntent here, since we need to re-set it in setLatestInfo()
        Intent deleteIntent = new Intent(mContext, TripService.class);
        deleteIntent.setAction(TripService.ACTION_CANCEL);
        deleteIntent.setData(mUri);
        PendingIntent pendingIntent = PendingIntent.getService(mContext, 0, deleteIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        if (notification == null) {
            notification = createNotification(pendingIntent);
        }

        setLatestInfo(notification, stopId, routeId, mTimeDiff, pendingIntent);
        mTaskContext.setNotification(id, notification);
    }

    /*
    private static final long[] VIBRATE_PATTERN = {
    0,    // on
    1000, // off
    1000, // on
    1000, // off
    1000, // on
    1000, // off
    };
    */

    private Notification createNotification(PendingIntent deleteIntent) {
        return new NotificationCompat.Builder(mContext).setSmallIcon(R.drawable.ic_stat_notification)
                .setDefaults(Notification.DEFAULT_ALL).setOnlyAlertOnce(true)
                //.setLights(0xFF00FF00, 1000, 1000)
                //.setVibrate(VIBRATE_PATTERN)
                .setDeleteIntent(deleteIntent).build();
    }

    @SuppressWarnings("deprecation")
    private void setLatestInfo(Notification notification, String stopId, String routeId, long timeDiff,
            PendingIntent deleteIntent) {
        final String title = mContext.getString(R.string.app_name);

        final PendingIntent intent = PendingIntent.getActivity(mContext, 0,
                new ArrivalsListActivity.Builder(mContext, stopId).getIntent(), PendingIntent.FLAG_UPDATE_CURRENT);

        notification.setLatestEventInfo(mContext, title, getNotifyText(routeId, timeDiff), intent);

        // #104 - Bug in setLatestEventInfo() erases the deleteIntent, so reset it here
        notification.deleteIntent = deleteIntent;
    }

    private String getNotifyText(String routeId, long timeDiff) {
        final String routeName = TripService.getRouteShortName(mContext, routeId);

        if (timeDiff <= 0) {
            return mContext.getString(R.string.trip_stat_gone, routeName);
        } else if (timeDiff < ONE_MINUTE) {
            return mContext.getString(R.string.trip_stat_lessthanone, routeName);
        } else if (timeDiff < ONE_MINUTE * 2) {
            return mContext.getString(R.string.trip_stat_one, routeName);
        } else {
            return mContext.getString(R.string.trip_stat, routeName, (int) (timeDiff / ONE_MINUTE));
        }
    }
}