ru.gelin.android.weather.notification.skin.impl.BaseWeatherNotificationReceiver.java Source code

Java tutorial

Introduction

Here is the source code for ru.gelin.android.weather.notification.skin.impl.BaseWeatherNotificationReceiver.java

Source

/*
 *  Android Weather Notification.
 *  Copyright (C) 2010  Denis Nelubin aka Gelin
 *
 *  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 2 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, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  http://gelin.ru
 *  mailto:den@gelin.ru
 */

package ru.gelin.android.weather.notification.skin.impl;

import android.app.Notification;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;
import ru.gelin.android.weather.TemperatureUnit;
import ru.gelin.android.weather.Weather;
import ru.gelin.android.weather.WeatherCondition;
import ru.gelin.android.weather.WeatherConditionType;
import ru.gelin.android.weather.notification.ParcelableWeather2;
import ru.gelin.android.weather.notification.WeatherStorage;
import ru.gelin.android.weather.notification.skin.Tag;

import java.util.List;

import static ru.gelin.android.weather.notification.skin.impl.ResourceIdFactory.STRING;

/**
 *  Weather notification receiver built into basic application.
 */
abstract public class BaseWeatherNotificationReceiver extends WeatherNotificationReceiver {

    /** Key to store the weather in the bundle */
    static final String WEATHER_KEY = "weather";

    /** Handler to receive the weather */
    static Handler handler;

    /**
     *  Registers the handler to receive the new weather.
     *  The handler is owned by activity which have initiated the update.
     *  The handler is used to update the weather displayed by the activity. 
     */
    static synchronized void registerWeatherHandler(Handler handler) {
        BaseWeatherNotificationReceiver.handler = handler;
    }

    /**
     *  Unregisters the weather update handler.
     */
    static synchronized void unregisterWeatherHandler() {
        BaseWeatherNotificationReceiver.handler = null;
    }

    @Override
    protected void cancel(Context context) {
        Log.d(Tag.TAG, "cancelling weather");
        getNotificationManager(context).cancel(getNotificationId());
    }

    @Override
    protected void notify(Context context, Weather weather) {
        Log.d(Tag.TAG, "displaying weather: " + weather);

        WeatherStorage storage = new WeatherStorage(context);
        storage.save(weather);

        WeatherFormatter formatter = getWeatherFormatter(context, weather);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);

        builder.setSmallIcon(getNotificationIconId(weather));

        if (weather.isEmpty() || weather.getConditions().size() <= 0) {
            builder.setTicker(context.getString(formatter.getIds().id(STRING, "unknown_weather")));
        } else {
            builder.setTicker(formatter.formatTicker());
            builder.setSmallIcon(getNotificationIconId(weather),
                    getNotificationIconLevel(weather, formatter.getStyler().getTempType().getTemperatureUnit()));
        }

        builder.setWhen(weather.getQueryTime().getTime());
        builder.setOngoing(true);
        builder.setAutoCancel(false);

        builder.setContentIntent(getContentIntent(context));

        //Lollipop notification on lock screen
        builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);

        Notification notification = builder.build();

        switch (formatter.getStyler().getNotifyStyle()) {
        case CUSTOM_STYLE:
            RemoteViews views = new RemoteViews(context.getPackageName(), formatter.getStyler().getLayoutId());
            RemoteWeatherLayout layout = getRemoteWeatherLayout(context, views, formatter.getStyler());
            layout.bind(weather);
            notification.contentView = views;
            break;
        case STANDARD_STYLE:
            builder.setContentTitle(formatter.formatContentTitle());
            builder.setContentText(formatter.formatContentText());
            Bitmap largeIcon = formatter.formatLargeIcon();
            if (largeIcon != null) {
                builder.setLargeIcon(largeIcon);
            }
            notification = builder.build();
            break;
        }

        getNotificationManager(context).notify(getNotificationId(), notification);

        notifyHandler(weather);
    }

    /**
     *  Returns the notification ID for the skin.
     *  Different skins withing the same application must return different results here.
     */
    protected int getNotificationId() {
        return this.getClass().getName().hashCode();
    }

    /**
     *  Returns the pending intent called on click on notification.
     *  This intent starts the weather info activity.
     */
    protected PendingIntent getContentIntent(Context context) {
        Intent intent = new Intent();
        intent.setComponent(getWeatherInfoActivityComponentName());
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        return PendingIntent.getActivity(context, 0, intent, 0);
    }

    protected void notifyHandler(Weather weather) {
        synchronized (BaseWeatherNotificationReceiver.class) { //monitor of static methods
            if (handler == null) {
                return;
            }
            Message message = handler.obtainMessage();
            Bundle bundle = message.getData();
            bundle.putParcelable(WEATHER_KEY, new ParcelableWeather2(weather));
            message.sendToTarget();
        }
    }

    /**
     *  Returns the component name of the weather info activity
     */
    abstract protected ComponentName getWeatherInfoActivityComponentName();

    /**
     *  Returns the ID of the notification icon based on the current weather.
     */
    protected int getNotificationIconId(Weather weather) {
        List<WeatherCondition> conditions = weather.getConditions();
        if (conditions == null || conditions.isEmpty()) {
            return WeatherConditionFormat.getDrawableId(WeatherConditionType.CLOUDS_CLEAR);
        }
        return WeatherConditionFormat.getDrawableId(weather.getConditions().iterator().next());
    }

    /**
     *  Returns the notification icon level.
     */
    protected int getNotificationIconLevel(Weather weather, TemperatureUnit unit) {
        return 24; //24dp for notification icon size
    }

    /**
     *  Creates the remove view layout for the notification.
     */
    protected RemoteWeatherLayout getRemoteWeatherLayout(Context context, RemoteViews views,
            NotificationStyler styler) {
        return new RemoteWeatherLayout(context, views, styler);
    }

    /**
     *  Creates the weather formatter.
     */
    protected WeatherFormatter getWeatherFormatter(Context context, Weather weather) {
        return new WeatherFormatter(context, weather);
    }

}