org.alfresco.mobile.android.platform.AlfrescoNotificationManager.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.mobile.android.platform.AlfrescoNotificationManager.java

Source

/*******************************************************************************
 * Copyright (C) 2005-2014 Alfresco Software Limited.
 *
 * This file is part of Alfresco Mobile for Android.
 *
 * 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 org.alfresco.mobile.android.platform;

import org.alfresco.mobile.android.async.Operation;
import org.alfresco.mobile.android.async.OperationRequestIds;
import org.alfresco.mobile.android.async.OperationSchema;
import org.alfresco.mobile.android.async.OperationsContentProvider;
import org.alfresco.mobile.android.async.node.create.CreateDocumentRequest;
import org.alfresco.mobile.android.async.node.download.DownloadRequest;
import org.alfresco.mobile.android.async.node.update.UpdateContentRequest;
import org.alfresco.mobile.android.foundation.R;
import org.alfresco.mobile.android.platform.intent.PrivateIntent;
import org.alfresco.mobile.android.platform.provider.CursorUtils;
import org.alfresco.mobile.android.platform.utils.AndroidVersion;
import org.alfresco.mobile.android.platform.utils.SessionUtils;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.NotificationCompat;
import android.text.Html;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

import de.keyboardsurfer.android.widget.crouton.Crouton;
import de.keyboardsurfer.android.widget.crouton.Style;

/**
 * Manager responsible of all dialog, notification and warning
 * 
 * @author jpascal
 */
public class AlfrescoNotificationManager extends Manager {
    // ///////////////////////////////////////////////////////////////////////////
    // CHANNELS
    // ///////////////////////////////////////////////////////////////////////////
    public static final int CHANNEL_DEFAULT = 500;

    protected static final int CHANNEL_DEFAULT_INDEX = 0;

    public static final int CHANNEL_UPLOAD = 501;

    protected static final int CHANNEL_UPLOAD_INDEX = 1;

    public static final int CHANNEL_DOWNLOAD = 502;

    protected static final int CHANNEL_DOWNLOAD_INDEX = 2;

    public static final int CHANNEL_SYNC = 510;

    protected static final int CHANNEL_SYNC_INDEX = 3;

    // ///////////////////////////////////////////////////////////////////////////
    // BUNDLE
    // ///////////////////////////////////////////////////////////////////////////
    public static final String ARGUMENT_TITLE = "title";

    public static final String ARGUMENT_DESCRIPTION = "description";

    public static final String ARGUMENT_PROGRESS_MAX = "size";

    public static final String ARGUMENT_INDETERMINATE = "indeterminate";

    public static final String ARGUMENT_CONTENT_INFO = "contentInfo";

    public static final String ARGUMENT_SMALL_ICON = "smallIcon";

    public static final String ARGUMENT_PROGRESS = "progress";

    public static final String ARGUMENT_CHANNEL = "channel";

    // ///////////////////////////////////////////////////////////////////////////
    // ARGUMENTS
    // ///////////////////////////////////////////////////////////////////////////
    protected static final Object LOCK = new Object();

    private static final String TAG = AlfrescoNotificationManager.class.getSimpleName();

    protected static Manager mInstance;

    // ///////////////////////////////////////////////////////////////////////////
    // CONSTRUCTOR
    // ///////////////////////////////////////////////////////////////////////////
    protected AlfrescoNotificationManager(Context applicationContext) {
        super(applicationContext);
    }

    public static AlfrescoNotificationManager getInstance(Context context) {
        synchronized (LOCK) {
            if (mInstance == null) {
                mInstance = Manager.getInstance(context, AlfrescoNotificationManager.class.getSimpleName());
            }
            return (AlfrescoNotificationManager) mInstance;
        }
    }

    // ///////////////////////////////////////////////////////////////////////////
    // LIFECYCLE
    // ///////////////////////////////////////////////////////////////////////////
    public void shutdown() {
        mInstance = null;
    }

