Commit 9cb2be1d authored by Sajal Narang's avatar Sajal Narang

Implement event reminder notifications

parent 31795ae7
......@@ -110,6 +110,20 @@
</intent-filter>
</activity>
<service
android:name=".notifications.NotificationIntentService"
android:enabled="true"
android:exported="false" />
<receiver android:name=".notifications.NotificationEventReceiver" />
<receiver android:name=".notifications.NotificationServiceStarterReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.TIME_SET" />
</intent-filter>
</receiver>
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
......
......@@ -6,6 +6,9 @@ public class Constants {
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 3;
public static final int RESULT_LOAD_IMAGE = 11;
public static final String NOTIFICATIONS_RESPONSE_JSON = "notifications_json";
public static final String EVENT_ID = "event_id";
public static final String EVENT_LATITUDE = "event_latitude";
public static final String EVENT_LONGITUDE = "event_longitude";
public static final String EVENT_JSON = "event_json";
public static final String EVENT_LIST_JSON = "event_list_json";
public static final String USER_ID = "user_id";
......
......@@ -26,10 +26,12 @@ import com.squareup.picasso.Picasso;
import app.insti.api.UnsafeOkHttpClient;
import app.insti.data.Body;
import app.insti.data.Event;
import app.insti.data.User;
import app.insti.fragment.BackHandledFragment;
import app.insti.fragment.BodyFragment;
import app.insti.fragment.CalendarFragment;
import app.insti.fragment.EventFragment;
import app.insti.fragment.ExploreFragment;
import app.insti.fragment.FeedFragment;
import app.insti.fragment.MapFragment;
......@@ -42,10 +44,12 @@ import app.insti.fragment.ProfileFragment;
import app.insti.fragment.QuickLinksFragment;
import app.insti.fragment.SettingsFragment;
import app.insti.fragment.TrainingBlogFragment;
import app.insti.notifications.NotificationEventReceiver;
import static app.insti.Constants.MY_PERMISSIONS_REQUEST_ACCESS_LOCATION;
import static app.insti.Constants.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE;
import static app.insti.Constants.RESULT_LOAD_IMAGE;
import static app.insti.notifications.NotificationIntentService.ACTION_OPEN_EVENT;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, BackHandledFragment.BackHandlerInterface {
......@@ -80,8 +84,20 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
feedFragment = new FeedFragment();
updateFragment(feedFragment);
Intent appLinkIntent = getIntent();
handleIntent(appLinkIntent);
Intent intent = getIntent();
if (intent != null) {
if (intent.getAction() != null && intent.getAction().equals(ACTION_OPEN_EVENT)) {
EventFragment eventFragment = new EventFragment();
Bundle bundle = new Bundle();
bundle.putString(Constants.EVENT_JSON, intent.getStringExtra(Constants.EVENT_JSON));
eventFragment.setArguments(bundle);
updateFragment(eventFragment);
} else {
handleIntent(intent);
}
}
NotificationEventReceiver.setupAlarm(getApplicationContext());
}
private void handleIntent(Intent appLinkIntent) {
......
......@@ -36,11 +36,16 @@ public class SessionManager {
editor = pref.edit();
editor.putBoolean(Constants.IS_LOGGED_IN, true);
editor.putString(Constants.GCM_ID, gcmId);
editor.putString(Constants.USER_ID, currentUser.getUserID());
editor.putString(Constants.CURRENT_USER, currentUser.toString());
editor.putString(Constants.SESSION_ID, sessionID);
editor.commit();
}
public String getUserID() {
return pref.getString(Constants.USER_ID, "");
}
public String getSessionID() {
return pref.getString(Constants.SESSION_ID, "");
}
......
......@@ -40,12 +40,12 @@ public interface RetrofitInterface {
@GET("events")
Call<NewsFeedResponse> getNewsFeed(@Header("Cookie") String sessionId);
@GET("locations")
Call<List<Venue>> getAllVenues();
@GET("events")
Call<NewsFeedResponse> getEventsBetweenDates(@Header("Cookie") String sessionId, @Query("start") String start, @Query("end") String end);
@GET("locations")
Call<List<Venue>> getAllVenues();
@GET("users/{uuid}")
Call<User> getUser(@Header("Cookie") String sessionId, @Path("uuid") String uuid);
......
......@@ -5,6 +5,7 @@ import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;
import android.support.annotation.NonNull;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import java.sql.Timestamp;
......@@ -210,4 +211,9 @@ public class Event {
public void setEventUserUes(int eventUserUes) {
this.eventUserUes = eventUserUes;
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}
package com.iitb.moodindigo.mi2016;
package app.insti.notifications;
import android.app.AlarmManager;
import android.app.PendingIntent;
......@@ -15,14 +15,13 @@ NotificationEventReceiver extends WakefulBroadcastReceiver {
private static final String ACTION_START_NOTIFICATION_SERVICE = "ACTION_START_NOTIFICATION_SERVICE";
private static final String ACTION_DELETE_NOTIFICATION = "ACTION_DELETE_NOTIFICATION";
private static final int NOTIFICATIONS_INTERVAL_IN_HOURS = 1;
public static void setupAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent = getStartPendingIntent(context);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
getTriggerAt(new Date()),
1000 * 60 * 15, //Change this to 1000 * 60 for testing => runs every minute
1000 * 60 * 10, //Change this to 1000 * 60 for testing => runs every minute
alarmIntent);
}
......
package com.iitb.moodindigo.mi2016;
package app.insti.notifications;
import android.app.IntentService;
import android.app.Notification;
......@@ -6,29 +6,36 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.iitb.moodindigo.mi2016.ServerConnection.GsonModels;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import app.insti.Constants;
import app.insti.MainActivity;
import app.insti.R;
import app.insti.SessionManager;
import app.insti.api.RetrofitInterface;
import app.insti.api.ServiceGenerator;
import app.insti.data.Event;
import app.insti.data.User;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class NotificationIntentService extends IntentService {
private static final String ACTION_START = "ACTION_START";
private static final String ACTION_DELETE = "ACTION_DELETE";
private static final String ACTION_NAVIGATE = "ACTION_NAVIGATE";
private static final String ACTION_NOT_GOING = "ACTION_NOT_GOING";
public static final String ACTION_OPEN_EVENT = "ACTION_OPEN_EVENT";
private static int NOTIFICATION_ID = 1;
private SharedPreferences.Editor goingSharedPreferencesEditor;
private NotificationManager manager;
public NotificationIntentService() {
......@@ -63,17 +70,33 @@ public class NotificationIntentService extends IntentService {
if (ACTION_DELETE.equals(action)) {
processDeleteNotification(intent);
}
if ("ACTION_NOT_GOING".equals(action)) {
if (Cache.getGoingEventsList() != null) {
GsonModels.Event event = (new Gson().fromJson(intent.getStringExtra("EVENT_JSON"), GsonModels.Event.class));
Cache.removeFromGoingList(event);
goingSharedPreferencesEditor = this.getSharedPreferences("GOING", Context.MODE_PRIVATE).edit();
String goingEventsListJson = (new Gson()).toJson(Cache.getGoingEventsList());
goingSharedPreferencesEditor.putString("GOING_LIST", goingEventsListJson);
goingSharedPreferencesEditor.apply();
if (ACTION_NOT_GOING.equals(action)) {
String eventID = intent.getStringExtra(Constants.EVENT_ID);
String sessionID = intent.getStringExtra(Constants.SESSION_ID);
RetrofitInterface retrofitInterface = ServiceGenerator.createService(RetrofitInterface.class);
retrofitInterface.updateUserEventStatus("sessionid=" + sessionID, eventID, Constants.STATUS_NOT_GOING).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
}
});
manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(intent.getIntExtra("NOTIFICATION_ID", -1));
}
if (ACTION_NAVIGATE.equals(action)) {
manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(intent.getIntExtra("NOTIFICATION_ID", -1));
double latitude = intent.getDoubleExtra(Constants.EVENT_LATITUDE, 0);
double longitude = intent.getDoubleExtra(Constants.EVENT_LONGITUDE, 0);
Uri gmmIntentUri = Uri.parse("google.navigation:q=" + latitude + "," + longitude + "&mode=w");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
startActivity(mapIntent);
}
} finally {
WakefulBroadcastReceiver.completeWakefulIntent(intent);
......@@ -85,62 +108,75 @@ public class NotificationIntentService extends IntentService {
}
private void processStartNotification() {
// Do something. For example, fetch fresh data from backend to create a rich notification?
SharedPreferences goingPreferences = getApplicationContext().getSharedPreferences("GOING", Context.MODE_PRIVATE);
String goingList = goingPreferences.getString("GOING_LIST", null);
Type type = new TypeToken<List<GsonModels.Event>>() {
}.getType();
List<GsonModels.Event> goingListGson = (new Gson()).fromJson(goingList, type);
if (goingListGson == null) {
;
} else {
for (int i = 0; i < goingListGson.size(); i++) {
GsonModels.Event event = goingListGson.get(i);
long timediff = getDateDiff(new Date(), event.getDate(), TimeUnit.MINUTES);
SessionManager sessionManager = new SessionManager(this);
String userID = sessionManager.getUserID();
final String sessionID = sessionManager.getSessionID();
RetrofitInterface retrofitInterface = ServiceGenerator.createService(RetrofitInterface.class);
retrofitInterface.getUser("sessionid=" + sessionID, userID).enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.isSuccessful()) {
User user = response.body();
List<Event> goingEventList = user.getUserGoingEvents();
if (goingEventList != null) {
for (Event event : goingEventList) {
long timediff = getDateDiff(new Date(), event.getEventStartTime(), TimeUnit.MINUTES);
if (timediff <= 30 && timediff > 0) { // Change this to 30*10000 for testing
NOTIFICATION_ID = (int) Long.parseLong(event.get_id().substring(6, 11), 16);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(event.getTitle())
NOTIFICATION_ID = event.getEventID().hashCode();
final NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setContentTitle(event.getEventName())
.setAutoCancel(true)
.setColor(getResources().getColor(R.color.yellow))
.setContentText("Event is about to start in " + getDateDiff(new Date(), event.getDate(), TimeUnit.MINUTES) + ((getDateDiff(new Date(), event.getDate(), TimeUnit.MINUTES) == 1) ? " minute." : " minutes."))
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_event_white_24dp))
.setSmallIcon(R.drawable.ic_event_white_24dp);
.setColor(getResources().getColor(R.color.colorAccent))
.setContentText("Event is about to start in " + getDateDiff(new Date(), event.getEventStartTime(), TimeUnit.MINUTES) + ((getDateDiff(new Date(), event.getEventStartTime(), TimeUnit.MINUTES) == 1) ? " minute." : " minutes."))
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.lotus_white))
.setSmallIcon(R.drawable.lotus_white);
Intent intent = new Intent(this, MainActivity.class);
intent.setAction("OPEN_EVENT");
String eventJson = (new Gson()).toJson(event);
intent.putExtra("EVENT_JSON", eventJson);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.setAction(ACTION_OPEN_EVENT);
intent.putExtra(Constants.SESSION_ID, sessionID);
intent.putExtra(Constants.EVENT_JSON, event.toString());
PendingIntent pendingIntent = PendingIntent.getActivity(this,
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
NOTIFICATION_ID,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
builder.setDeleteIntent(NotificationEventReceiver.getDeleteIntent(this));
builder.setDeleteIntent(NotificationEventReceiver.getDeleteIntent(getApplicationContext()));
Intent navigateIntent = new Intent(this, MainActivity.class);
Intent navigateIntent = new Intent(getApplicationContext(), NotificationIntentService.class);
navigateIntent.setAction(ACTION_NAVIGATE);
navigateIntent.putExtra("EVENT_JSON", eventJson);
navigateIntent.putExtra(Constants.EVENT_ID, event.getEventID());
navigateIntent.putExtra(Constants.EVENT_LATITUDE, event.getEventVenues().get(0).getVenueLatitude());
navigateIntent.putExtra(Constants.EVENT_LONGITUDE, event.getEventVenues().get(0).getVenueLongitude());
navigateIntent.putExtra("NOTIFICATION_ID", NOTIFICATION_ID);
PendingIntent navigatePendingIntent = PendingIntent.getActivity(this, 0, navigateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.ic_navigation_white_24dp, "Navigate", navigatePendingIntent);
PendingIntent navigatePendingIntent = PendingIntent.getService(getApplicationContext(), 0, navigateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.baseline_navigation_white_24, "Navigate", navigatePendingIntent);
Intent notGoingIntent = new Intent(this, NotificationIntentService.class);
Intent notGoingIntent = new Intent(getApplicationContext(), NotificationIntentService.class);
notGoingIntent.setAction(ACTION_NOT_GOING);
notGoingIntent.putExtra("EVENT_JSON", eventJson);
notGoingIntent.putExtra(Constants.SESSION_ID, sessionID);
notGoingIntent.putExtra(Constants.EVENT_ID, event.getEventID());
notGoingIntent.putExtra("NOTIFICATION_ID", NOTIFICATION_ID);
PendingIntent notGoingPendingIntent = PendingIntent.getService(this, 0, notGoingIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.ic_close_white_24dp, "Not Going", notGoingPendingIntent);
PendingIntent notGoingPendingIntent = PendingIntent.getService(getApplicationContext(), 0, notGoingIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.baseline_close_white_24, "Not Going", notGoingPendingIntent);
manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = builder.build();
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;
manager.notify(NOTIFICATION_ID, notification);
}
}
}
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
}
});
}
}
\ No newline at end of file
package com.iitb.moodindigo.mi2016;
package app.insti.notifications;
import android.content.BroadcastReceiver;
import android.content.Context;
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment