Completed notifications module

git-svn-id: https://forja.rediris.es/svn/cusl6-swadroid/trunk@108 5bc14d19-1e4b-4ba2-aa50-860af135f48c
This commit is contained in:
Juan Miguel Boyero Corral 2011-11-22 22:09:04 +00:00
parent 733b5fc1f2
commit 9d1dbc421f
11 changed files with 410 additions and 54 deletions

View File

@ -18,16 +18,25 @@ public final class R {
public static final int ic_launcher_swadroid=0x7f020001;
}
public static final class id {
public static final int preferences_menu=0x7f080000;
public static final int eventLocation=0x7f080004;
public static final int eventSender=0x7f080003;
public static final int eventSummary=0x7f080005;
public static final int eventTime=0x7f080002;
public static final int eventType=0x7f080001;
public static final int notificationsUpdateButton=0x7f080000;
public static final int preferences_menu=0x7f080006;
}
public static final class layout {
public static final int functions_list_item=0x7f030000;
public static final int main=0x7f030001;
public static final int notifications=0x7f030002;
public static final int notifications_list_item=0x7f030003;
}
public static final class menu {
public static final int menu_main=0x7f070000;
}
public static final class string {
public static final int notificationsDateMsg=0x7f060027;
public static final int app_name=0x7f060000;
public static final int close_dialog=0x7f060005;
public static final int coursesModuleLabel=0x7f060003;
@ -37,15 +46,22 @@ public final class R {
public static final int errorMsgLaunchingActivity=0x7f060019;
public static final int errorMsgNoConnection=0x7f06001c;
public static final int errorMsgWorkaroundEmulator=0x7f06001a;
public static final int examAnnouncement=0x7f060021;
public static final int forumReply=0x7f060025;
public static final int loginModuleLabel=0x7f060001;
public static final int loginProgressDescription=0x7f060014;
public static final int loginProgressTitle=0x7f060013;
public static final int loginSuccessfulMsg=0x7f06001e;
public static final int loginTitle_menu=0x7f060012;
public static final int marksFile=0x7f060022;
public static final int message=0x7f060024;
public static final int notice=0x7f060023;
public static final int notificationsFromMsg=0x7f060026;
public static final int notificationsModuleLabel=0x7f060002;
public static final int notificationsProgressDescription=0x7f060016;
public static final int notificationsProgressTitle=0x7f060015;
public static final int notificationsSuccessfulMsg=0x7f06001f;
public static final int notificationsUpdateButton=0x7f060020;
public static final int preferencesTitle_menu=0x7f060011;
public static final int saveMsg_preferences=0x7f06000e;
public static final int saveSummary_preferences=0x7f06000f;

View File

@ -2,7 +2,7 @@
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:textColor="#ffffff"
android:textSize="24sp">

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/notificationsUpdateButton"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="@string/notificationsUpdateButton"
android:layout_gravity="center_horizontal"/>
<ListView
android:id="@+id/android:list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:listSelector="@android:color/transparent" />
</LinearLayout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:layout_width="match_parent" android:orientation="vertical">
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/eventType"
android:padding="5dp"
android:textColor="#ffffff"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/eventTime"
android:textColor="#ffffff"
android:padding="1dp"
android:textStyle="italic" />
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/eventSender"
android:textColor="#ffffff"
android:padding="1dp"
android:textStyle="italic" />
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/eventLocation"
android:textColor="#ffffff"
android:padding="1dp"
android:textStyle="italic" />
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/eventSummary"
android:textColor="#ffffff"
android:padding="1dp" />
</LinearLayout>

View File

@ -23,4 +23,10 @@
<string name="errorMsgLaunchingActivity">Ha ocurrido un error durante la ejecución de la operación</string><string name="errorMsgNoConnection">No hay conexión</string>
<string name="errorCopyMsg_DB">Error copiando base de datos</string><string name="upgradeMsg_DB">Actualizando base de datos...</string>
<string name="loginSuccessfulMsg">Conectado</string><string name="notificationsSuccessfulMsg">Notificaciones descargadas</string>
<string name="notificationsUpdateButton">Actualizar</string>
<string name="examAnnouncement">Convocatoria de examen</string>
<string name="marksFile">Archivo de calificaciones</string>
<string name="notice">Aviso</string>
<string name="message">Mensaje</string>
<string name="forumReply">Respuesta en foro</string><string name="notificationsFromMsg">De</string><string name=" notificationsDateMsg">Fecha</string>
</resources>

View File

@ -19,12 +19,20 @@
<string name="loginTitle_menu">Login</string>
<string name="loginProgressTitle">Login</string>
<string name="loginProgressDescription">Connecting...</string>
<string name="notificationsProgressTitle">Notifications</string><string name="notificationsProgressDescription">Fetching new notifications</string><string name="coursesProgressTitle">Courses</string><string name="coursesProgressDescription">Getting courses...</string><string name="errorMsgLaunchingActivity">An error occurred during the execution of the operation</string>
<string name="notificationsProgressTitle">Notifications</string><string name="notificationsProgressDescription">Retrieving new notifications</string><string name="coursesProgressTitle">Courses</string><string name="coursesProgressDescription">Retrieving courses...</string><string name="errorMsgLaunchingActivity">An error occurred during the execution of the operation</string>
<string name="errorMsgWorkaroundEmulator">Damn. That Android emulator bug appeared again. Retrying...</string>
<string name="errorCopyMsg_DB">Error copying database</string>
<string name="errorMsgNoConnection">No connection found</string><string name="upgradeMsg_DB">Upgrading database...</string><string name="loginSuccessfulMsg">Login successful</string>
<string name="notificationsSuccessfulMsg">Notifications fetched</string>
<string name="notificationsUpdateButton">Update</string>
<string name="examAnnouncement">Exam announcement</string>
<string name="marksFile">Marks file</string>
<string name="notice">Notice</string>
<string name="message">Message</string>
<string name="forumReply">Forum reply</string>
<string name="notificationsFromMsg">From</string>
<string name=" notificationsDateMsg">Date</string>

View File

@ -27,7 +27,7 @@ public class Global {
/**
* SWAD application key
*/
private static final String AppKey = "";
private static final String AppKey = "HTC-Desire";
/**
* User logged flag
*/

View File

@ -0,0 +1,120 @@
/*
* 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.gui;
import java.util.Date;
import es.ugr.swad.swadroid.R;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;
/**
* Custom adapter for display notifications
* @author Juan Miguel Boyero Corral <juanmi1982@gmail.com>
*
*/
public class NotificationsCursorAdapter extends CursorAdapter {
public NotificationsCursorAdapter(Context context, Cursor c) {
super(context, c);
}
public NotificationsCursorAdapter(Context context, Cursor c,
boolean autoRequery) {
super(context, c, autoRequery);
}
public NotificationsCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
long unixTime;
String type, sender, from, dateTitle;
Date d;
TextView eventType = (TextView) view.findViewById(R.id.eventType);
TextView eventTime = (TextView) view.findViewById(R.id.eventTime);
TextView eventSender = (TextView) view.findViewById(R.id.eventSender);
TextView location = (TextView) view.findViewById(R.id.eventLocation);
TextView summary = (TextView) view.findViewById(R.id.eventSummary);
if(eventType != null) {
type = cursor.getString(cursor.getColumnIndex("eventType"));
if(type.equals("examAnnouncement"))
{
type = context.getString(R.string.examAnnouncement);
view.setBackgroundColor(Color.parseColor("#088A08"));
} else if(type.equals("marksFile"))
{
type = context.getString(R.string.marksFile);
view.setBackgroundColor(Color.parseColor("#DF7401"));
} else if(type.equals("notice"))
{
type = context.getString(R.string.notice);
view.setBackgroundColor(Color.parseColor("#868A08"));
} else if(type.equals("message"))
{
type = context.getString(R.string.message);
view.setBackgroundColor(Color.BLUE);
} else if(type.equals("forumReply"))
{
type = context.getString(R.string.forumReply);
view.setBackgroundColor(Color.parseColor("#B40404"));
}
eventType.setText(type);
}
if(eventTime != null){
unixTime = Long.parseLong(cursor.getString(cursor.getColumnIndex("eventTime")));
d = new Date(unixTime * 1000);
dateTitle = context.getString(R.string.notificationsDateMsg);
eventTime.setText(dateTitle + ": " + d.toLocaleString());
}
if(eventSender != null){
sender = cursor.getString(cursor.getColumnIndex("userFirstname")) + " "
+ cursor.getString(cursor.getColumnIndex("userSurname1")) + " "
+ cursor.getString(cursor.getColumnIndex("userSurname2"));
from = context.getString(R.string.notificationsFromMsg);
eventSender.setText(from + ": " + sender);
}
if(location != null) {
location.setText(cursor.getString(cursor.getColumnIndex("location")));
}
if(summary != null){
summary.setText(cursor.getString(cursor.getColumnIndex("summary")));
}
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater vi = LayoutInflater.from(context);
View v = vi.inflate(R.layout.notifications_list_item, null);
return v;
}
}

View File

@ -44,6 +44,22 @@ public class DataBaseHelper {
db.close();
}
/**
* Gets DB object
* @return DataFramework DB object
*/
public DataFramework getDb() {
return db;
}
/**
* Sets DB object
* @param db DataFramework DB object
*/
public void setDb(DataFramework db) {
this.db = db;
}
/**
* Function to parse from Integer to Boolean
* @param n Integer to be parsed
@ -114,6 +130,16 @@ public class DataBaseHelper {
o = new PairTable<Integer, Integer>(table,
ent.getInt(params.getFirst()),
ent.getInt(params.getSecond()));
} else if(table.equals(Global.DB_TABLE_NOTIFICATIONS)) {
o = new Notification(ent.getInt("id"),
ent.getString("eventType"),
ent.getLong("eventTime"),
ent.getString("userSurname1"),
ent.getString("userSurname2"),
ent.getString("userFirstname"),
ent.getString("location"),
ent.getString("summary"),
ent.getInt("status"));
}
return o;
@ -168,7 +194,7 @@ public class DataBaseHelper {
ent.setValue("eventTime", eventTime);
ent.setValue("userSurname1", n.getUserSurname1());
ent.setValue("userSurname2", n.getUserSurname2());
ent.setValue("userFirstName", n.getUserFirstName());
ent.setValue("userFirstname", n.getUserFirstName());
ent.setValue("location", n.getLocation());
ent.setValue("summary", n.getSummary());
ent.setValue("status", status);
@ -317,13 +343,14 @@ public class DataBaseHelper {
*/
public String getFieldOfLastNotification(String field)
{
String orderby = "eventTime desc";
List<Entity> rows = db.getEntityList(Global.DB_TABLE_NOTIFICATIONS, null, orderby);
String where = null;
String orderby = "eventTime DESC";
List<Entity> rows = db.getEntityList(Global.DB_TABLE_NOTIFICATIONS, where, orderby);
String f = "0";
if(rows.size() > 0)
{
Entity ent = rows.get(rows.size()-1);
Entity ent = rows.get(0);
f = (String) ent.getValue(field);
}
@ -332,17 +359,20 @@ public class DataBaseHelper {
/**
* Clear old notifications
* @param timestamp Newest timestamp to clear
* @param size Max table size
*/
public void clearOldNotifications(long timestamp)
public void clearOldNotifications(int size)
{
String where = "eventTime < " + timestamp;
List<Entity> rows = db.getEntityList(Global.DB_TABLE_NOTIFICATIONS, where);
Iterator<Entity> iter = rows.iterator();
String where = null;
String orderby = "eventTime ASC";
List<Entity> rows = db.getEntityList(Global.DB_TABLE_NOTIFICATIONS, where, orderby);
int numRows = rows.size();
int numDeletions = numRows - size;
while (iter.hasNext()) {
Entity ent = iter.next();
ent.delete();
if(numRows > size)
{
for(int i=0; i<numDeletions; i++)
rows.remove(i);
}
}
}

View File

@ -21,6 +21,7 @@ package es.ugr.swad.swadroid.modules;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
@ -56,7 +57,7 @@ import com.android.dataframework.DataFramework;
* Superclass for encapsulate common behavior of all modules.
* @author Juan Miguel Boyero Corral <juanmi1982@gmail.com>
*/
public abstract class Module extends Activity {
public abstract class Module extends ListActivity {
/**
* SOAP_ACTION param for webservice request.
*/
@ -120,6 +121,11 @@ public abstract class Module extends Activity {
*/
protected abstract void connect();
/**
* Launches action after executing connect() method
*/
protected abstract void postConnect();
/**
* Gets METHOD_NAME parameter.
* @return METHOD_NAME parameter.
@ -233,19 +239,19 @@ public abstract class Module extends Activity {
}
/**
* Launch login activity when required
* Run connection. Launch Login activity when required
*/
private void runLogin()
protected void runConnection()
{
isConnected = connectionAvailable(this);
if (!isConnected) {
Toast.makeText(this, R.string.errorMsgNoConnection, Toast.LENGTH_LONG).show();
} else {
//If not logged and this is not the Login module, launch login
if(!Global.isLogged() && !(this instanceof Login)) {
//If this is not the Login module, launch login check
if(!(this instanceof Login)) {
Intent loginActivity = new Intent(getBaseContext(),
Login.class);
startActivityForResult(loginActivity, Global.LOGIN_REQUEST_CODE);
Login.class);
startActivityForResult(loginActivity, Global.LOGIN_REQUEST_CODE);
}
}
}
@ -273,7 +279,74 @@ public abstract class Module extends Activity {
}
}
runLogin();
Log.d(Global.MODULE_TAG, "onCreate()");
}
/* (non-Javadoc)
* @see android.app.Activity#onPause()
*/
@Override
protected void onPause() {
super.onPause();
if(errorDialog != null) {
errorDialog.dismiss();
}
Log.d(Global.MODULE_TAG, "onPause()");
}
/* (non-Javadoc)
* @see android.app.ListActivity#onDestroy()
*/
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(Global.MODULE_TAG, "onDestroy()");
}
/* (non-Javadoc)
* @see android.app.Activity#onNewIntent(android.content.Intent)
*/
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(Global.MODULE_TAG, "onNewIntent()");
}
/* (non-Javadoc)
* @see android.app.Activity#onRestart()
*/
@Override
protected void onRestart() {
super.onRestart();
Log.d(Global.MODULE_TAG, "onRestart()");
}
/* (non-Javadoc)
* @see android.app.Activity#onResume()
*/
@Override
protected void onResume() {
super.onResume();
Log.d(Global.MODULE_TAG, "onResume()");
}
/* (non-Javadoc)
* @see android.app.Activity#onStart()
*/
@Override
protected void onStart() {
super.onStart();
Log.d(Global.MODULE_TAG, "onStart()");
}
/* (non-Javadoc)
* @see android.app.Activity#onStop()
*/
@Override
protected void onStop() {
super.onStop();
Log.d(Global.MODULE_TAG, "onStop()");
}
/* (non-Javadoc)
@ -299,6 +372,8 @@ public abstract class Module extends Activity {
break;
}
}
Log.d(Global.MODULE_TAG, "onActivityResult()");
}
/**
@ -430,25 +505,14 @@ public abstract class Module extends Activity {
return super.onOptionsItemSelected(item);
}
/* (non-Javadoc)
* @see android.app.Activity#onPause()
*/
@Override
protected void onPause() {
super.onPause();
if(errorDialog != null) {
errorDialog.dismiss();
}
}
/**
/**
* Shows progress dialog when connecting to SWAD
*/
protected class Connect extends AsyncTask<String, Void, Void> {
/**
* Progress dialog.
*/
ProgressDialog Dialog = new ProgressDialog(Module.this);
ProgressDialog dialog = new ProgressDialog(Module.this);
/**
* Exception pointer.
*/
@ -475,9 +539,9 @@ public abstract class Module extends Activity {
@Override
protected void onPreExecute() {
if(showDialog) {
Dialog.setMessage(progressDescription);
Dialog.setTitle(progressTitle);
Dialog.show();
dialog.setMessage(progressDescription);
dialog.setTitle(progressTitle);
dialog.show();
}
}
@ -507,10 +571,12 @@ public abstract class Module extends Activity {
*/
@Override
protected void onPostExecute(Void unused) {
if(showDialog) {
Dialog.dismiss();
if(dialog.isShowing()) {
dialog.dismiss();
}
postConnect();
if(e != null) {
/**
* If an exception has occurred, shows error message according to

View File

@ -28,20 +28,46 @@ import org.xmlpull.v1.XmlPullParserException;
import es.ugr.swad.swadroid.Global;
import es.ugr.swad.swadroid.R;
import es.ugr.swad.swadroid.gui.NotificationsCursorAdapter;
import es.ugr.swad.swadroid.model.User;
import es.ugr.swad.swadroid.model.Notification;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
* Notifications module for get user's notifications
* @author Juan Miguel Boyero Corral <juanmi1982@gmail.com>
*
*/
public class Notifications extends Module {
/**
* Time period to store notifications
* Max size to store notifications
*/
private static final long TIMESTAMP_LIMIT = 2629743; //A month
private static final int SIZE_LIMIT = 25;
/**
* Downloads new notifications when pushed
*/
private Button updateButton;
/**
* Notifications adapter for showing the data
*/
private NotificationsCursorAdapter adapter;
/**
* Cursor for database access
*/
private Cursor dbCursor;
/**
* Cursor selection parameter
*/
private String selection = null;
/**
* Cursor orderby parameter
*/
private String orderby = "eventTime DESC";
/* (non-Javadoc)
* @see es.ugr.swad.swadroid.modules.Module#onCreate(android.os.Bundle)
@ -49,7 +75,20 @@ public class Notifications extends Module {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.notifications);
setContentView(R.layout.notifications);
updateButton = (Button)this.findViewById(R.id.notificationsUpdateButton);
updateButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
runConnection();
}
});
//dbHelper.emptyTable(Global.DB_TABLE_NOTIFICATIONS);
dbCursor = dbHelper.getDb().getCursor(Global.DB_TABLE_NOTIFICATIONS, selection, orderby);
adapter = new NotificationsCursorAdapter(this, dbCursor);
setListAdapter(adapter);
setMETHOD_NAME("getNotifications");
}
@ -65,9 +104,6 @@ public class Notifications extends Module {
Long timestamp = new Long(dbHelper.getFieldOfLastNotification("eventTime"));
timestamp++;
//Clear old notifications to control database size
dbHelper.clearOldNotifications(timestamp - TIMESTAMP_LIMIT);
//Creates webservice request, adds required params and sends request to webservice
createRequest();
addParam("wsKey", User.getWsKey());
@ -96,10 +132,11 @@ public class Notifications extends Module {
}
//Request finalized without errors
//setResult(RESULT_OK);
}
Log.i(Global.NOTIFICATIONS_TAG, "Retrieved " + csSize + " notifications");
//finish();
//Clear old notifications to control database size
dbHelper.clearOldNotifications(SIZE_LIMIT);
}
}
/* (non-Javadoc)
@ -113,4 +150,13 @@ public class Notifications extends Module {
new Connect(true, progressDescription, progressTitle).execute();
}
/* (non-Javadoc)
* @see es.ugr.swad.swadroid.modules.Module#postConnect()
*/
@Override
protected void postConnect() {
//Refresh data on screen
dbCursor = dbHelper.getDb().getCursor(Global.DB_TABLE_NOTIFICATIONS, selection, orderby);
adapter.changeCursor(dbCursor);
}
}