    // //////////////////////////////////////////////////////////////////////
    // TOAST
    // //////////////////////////////////////////////////////////////////////
    public void showToast(String text) {
        int duration = Toast.LENGTH_SHORT;
        Toast toast = Toast.makeText(appContext, text, duration);
        toast.show();
    }

    public void showToast(int text) {
        int duration = Toast.LENGTH_SHORT;
        Toast toast = Toast.makeText(appContext, text, duration);
        toast.show();
    }

    public void showLongToast(String text) {
        int duration = Toast.LENGTH_LONG;
        Toast toast = Toast.makeText(appContext, text, duration);
        toast.show();
    }

    public void showLongToast(int text) {
        int duration = Toast.LENGTH_LONG;
        Toast toast = Toast.makeText(appContext, text, duration);
        toast.show();
    }

    // //////////////////////////////////////////////////////////////////////
    // CROUTON
    // //////////////////////////////////////////////////////////////////////
    public void showInfoCrouton(Activity activity, String text) {
        Crouton.cancelAllCroutons();
        Crouton.showText(activity, Html.fromHtml(text), Style.INFO);
    }

    public void showAlertCrouton(Activity activity, String text) {
        Crouton.cancelAllCroutons();
        Crouton.showText(activity, Html.fromHtml(text), Style.ALERT);
    }

    public void showInfoCrouton(Activity activity, int text) {
        Crouton.cancelAllCroutons();
        Crouton.showText(activity, text, Style.INFO);
    }

    public void showAlertCrouton(Activity activity, int text) {
        Crouton.cancelAllCroutons();
        Crouton.showText(activity, text, Style.ALERT);
    }

    // ///////////////////////////////////////////////////////////////////////////
    // ACTIONBAR NOTIFICATION METHODS
    // ///////////////////////////////////////////////////////////////////////////
    public int createSimpleNotification(int notificationId, String title, String description, String contentInfo) {
        Bundle b = new Bundle();
        b.putString(ARGUMENT_TITLE, title);
        if (description != null) {
            b.putString(ARGUMENT_DESCRIPTION, description);
        }
        if (contentInfo != null) {
            b.putString(ARGUMENT_CONTENT_INFO, contentInfo);
        }
        return createNotification(notificationId, b);
    }

    public int createIndeterminateNotification(int notificationId, String title, String description,
            String contentInfo) {
        Bundle b = new Bundle();
        b.putString(ARGUMENT_TITLE, title);
        b.putBoolean(ARGUMENT_INDETERMINATE, true);
        if (description != null) {
            b.putString(ARGUMENT_DESCRIPTION, description);
        }
        if (contentInfo != null) {
            b.putString(ARGUMENT_CONTENT_INFO, contentInfo);
        }
        return createNotification(notificationId, b);
    }

    public int createProgressNotification(int notificationId, String title, String description, String contentInfo,
            long progress, long maxprogress) {
        Bundle b = new Bundle();
        b.putString(ARGUMENT_TITLE, title);
        b.putBoolean(ARGUMENT_INDETERMINATE, false);
        b.putLong(ARGUMENT_PROGRESS_MAX, maxprogress);
        b.putLong(ARGUMENT_PROGRESS, progress);
        if (description != null) {
            b.putString(ARGUMENT_DESCRIPTION, description);
        }
        if (contentInfo != null) {
            b.putString(ARGUMENT_CONTENT_INFO, contentInfo);
        }
        return createNotification(notificationId, b);
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public int createNotification(int notificationId, Bundle params) {
        Notification notification;

        // Get the builder to create notification.
        NotificationCompat.Builder builder = new NotificationCompat.Builder(appContext.getApplicationContext());
        builder.setContentTitle(params.getString(ARGUMENT_TITLE));
        if (params.containsKey(ARGUMENT_DESCRIPTION)) {
            builder.setContentText(params.getString(ARGUMENT_DESCRIPTION));
        }
        builder.setNumber(0);

        if (AndroidVersion.isLollipopOrAbove()) {
            builder.setSmallIcon(R.drawable.ic_notification);
            builder.setColor(appContext.getResources().getColor(R.color.alfresco_sky));
        } else {
            builder.setSmallIcon(R.drawable.ic_notification);
        }

        if (params.containsKey(ARGUMENT_DESCRIPTION)) {
            builder.setContentText(params.getString(ARGUMENT_DESCRIPTION));
        }

        if (params.containsKey(ARGUMENT_CONTENT_INFO)) {
            builder.setContentInfo(params.getString(ARGUMENT_CONTENT_INFO));
        }

        if (params.containsKey(ARGUMENT_SMALL_ICON)) {
            builder.setSmallIcon(params.getInt(ARGUMENT_SMALL_ICON));
        }

        Intent i;
        PendingIntent pIntent;
        switch (notificationId) {
        case CHANNEL_SYNC:
            i = new Intent(PrivateIntent.ACTION_SYNCHRO_DISPLAY);
            pIntent = PendingIntent.getActivity(appContext, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
            break;

        default:
            i = new Intent(PrivateIntent.ACTION_DISPLAY_OPERATIONS);
            i.putExtra(PrivateIntent.EXTRA_OPERATIONS_TYPE, notificationId);
            if (SessionUtils.getAccount(appContext) != null) {
                i.putExtra(PrivateIntent.EXTRA_ACCOUNT_ID, SessionUtils.getAccount(appContext).getId());
            }
            pIntent = PendingIntent.getActivity(appContext, 0, i, 0);
            break;
        }
        builder.setContentIntent(pIntent);

        if (AndroidVersion.isICSOrAbove()) {
            if (params.containsKey(ARGUMENT_PROGRESS_MAX) && params.containsKey(ARGUMENT_PROGRESS)) {
                long max = params.getLong(ARGUMENT_PROGRESS_MAX);
                long progress = params.getLong(ARGUMENT_PROGRESS);
                float value = (((float) progress / ((float) max)) * 100);
                int percentage = Math.round(value);
                builder.setProgress(100, percentage, false);
            }

            if (params.getBoolean(ARGUMENT_INDETERMINATE)) {
                builder.setProgress(0, 0, true);
            }
        } else {
            RemoteViews remote = new RemoteViews(appContext.getPackageName(), R.layout.app_notification);
            remote.setImageViewResource(R.id.status_icon, R.drawable.ic_application_logo);
            remote.setTextViewText(R.id.status_text, params.getString(ARGUMENT_TITLE));
            remote.setProgressBar(R.id.status_progress, params.getInt(ARGUMENT_PROGRESS_MAX), 0, false);
            builder.setContent(remote);
        }

        if (AndroidVersion.isJBOrAbove()) {
            builder.setPriority(0);
            notification = builder.build();
        } else {
            notification = builder.getNotification();
        }

        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        ((NotificationManager) appContext.getSystemService(Context.NOTIFICATION_SERVICE)).notify(notificationId,
                notification);

        return notificationId;
    }

    // ///////////////////////////////////////////////////////////////////////////
    // HANDLERS
    // ///////////////////////////////////////////////////////////////////////////
    protected class NotificationTimer implements Runnable {
        int channelId;

        public NotificationTimer(int channelId) {
            this.channelId = channelId;
        }

        @Override
        public void run() {
            createNotificationChannel(channelId);
            if (channelStatus[getIndex(channelId)]) {
                // Log.d(TAG, "Refresh");
                downloadHandler.postDelayed(this, 1000);
            }
        }
    }

    // ///////////////////////////////////////////////////////////////////////////
    // CHANNELS
    // ///////////////////////////////////////////////////////////////////////////
    private Handler downloadHandler = new Handler();

    private NotificationTimer[] channelTimers = new NotificationTimer[4];

    private Boolean[] channelStatus = { false, false, false, false };

    private Integer getIndex(int channelId) {
        try {
            int index = CHANNEL_DEFAULT_INDEX;
            switch (channelId) {
            case CHANNEL_DOWNLOAD:
                index = CHANNEL_DOWNLOAD_INDEX;
                break;
            case CHANNEL_SYNC:
                index = CHANNEL_SYNC_INDEX;
                break;
            case CHANNEL_UPLOAD:
                index = CHANNEL_UPLOAD_INDEX;
                break;
            default:
                break;
            }
            return index;
        } catch (Exception e) {
            return null;
        }
    }

    private NotificationTimer getTimer(int channelId) {
        try {
            return channelTimers[getIndex(channelId)];
        } catch (Exception e) {
            return null;
        }
    }

    public void startRefresh(int channelId) {
        if (getTimer(channelId) != null) {
            return;
        }
        NotificationTimer notificationTimer = new NotificationTimer(channelId);
        channelTimers[getIndex(channelId)] = notificationTimer;
        channelStatus[getIndex(channelId)] = true;

        // start it with
        downloadHandler.post(notificationTimer);
    }

    public void monitorChannel(int requestTypeId) {
        // Log.d(TAG, "[Refresh] START");

        int channelId = CHANNEL_DEFAULT;
        switch (requestTypeId) {
        case OperationRequestIds.ID_NODE_CREATE:
        case OperationRequestIds.ID_NODE_UPDATE_CONTENT:
        case OperationRequestIds.ID_NODE_UPDATE:
            channelId = CHANNEL_UPLOAD;
            break;
        case OperationRequestIds.ID_NODE_DOWNLOAD:
            channelId = CHANNEL_DOWNLOAD;
            break;
        default:

            break;
        }

        if (channelId != CHANNEL_DEFAULT) {
            startRefresh(channelId);
        }
    }

    public void cancelMonitorChannel(int channelId) {
        // Log.d(TAG, "[Refresh] STOP");
        channelStatus[getIndex(channelId)] = false;
        channelTimers[getIndex(channelId)] = null;
    }

    public void unMonitorChannel(int requestTypeId) {
        // Log.d(TAG, "[Refresh] STOP");
        int channelId = CHANNEL_DEFAULT;
        switch (requestTypeId) {
        case OperationRequestIds.ID_NODE_CREATE:
        case OperationRequestIds.ID_NODE_UPDATE_CONTENT:
        case OperationRequestIds.ID_NODE_UPDATE:
            channelId = CHANNEL_UPLOAD;
            break;
        case OperationRequestIds.ID_NODE_DOWNLOAD:
            channelId = CHANNEL_DOWNLOAD;
            break;
        default:

            break;
        }

        channelStatus[getIndex(channelId)] = false;
        channelTimers[getIndex(channelId)] = null;
    }

    private void createNotificationChannel(int channelId) {
        Cursor cursor = null;
        int inProgress = 0;
        int completed = 0;
        long downloadedSoFar = 0, totalSize = 0;
        int total;
        String title = null, description = null, contentInfo = null;
        try {
            // Retrieve Info
            cursor = createCursor(channelId);
            total = cursor.getCount();
            while (cursor.moveToNext()) {
                int status = cursor.getInt(OperationSchema.COLUMN_STATUS_ID);
                totalSize += cursor.getLong(OperationSchema.COLUMN_TOTAL_SIZE_BYTES_ID);
                switch (status) {
                case Operation.STATUS_PAUSED:
                case Operation.STATUS_PENDING:
                    break;
                case Operation.STATUS_RUNNING:
                    inProgress++;
                    downloadedSoFar += cursor.getLong(OperationSchema.COLUMN_BYTES_DOWNLOADED_SO_FAR_ID);
                    break;
                case Operation.STATUS_SUCCESSFUL:
                    downloadedSoFar += cursor.getLong(OperationSchema.COLUMN_TOTAL_SIZE_BYTES_ID);
                    completed++;
                    break;
                default:
                    break;
                }
            }

            // Create the associated
            switch (channelId) {
            case CHANNEL_DOWNLOAD:
                if (total == 0) {
                    cancelMonitorChannel(CHANNEL_DOWNLOAD);
                    return;
                }
                // COMPLETED
                if (completed == total) {
                    title = String.format(appContext.getResources().getQuantityString(
                            R.plurals.download_complete_description, completed), Integer.toString(completed));
                    description = appContext.getString(R.string.download_complete);
                    cancelMonitorChannel(CHANNEL_DOWNLOAD);
                } else {
                    title = String.format(
                            appContext.getResources().getQuantityString(R.plurals.download_in_progress, total),
                            Integer.toString(total));
                    description = appContext.getString(R.string.download_progress);
                }
                contentInfo = completed + "/" + total;
                break;
            case CHANNEL_UPLOAD:
                if (total == 0) {
                    cancelMonitorChannel(CHANNEL_UPLOAD);
                    return;
                }
                // COMPLETED
                if (completed == total) {
                    title = String.format(appContext.getResources().getQuantityString(
                            R.plurals.upload_complete_description, completed), Integer.toString(completed));
                    description = appContext.getString(R.string.upload_complete);
                    cancelMonitorChannel(CHANNEL_UPLOAD);
                } else {
                    title = String.format(
                            appContext.getResources().getQuantityString(R.plurals.batch_in_progress, total),
                            Integer.toString(total));
                    description = appContext.getString(R.string.upload_in_progress);
                }
                contentInfo = completed + "/" + total;
                break;
            case CHANNEL_SYNC:
                break;
            default:
                break;
            }

            if (completed == total) {
                createSimpleNotification(channelId, title, description, contentInfo);
            } else if (downloadedSoFar != totalSize) {
                createProgressNotification(channelId, title, description, contentInfo, downloadedSoFar, totalSize);
            } else {
                createIndeterminateNotification(channelId, title, description, contentInfo);
            }
            Log.d(TAG, title + " " + description + " " + contentInfo + " " + downloadedSoFar + " " + totalSize + " "
                    + (downloadedSoFar / totalSize) * 100 + " " + 100);
        } catch (Exception e) {
        } finally {
            CursorUtils.closeCursor(cursor);
        }
    }

    // ///////////////////////////////////////////////////////////////////////////
    // EVENTS RECEIVER
    // ///////////////////////////////////////////////////////////////////////////
    private static final String UPLOAD_REQUESTS = OperationSchema.COLUMN_REQUEST_TYPE + " IN ("
            + CreateDocumentRequest.TYPE_ID + "," + UpdateContentRequest.TYPE_ID + ")";

    private static final String DOWNLOAD_REQUESTS = OperationSchema.COLUMN_REQUEST_TYPE + " IN ("
            + DownloadRequest.TYPE_ID + ")";

    private static final String ALL_REQUESTS = OperationSchema.COLUMN_REQUEST_TYPE + " IN ("
            + DownloadRequest.TYPE_ID + "," + CreateDocumentRequest.TYPE_ID + "," + UpdateContentRequest.TYPE_ID
            + ")";

    public Cursor createCursor(int id) {
        if (id <= 0) {
            return null;
        }

        String request = ALL_REQUESTS;
        switch (id) {
        case AlfrescoNotificationManager.CHANNEL_DOWNLOAD:
            request = DOWNLOAD_REQUESTS;
            break;
        case AlfrescoNotificationManager.CHANNEL_UPLOAD:
            request = UPLOAD_REQUESTS;
            break;
        default:
            break;
        }

        if (SessionUtils.getAccount(appContext) != null) {
            request = OperationsContentProvider.getAccountFilter(SessionUtils.getAccount(appContext)) + " AND "
                    + request;
        }

        Uri baseUri = OperationsContentProvider.CONTENT_URI;
        return appContext.getContentResolver().query(baseUri, OperationSchema.COLUMN_ALL, request, null, null);
    }

    // ///////////////////////////////////////////////////////////////////////////
    // EVENTS RECEIVER
    // ///////////////////////////////////////////////////////////////////////////

}