es.ugr.swad.swadroid.modules.notifications.Notifications.java Source code

Java tutorial

Introduction

Here is the source code for es.ugr.swad.swadroid.modules.notifications.Notifications.java

Source

/*
 *  This file is part of SWADroid.
 *
 *  Copyright (C) 2010 Juan Miguel Boyero Corral <juanmi1982@gmail.com>
 *
 *  SWADroid 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 3 of the License, or
 *  (at your option) any later version.
 *
 *  SWADroid 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 SWADroid.  If not, see <http://www.gnu.org/licenses/>.
 */
package es.ugr.swad.swadroid.modules.notifications;

import android.accounts.Account;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import org.ksoap2.serialization.SoapObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import es.ugr.swad.swadroid.Constants;
import es.ugr.swad.swadroid.R;
import es.ugr.swad.swadroid.analytics.SWADroidTracker;
import es.ugr.swad.swadroid.database.DataBaseHelper;
import es.ugr.swad.swadroid.gui.AlertNotificationFactory;
import es.ugr.swad.swadroid.model.Model;
import es.ugr.swad.swadroid.model.SWADNotification;
import es.ugr.swad.swadroid.modules.Module;
import es.ugr.swad.swadroid.modules.login.Login;
import es.ugr.swad.swadroid.sync.SyncUtils;
import es.ugr.swad.swadroid.utils.DateTimeUtils;
import es.ugr.swad.swadroid.utils.Utils;
import es.ugr.swad.swadroid.webservices.SOAPClient;

/**
 * Notifications module for get user's notifications
 * @see <a href="https://openswad.org/ws/#getNotifications">getNotifications</a>
 *
 * @author Juan Miguel Boyero Corral <juanmi1982@gmail.com>
 * @author Antonio Aguilera Malagon <aguilerin@gmail.com>
 * @author Helena Rodriguez Gijon <hrgijon@gmail.com>
 */
public class Notifications extends Module implements SwipeRefreshLayout.OnRefreshListener {
    /**
     * Unique identifier for notification alerts
     */
    public static final int NOTIF_ALERT_ID = 1982;
    /**
     * Cursor orderby parameter
     */
    private final String orderby = "eventTime DESC";
    /**
     * Notifications counter
     */
    private int notifCount;
    /**
     * Error message returned by the synchronization service
     */
    private String errorMessage;
    /**
     * Notifications tag name for Logcat
     */
    private static final String TAG = Constants.APP_TAG + " Notifications";
    /**
     * Account type
     */
    private static final String accountType = "es.ugr.swad.swadroid";
    /**
     * Synchronization authority
     */
    private static final String authority = "es.ugr.swad.swadroid.content";
    /**
     * Synchronization receiver
     */
    private static SyncReceiver receiver;
    /**
     * Synchronization account
     */
    private static Account account;
    /**
     * Layout with "Pull to refresh" function
     */
    private SwipeRefreshLayout refreshLayout;
    /**
     * Layout containing birthday message
     */
    private LinearLayout mBirthdayLayout;
    /**
     * TextView containing birthday message
     */
    private TextView mBirthdayTextView;
    /**
     * ListView container for notifications
     */
    ExpandableListView list;
    /**
     * Adapter container for notifications
     */
    NotificationsExpandableListAdapter adapter;
    /**
     * TextView for the empty notifications message
     */
    TextView emptyNotifTextView;
    /**
     * List of groups for ExpandableListView
     */
    ArrayList<String> groupItem;
    /**
     * List of childs for ExpandableListView
     */
    ArrayList<List<Model>> childItem;
    /**
     * Id for the not seen notifications group
     */
    int NOT_SEEN_GROUP_ID = 0;
    /**
     * Id for the seen notifications group
     */
    int SEEN_GROUP_ID = 1;
    /**
     * ListView click listener
     */
    private OnChildClickListener clickListener = new OnChildClickListener() {
        @Override
        public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition,
                long id) {

            TextView notifCode = (TextView) v.findViewById(R.id.notifCode);
            TextView code = (TextView) v.findViewById(R.id.eventCode);
            TextView type = (TextView) v.findViewById(R.id.eventType);
            TextView userPhoto = (TextView) v.findViewById(R.id.eventUserPhoto);
            TextView sender = (TextView) v.findViewById(R.id.eventSender);
            TextView course = (TextView) v.findViewById(R.id.eventLocation);
            TextView summary = (TextView) v.findViewById(R.id.eventSummary);
            TextView content = (TextView) v.findViewById(R.id.eventText);
            TextView date = (TextView) v.findViewById(R.id.eventDate);
            TextView time = (TextView) v.findViewById(R.id.eventTime);
            TextView seenLocalText = (TextView) v.findViewById(R.id.seenLocal);

            Intent activity = new Intent(getApplicationContext(), NotificationItem.class);
            activity.putExtra("notifCode", notifCode.getText().toString());
            activity.putExtra("eventCode", code.getText().toString());
            activity.putExtra("notificationType", type.getText().toString());
            activity.putExtra("userPhoto", userPhoto.getText().toString());
            activity.putExtra("sender", sender.getText().toString());
            activity.putExtra("course", course.getText().toString());
            activity.putExtra("summary", summary.getText().toString());
            activity.putExtra("content", content.getText().toString());
            activity.putExtra("date", date.getText().toString());
            activity.putExtra("time", time.getText().toString());
            activity.putExtra("seenLocal", seenLocalText.getText().toString());
            startActivity(activity);

            return true;
        }
    };

    /**
     * Refreshes data on screen
     */
    private void refreshScreen() {
        // Refresh data on screen
        setChildGroupData();
        hideSwipeProgress();

        //If today is the user birthday, show birthday message
        if ((Login.getLoggedUser() != null) && DateTimeUtils.isBirthday(Login.getLoggedUser().getUserBirthday())) {
            mBirthdayTextView.setText(getString(R.string.birthdayMsg).replace(Constants.USERNAME_TEMPLATE,
                    Login.getLoggedUser().getUserFirstname()));
            mBirthdayLayout.setVisibility(View.VISIBLE);
        } else {
            mBirthdayLayout.setVisibility(View.GONE);
        }
    }

    /**
     * Sends to SWAD the "seen notifications" info
     */
    private void sendReadedNotifications() {
        List<Model> markedNotificationsList;
        String seenNotifCodes;
        Intent activity;
        int numMarkedNotificationsList;

        // Construct a list of seen notifications in state
        // "pending to mark as read in SWAD"
        markedNotificationsList = dbHelper.getAllRows(DataBaseHelper.DB_TABLE_NOTIFICATIONS, "seenLocal='"
                + Utils.parseBoolString(true) + "' AND seenRemote='" + Utils.parseBoolString(false) + "'", null);

        numMarkedNotificationsList = markedNotificationsList.size();
        if (isDebuggable)
            Log.d(TAG, "numMarkedNotificationsList=" + numMarkedNotificationsList);

        if (numMarkedNotificationsList > 0) {
            // Creates a string of notification codes separated by commas
            // from the previous list
            seenNotifCodes = Utils.getSeenNotificationCodes(markedNotificationsList);
            if (isDebuggable)
                Log.d(TAG, "seenNotifCodes=" + seenNotifCodes);

            // Sends "seen notifications" info to the server
            activity = new Intent(this, NotificationsMarkAllAsRead.class);
            activity.putExtra("seenNotifCodes", seenNotifCodes);
            activity.putExtra("numMarkedNotificationsList", numMarkedNotificationsList);
            startActivityForResult(activity, Constants.NOTIFMARKALLASREAD_REQUEST_CODE);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.app.Activity#onActivityResult(int, int,
     * android.content.Intent)
     */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == Constants.NOTIFMARKALLASREAD_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                Log.i(TAG, "Notifications marked as read in SWAD");
            } else {
                Log.e(TAG, "Error marking notifications as read in SWAD");
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see es.ugr.swad.swadroid.modules.Module#onCreate(android.os.Bundle)
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.expandablelist_items_pulltorefresh);

        getSupportActionBar().setIcon(R.drawable.notif);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }

        this.findViewById(R.id.groupSpinner).setVisibility(View.GONE);

        refreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container_expandablelist);
        list = (ExpandableListView) findViewById(R.id.expandablelist_pulltorefresh);
        emptyNotifTextView = (TextView) findViewById(R.id.list_item_title);
        mBirthdayLayout = (LinearLayout) findViewById(R.id.birthday_layout);
        mBirthdayTextView = (TextView) findViewById(R.id.birthdayTextView);

        groupItem = new ArrayList<String>();
        childItem = new ArrayList<List<Model>>();

        //Init ExpandableListView
        initSwipeOptions();

        //Set ExpandableListView data
        setGroupData();
        setChildGroupData();

        /*
         * If there aren't notifications to show, hide the notifications list
         * and show the empty notifications message
         */
        if (dbHelper.getAllRowsCount(DataBaseHelper.DB_TABLE_NOTIFICATIONS) == 0) {
            Log.d(TAG, "[onCreate] Notifications table is empty");

            emptyNotifTextView.setText(R.string.notificationsEmptyListMsg);
            emptyNotifTextView.setVisibility(View.VISIBLE);

            list.setOnChildClickListener(null);
            list.setVisibility(View.GONE);
        } else {
            Log.d(TAG, "[onCreate] Notifications table is not empty");

            emptyNotifTextView.setVisibility(View.GONE);
            list.setVisibility(View.VISIBLE);
        }

        setMETHOD_NAME("getNotifications");
        receiver = new SyncReceiver(this);
        account = new Account(getString(R.string.app_name), accountType);
    }

    /**
     * Launches an action when markAllRead button is pushed
     *
     * @param v
     *            Actual view
     */
    public void onMarkAllReadClick(View v) {
        dbHelper.updateAllNotifications("seenLocal", Utils.parseBoolString(true));

        // Sends to SWAD the "seen notifications" info
        sendReadedNotifications();

        refreshScreen();
    }

    /*
     * (non-Javadoc)
     * 
     * @see es.ugr.swad.swadroid.modules.Module#onResume()
     */
    @Override
    protected void onResume() {
        super.onResume();
        SWADroidTracker.sendScreenView(getApplicationContext(), TAG);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(NotificationsSyncAdapterService.START_SYNC);
        intentFilter.addAction(NotificationsSyncAdapterService.STOP_SYNC);
        intentFilter.addAction(Intent.CATEGORY_DEFAULT);
        registerReceiver(receiver, intentFilter);

        Log.i(TAG, "Registered receiver for automatic synchronization");

        refreshScreen();
    }

    /*
     * (non-Javadoc)
     * 
     * @see es.ugr.swad.swadroid.modules.Module#onPause()
     */
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
        Log.i(TAG, "Unregistered receiver for automatic synchronization");
    }

    /*
     * (non-Javadoc)
     * 
     * @see es.ugr.swad.swadroid.modules.Module#requestService()
     */
    @Override
    protected void requestService() throws Exception {
        int numDeletedNotif = 0;

        if (SyncUtils.isSyncAutomatically(getApplicationContext())) {
            Log.i(TAG, "Automatic synchronization is enabled. Requesting asynchronous sync operation");

            // Call synchronization service
            ContentResolver.requestSync(account, authority, new Bundle());
        } else {
            Log.i(TAG, "Automatic synchronization is disabled. Requesting manual sync operation");

            // Calculates next timestamp to be requested
            Long timestamp = Long.valueOf(dbHelper.getFieldOfLastNotification("eventTime"));
            timestamp++;

            // Creates webservice request, adds required params and sends
            // request to webservice
            createRequest(SOAPClient.CLIENT_TYPE);
            addParam("wsKey", Login.getLoggedUser().getWsKey());
            addParam("beginTime", timestamp);
            sendRequest(SWADNotification.class, false);

            if (result != null) {
                dbHelper.beginTransaction();

                // Stores notifications data returned by webservice response
                ArrayList<?> res = new ArrayList<Object>((Vector<?>) result);
                SoapObject soap = (SoapObject) res.get(1);
                int numNotif = soap.getPropertyCount();

                notifCount = 0;
                for (int i = 0; i < numNotif; i++) {
                    SoapObject pii = (SoapObject) soap.getProperty(i);
                    Long notifCode = Long.valueOf(pii.getProperty("notifCode").toString());
                    Long eventCode = Long.valueOf(pii.getProperty("eventCode").toString());
                    String eventType = pii.getProperty("eventType").toString();
                    Long eventTime = Long.valueOf(pii.getProperty("eventTime").toString());
                    String userSurname1 = pii.getProperty("userSurname1").toString();
                    String userSurname2 = pii.getProperty("userSurname2").toString();
                    String userFirstName = pii.getProperty("userFirstname").toString();
                    String userPhoto = pii.getProperty("userPhoto").toString();
                    String location = pii.getProperty("location").toString();
                    String summary = pii.getProperty("summary").toString();
                    Integer status = Integer.valueOf(pii.getProperty("status").toString());
                    String content = pii.getProperty("content").toString();
                    boolean notifReadSWAD = (status >= 4);
                    boolean notifCancelled = (status >= 8);

                    // Add not cancelled notifications only
                    if (!notifCancelled) {
                        SWADNotification n = new SWADNotification(notifCode, eventCode, eventType, eventTime,
                                userSurname1, userSurname2, userFirstName, userPhoto, location, summary, status,
                                content, notifReadSWAD, notifReadSWAD);
                        dbHelper.insertNotification(n);

                        // Count unread notifications only
                        if (!notifReadSWAD) {
                            notifCount++;
                        }

                        if (isDebuggable)
                            Log.d(TAG, n.toString());
                    }
                }

                // Request finalized without errors
                setResult(RESULT_OK);
                Log.i(TAG, "Retrieved " + numNotif + " notifications (" + notifCount + " unread)");

                // Clean old notifications to control database size
                numDeletedNotif = dbHelper.cleanOldNotificationsByAge(Constants.CLEAN_NOTIFICATIONS_THRESHOLD);
                Log.i(TAG, "Deleted " + numDeletedNotif + " notifications from database");

                dbHelper.endTransaction(true);
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see es.ugr.swad.swadroid.modules.Module#connect()
     */
    @Override
    protected void connect() {
        String progressDescription = getString(R.string.notificationsProgressDescription);
        int progressTitle = R.string.notificationsProgressTitle;

        startConnection(false, progressDescription, progressTitle);
    }

    /*
     * (non-Javadoc)
     * 
     * @see es.ugr.swad.swadroid.modules.Module#postConnect()
     */
    @Override
    protected void postConnect() {
        Notification notif;
        Intent notificationIntent = new Intent(this, Notifications.class);
        PendingIntent pendingIntent;

        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //single top to avoid creating many activity stacks queue
        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

        pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);

        if (!SyncUtils.isSyncAutomatically(getApplicationContext())) {
            if (notifCount > 0) {
                notif = AlertNotificationFactory.createAlertNotification(getApplicationContext(),
                        getString(R.string.app_name), notifCount + " " + getString(R.string.notificationsAlertMsg),
                        getString(R.string.app_name), pendingIntent, R.drawable.ic_launcher_swadroid_notif,
                        R.drawable.ic_launcher_swadroid, true, true, false, false);

                AlertNotificationFactory.showAlertNotification(getApplicationContext(), notif, NOTIF_ALERT_ID);
            } else {
                Toast.makeText(this, R.string.NoNotificationsMsg, Toast.LENGTH_LONG).show();
            }

            // Sends to SWAD the "seen notifications" info
            sendReadedNotifications();

            refreshScreen();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see es.ugr.swad.swadroid.modules.Module#onError()
     */
    @Override
    protected void onError() {

    }

    /**
     * Removes all notifications from database
     *
     * @param context
     *            Database context
     */
    public void clearNotifications(Context context) {
        try {
            dbHelper.emptyTable(DataBaseHelper.DB_TABLE_NOTIFICATIONS);
        } catch (Exception e) {
            error(TAG, e.getMessage(), e, true);
        }
    }

    /**
     * Synchronization callback. Is called when synchronization starts and stops
     *
     * @author Juan Miguel Boyero Corral <juanmi1982@gmail.com>
     */
    private class SyncReceiver extends BroadcastReceiver {

        public SyncReceiver(Notifications activity) {

        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(NotificationsSyncAdapterService.START_SYNC)) {
                Log.i(TAG, "Started sync");
            } else if (intent.getAction().equals(NotificationsSyncAdapterService.STOP_SYNC)) {
                Log.i(TAG, "Stopped sync");

                notifCount = intent.getIntExtra("notifCount", 0);
                errorMessage = intent.getStringExtra("errorMessage");
                if ((errorMessage != null) && !errorMessage.equals("")) {
                    error(TAG, errorMessage, null, true);
                } else if (notifCount == 0) {
                    Toast.makeText(context, R.string.NoNotificationsMsg, Toast.LENGTH_LONG).show();
                }

                refreshScreen();
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.notification_activity_actions, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_markAllRead:
            dbHelper.updateAllNotifications("seenLocal", Utils.parseBoolString(true));
            sendReadedNotifications();
            refreshScreen();
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }

    /*
     * @Override public void setContentView(int layoutResID) { View v =
     * getLayoutInflater().inflate(layoutResID, refreshLayout, false);
     * setContentView(v); }
     * 
     * @Override public void setContentView(View view) { setContentView(view,
     * view.getLayoutParams()); }
     * 
     * @Override public void setContentView(View view, ViewGroup.LayoutParams
     * params) { refreshLayout.addView(view, params); initSwipeOptions(); }
     */

    private void initSwipeOptions() {
        refreshLayout.setOnRefreshListener(this);
        setAppearance();
        // disableSwipe();

        list.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView absListView, int scrollState) {
            }

            @Override
            public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount,
                    int totalItemCount) {

                boolean enable = false;
                if (list != null && list.getChildCount() > 0) {
                    // check if the first item of the list is visible
                    boolean firstItemVisible = list.getFirstVisiblePosition() == 0;
                    // check if the top of the first item is visible
                    boolean topOfFirstItemVisible = list.getChildAt(0).getTop() == 0;
                    // enabling or disabling the refresh layout
                    enable = firstItemVisible && topOfFirstItemVisible;
                }
                refreshLayout.setEnabled(enable);
            }
        });
        /*
         * Create a ListView-specific touch listener. ListViews are given special treatment because
         * by default they handle touches for their list items... i.e. they're in charge of drawing
         * the pressed state (the list selector), handling list item clicks, etc.
         * 
         * Requires Android 3.1 (HONEYCOMB_MR1) or newer
         */
        /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
           SwipeListViewTouchListener touchListener =
         new SwipeListViewTouchListener(
               list,
             new SwipeListViewTouchListener.OnSwipeCallback() {                   
                 @Override
                 public void onSwipeLeft(ListView listView, int [] reverseSortedPositions) {
                        if(reverseSortedPositions.length > 0) {
                            swipeItem(reverseSortedPositions[0]);
                        }
                 }
            
                 @Override
                 public void onSwipeRight(ListView listView, int [] reverseSortedPositions) {
                        if(reverseSortedPositions.length > 0) {
                            swipeItem(reverseSortedPositions[0]);
                        }
                 }
            
              @Override
              public void onStartSwipe() {
                        disableSwipe();
              }
            
              @Override
              public void onStopSwipe() {
                 enableSwipe();
              }
             },
             true,
             true);
               
           list.setOnTouchListener(touchListener);
           // Setting this scroll listener is required to ensure that during ListView scrolling,
           // we don't look for swipes.
           list.setOnScrollListener(touchListener.makeScrollListener(refreshLayout));
        } else {
           Log.w(TAG, "SwipeListViewTouchListener requires Android 3.1 (HONEYCOMB_MR1) or newer");
           list.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
           public void onScrollStateChanged(AbsListView absListView, int scrollState) {
           }
            
           @Override
           public void onScroll(AbsListView absListView, int firstVisibleItem,
                   int visibleItemCount, int totalItemCount) {
                  
              boolean enable = false;
             if(list != null && list.getChildCount() > 0){
                 // check if the first item of the list is visible
                 boolean firstItemVisible = list.getFirstVisiblePosition() == 0;
                 // check if the top of the first item is visible
                 boolean topOfFirstItemVisible = list.getChildAt(0).getTop() == 0;
                 // enabling or disabling the refresh layout
                 enable = firstItemVisible && topOfFirstItemVisible;
             }
             refreshLayout.setEnabled(enable);
           }
             });   
        }*/
    }

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    private void setAppearance() {
        refreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright, android.R.color.holo_green_light,
                android.R.color.holo_orange_light, android.R.color.holo_red_light);
    }

    /**
     * It shows the SwipeRefreshLayout progress
     */
    public void showSwipeProgress() {
        refreshLayout.setRefreshing(true);
    }

    /**
     * It shows the SwipeRefreshLayout progress
     */
    public void hideSwipeProgress() {
        refreshLayout.setRefreshing(false);
    }

    /**
     * Enables swipe gesture
     */
    public void enableSwipe() {
        refreshLayout.setEnabled(true);
        //Log.d(TAG, "RefreshLayout Swipe ENABLED");
    }

    /**
     * Disables swipe gesture. It prevents manual gestures but keeps the option
     * to show refreshing programatically.
     */
    public void disableSwipe() {
        refreshLayout.setEnabled(false);
        //Log.d(TAG, "RefreshLayout Swipe DISABLED");
    }

    /**
     * It must be overriden by parent classes if manual swipe is enabled.
     */
    @Override
    public void onRefresh() {
        showSwipeProgress();
        runConnection();

        if (!isConnected) {
            hideSwipeProgress();
        }
    }

    public void setGroupData() {
        groupItem.add(getString(R.string.notSeenLabel));
        groupItem.add(getString(R.string.seenLabel));
    }

    public void setChildGroupData() {
        List<Model> child;

        //Clear data
        childItem.clear();

        //Add data for not seen notifications       
        child = dbHelper.getAllRows(DataBaseHelper.DB_TABLE_NOTIFICATIONS,
                "seenLocal='" + Utils.parseBoolString(false) + "'", orderby);
        childItem.add(child);

        //Add data for seen notifications   
        child = dbHelper.getAllRows(DataBaseHelper.DB_TABLE_NOTIFICATIONS,
                "seenLocal='" + Utils.parseBoolString(true) + "'", orderby);
        childItem.add(child);

        Log.d(TAG, "groups size=" + childItem.size());
        Log.d(TAG, "not seen children size=" + childItem.get(NOT_SEEN_GROUP_ID).size());
        Log.d(TAG, "seen children size=" + childItem.get(SEEN_GROUP_ID).size());

        adapter = new NotificationsExpandableListAdapter(this, groupItem, childItem);

        if (dbHelper.getAllRowsCount(DataBaseHelper.DB_TABLE_NOTIFICATIONS) > 0) {
            Log.d(TAG, "[setChildGroupData] Notifications table is not empty");

            emptyNotifTextView.setVisibility(View.GONE);
            list.setVisibility(View.VISIBLE);

            list.setAdapter(adapter);
            list.setOnChildClickListener(clickListener);

            //Expand the groups
            list.expandGroup(NOT_SEEN_GROUP_ID);
            list.expandGroup(SEEN_GROUP_ID);
        } else {
            Log.d(TAG, "[setChildGroupData] Notifications table is empty");

            list.setVisibility(View.GONE);
            emptyNotifTextView.setVisibility(View.VISIBLE);

            enableSwipe();
        }
    }
}