Skip to content
This repository was archived by the owner on May 31, 2025. It is now read-only.

Commit 4e9497e

Browse files
committed
File import feature completed
1 parent 93983f0 commit 4e9497e

27 files changed

+466
-177
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,19 @@
196196

197197
</intent-filter>
198198

199+
<intent-filter>
200+
<action android:name="android.intent.action.VIEW" />
201+
202+
<category android:name="android.intent.category.OPENABLE" />
203+
<category android:name="android.intent.category.BROWSABLE" />
204+
<category android:name="android.intent.category.DEFAULT" />
205+
206+
<data
207+
android:mimeType="application/octet-stream"
208+
android:scheme="content" />
209+
210+
</intent-filter>
211+
199212
</activity>
200213

201214
<!-- Receivers -->

app/src/main/java/com/noah/timely/alarms/AlarmReSchedulerService.java

Lines changed: 84 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,38 @@
1212
import static com.noah.timely.timetable.DaysFragment.ARG_POSITION;
1313

1414
import android.app.AlarmManager;
15+
import android.app.NotificationManager;
1516
import android.app.PendingIntent;
1617
import android.app.Service;
18+
import android.content.ContentResolver;
1719
import android.content.Context;
1820
import android.content.Intent;
21+
import android.graphics.Bitmap;
22+
import android.graphics.BitmapFactory;
23+
import android.media.RingtoneManager;
1924
import android.net.Uri;
2025
import android.os.Build;
2126
import android.os.IBinder;
2227

2328
import androidx.annotation.NonNull;
2429
import androidx.annotation.Nullable;
30+
import androidx.core.app.NotificationCompat;
31+
import androidx.core.content.ContextCompat;
32+
import androidx.preference.PreferenceManager;
2533

2634
import com.noah.timely.R;
2735
import com.noah.timely.assignment.AssignmentModel;
2836
import com.noah.timely.assignment.Reminder;
2937
import com.noah.timely.assignment.SubmissionNotifier;
3038
import com.noah.timely.core.DataModel;
3139
import com.noah.timely.core.SchoolDatabase;
40+
import com.noah.timely.main.App;
3241
import com.noah.timely.scheduled.AddScheduledDialog;
3342
import com.noah.timely.scheduled.ScheduledTaskNotifier;
3443
import com.noah.timely.timetable.DaysFragment;
3544
import com.noah.timely.timetable.TimetableModel;
3645
import com.noah.timely.timetable.TimetableNotifier;
46+
import com.noah.timely.util.Constants;
3747
import com.noah.timely.util.ThreadUtils;
3848

3949
import java.util.Calendar;
@@ -45,15 +55,18 @@
4555
* Service that would re-schedule all TimeLY alarms
4656
*/
4757
public class AlarmReSchedulerService extends Service {
58+
private static final int NOTIFICATION_ID = 234543; // a very random number that came out of nowhere
4859

4960
@Override
5061
public int onStartCommand(Intent intent, int flags, int startId) {
62+
Context context = getApplicationContext();
63+
if (intent.getAction().equals(Constants.ACTION.SHOW_NOTIFICATION)) {
64+
showActivityNofication(context);
65+
}
66+
5167
// make re-scheduler return immediately to avoid blocking main thread
5268
ThreadUtils.runBackgroundTask(() -> {
53-
54-
Context context = getApplicationContext();
5569
SchoolDatabase database = new SchoolDatabase(context);
56-
5770
// Reset the alarm here.
5871
List<DataModel> activeAlarms = database.getActiveAlarms();
5972
if (!activeAlarms.isEmpty()) {
@@ -89,6 +102,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
89102
List<DataModel> timetables1 = database.getTimeTableData(SchoolDatabase.SCHEDULED_TIMETABLE);
90103
if (!timetables1.isEmpty()) {
91104
// re-schedule alarms; get alarm data from app's database
105+
92106
for (DataModel rawData : timetables1) {
93107
TimetableModel timetable = (TimetableModel) rawData;
94108
registerPendingScheduledTimetables(context, timetable);
@@ -105,11 +119,49 @@ public int onStartCommand(Intent intent, int flags, int startId) {
105119
}
106120
}
107121

122+
// cancel on-going notification
123+
cancelNotification(context);
108124
}); // end re-schedule task
109125

126+
110127
return START_STICKY;
111128
}
112129

130+
private void cancelNotification(Context context) {
131+
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
132+
manager.cancel(NOTIFICATION_ID);
133+
}
134+
135+
private void showActivityNofication(Context context) {
136+
Uri SYSTEM_DEFAULT = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
137+
Uri APP_DEFAULT = new Uri.Builder()
138+
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
139+
.authority(context.getPackageName())
140+
.path(String.valueOf(R.raw.arpeggio1))
141+
.build();
142+
143+
String type = PreferenceManager.getDefaultSharedPreferences(context)
144+
.getString("Uri Type", "TimeLY's Default");
145+
146+
final Uri DEFAULT_URI = type.equals("TimeLY's Default") || SYSTEM_DEFAULT == null ? APP_DEFAULT
147+
: SYSTEM_DEFAULT;
148+
149+
Bitmap icon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.app_icon);
150+
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
151+
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, App.GENERAL_CHANNEL_ID);
152+
153+
builder.setContentTitle(getString(R.string.app_name) + " is in the background")
154+
.setContentText(getString(R.string.app_name) + " is scheduling new notifications")
155+
.setChannelId(App.GENERAL_CHANNEL_ID)
156+
.setSound(DEFAULT_URI)
157+
.setSmallIcon(R.drawable.ic_baseline_info_24)
158+
.setColor(ContextCompat.getColor(context, R.color.colorPrimary))
159+
.setLargeIcon(icon)
160+
.setOngoing(true);
161+
162+
manager.notify(NOTIFICATION_ID, builder.build());
163+
}
164+
113165
@Nullable
114166
@Override
115167
public IBinder onBind(Intent intent) {
@@ -144,7 +196,7 @@ private void registerPendingScheduledTimetables(Context context, TimetableModel
144196
.addCategory("com.noah.timely.scheduled")
145197
.setAction("com.noah.timely.scheduled.addAction")
146198
.setDataAndType(Uri.parse("content://com.noah.timely.scheduled.add." + triggerTime),
147-
"com.noah.timely.scheduled.dataType");
199+
"com.noah.timely.scheduled.dataType");
148200

149201
PendingIntent pi = PendingIntent.getBroadcast(context, 1156, scheduleIntent, 0);
150202

@@ -183,14 +235,14 @@ private void registerPendingTimetables(Context context, TimetableModel timetable
183235

184236
Intent timetableIntent = new Intent(context, TimetableNotifier.class);
185237
timetableIntent.putExtra(DaysFragment.ARG_TIME, time)
186-
.putExtra(ARG_CLASS, course)
187-
.putExtra(ARG_DAY, timetable.getCalendarDay())
188-
.putExtra(ARG_POSITION, position)
189-
.putExtra(ARG_PAGE_POSITION, position)
190-
.addCategory("com.noah.timely.timetable")
191-
.setAction("com.noah.timely.timetable.addAction")
192-
.setDataAndType(Uri.parse("content://com.noah.timely.add." + timeInMillis),
193-
"com.noah.timely.dataType");
238+
.putExtra(ARG_CLASS, course)
239+
.putExtra(ARG_DAY, timetable.getCalendarDay())
240+
.putExtra(ARG_POSITION, position)
241+
.putExtra(ARG_PAGE_POSITION, position)
242+
.addCategory("com.noah.timely.timetable")
243+
.setAction("com.noah.timely.timetable.addAction")
244+
.setDataAndType(Uri.parse("content://com.noah.timely.add." + timeInMillis),
245+
"com.noah.timely.dataType");
194246

195247
PendingIntent pi = PendingIntent.getBroadcast(context, 555, timetableIntent, PendingIntent.FLAG_UPDATE_CURRENT);
196248

@@ -231,26 +283,26 @@ private void registerPendingAssignments(Context context, AssignmentModel assignm
231283
String ln = truncateLecturerName(context, assignment.getLecturerName());
232284
Intent notifyIntentCurrent = new Intent(context, SubmissionNotifier.class);
233285
notifyIntentCurrent.putExtra(LECTURER_NAME, ln)
234-
.putExtra(TITLE, assignment.getTitle())
235-
.putExtra(POSITION, assignment.getPosition())
236-
.addCategory(context.getPackageName() + ".category")
237-
.setAction(context.getPackageName() + ".update")
238-
.setDataAndType(Uri.parse("content://" + context.getPackageName()),
239-
assignment.toString());
286+
.putExtra(TITLE, assignment.getTitle())
287+
.putExtra(POSITION, assignment.getPosition())
288+
.addCategory(context.getPackageName() + ".category")
289+
.setAction(context.getPackageName() + ".update")
290+
.setDataAndType(Uri.parse("content://" + context.getPackageName()),
291+
assignment.toString());
240292

241293
Intent notifyIntentPrevious = new Intent(context, Reminder.class);
242294
notifyIntentPrevious.putExtra(LECTURER_NAME, ln)
243-
.putExtra(TITLE, assignment.getTitle())
244-
.putExtra(NEXT_ALARM, CURRENT)
245-
.addCategory(context.getPackageName() + ".category")
246-
.setAction(context.getPackageName() + ".update")
247-
.setDataAndType(Uri.parse("content://" + context.getPackageName()),
248-
assignment.toString());
295+
.putExtra(TITLE, assignment.getTitle())
296+
.putExtra(NEXT_ALARM, CURRENT)
297+
.addCategory(context.getPackageName() + ".category")
298+
.setAction(context.getPackageName() + ".update")
299+
.setDataAndType(Uri.parse("content://" + context.getPackageName()),
300+
assignment.toString());
249301

250302
PendingIntent assignmentPiPrevious = PendingIntent.getBroadcast(context, 147, notifyIntentPrevious,
251-
PendingIntent.FLAG_UPDATE_CURRENT);
303+
PendingIntent.FLAG_UPDATE_CURRENT);
252304
PendingIntent assignmentPiCurrent = PendingIntent.getBroadcast(context, 141, notifyIntentCurrent,
253-
PendingIntent.FLAG_UPDATE_CURRENT);
305+
PendingIntent.FLAG_UPDATE_CURRENT);
254306
// Exact alarms not used here, so that android can perform its normal operation
255307
// on devices
256308
// >= 4.4 (KITKAT) to prevent unnecessary battery drain by alarms.
@@ -272,8 +324,8 @@ private void registerPendingAssignments(Context context, AssignmentModel assignm
272324
private String truncateLecturerName(Context context, String fullName) {
273325
String[] nameTokens = fullName.split(" ");
274326

275-
String[] titles = {"Barr", "Barrister", "Doc", "Doctor", "Dr", "Engineer", "Engr",
276-
"Mr", "Mister", "Mrs", "Ms", "Prof", "Professor"};
327+
String[] titles = { "Barr", "Barrister", "Doc", "Doctor", "Dr", "Engineer", "Engr",
328+
"Mr", "Mister", "Mrs", "Ms", "Prof", "Professor" };
277329

278330
StringBuilder nameBuilder = new StringBuilder();
279331
String shortenedName = "";
@@ -374,11 +426,11 @@ private void rescheduleNonRepeatingAlarm(@NonNull Context context, @NonNull Alar
374426
alarmReceiverIntent.addCategory("com.noah.timely.alarm.category");
375427
alarmReceiverIntent.setAction("com.noah.timely.alarm.cancel");
376428
alarmReceiverIntent.setDataAndType(Uri.parse("content://com.noah.timely/Alarms/alarm" + alarmMillis),
377-
"com.noah.timely.alarm.dataType");
429+
"com.noah.timely.alarm.dataType");
378430

379431
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
380432
PendingIntent alarmPI = PendingIntent.getBroadcast(context, 11789, alarmReceiverIntent,
381-
PendingIntent.FLAG_CANCEL_CURRENT);
433+
PendingIntent.FLAG_CANCEL_CURRENT);
382434
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
383435
// alarm has to be triggered even when device is in idle or doze mode.
384436
// This alarm is very important
@@ -422,11 +474,11 @@ private void rescheduleRepeatingPendingAlarm(@NonNull Context context, @NonNull
422474
alarmReceiverIntent.addCategory("com.noah.timely.alarm.category");
423475
alarmReceiverIntent.setAction("com.noah.timely.alarm.cancel");
424476
alarmReceiverIntent.setDataAndType(Uri.parse("content://com.noah.timely/Alarms/alarm" + alarmMillis),
425-
"com.noah.timely.alarm.dataType");
477+
"com.noah.timely.alarm.dataType");
426478

427479
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
428480
PendingIntent alarmPI = PendingIntent.getBroadcast(context, 11789, alarmReceiverIntent,
429-
PendingIntent.FLAG_UPDATE_CURRENT);
481+
PendingIntent.FLAG_UPDATE_CURRENT);
430482

431483
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
432484
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

app/src/main/java/com/noah/timely/alarms/AlarmReceiver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
import java.util.Locale;
2222

2323
public class AlarmReceiver extends BroadcastReceiver {
24+
public static String ALARM_POS = "com.noah.timely.position";
2425
static final int NOTIFICATION_ID = 11789;
2526
static final String ID = "Notification ID";
2627
static final String REPEAT_DAYS = "Alarm Repeat Days";
27-
public static String ALARM_POS = "com.noah.timely.position";
2828

2929
@Override
3030
public void onReceive(Context context, Intent intent) {

app/src/main/java/com/noah/timely/assignment/AddAssignmentActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ private void saveOrUpdateAssignment() {
295295

296296
data = new AssignmentModel(pos, ln, tt, description, date, cc, date, attachedPDF, attachedImage, false);
297297

298-
if (database.isAssignmentPresent(data) && !tryScheduleNotifiers(yy, mm, dd, tt, ln, data, pos)) {
298+
if (!database.isAssignmentAbsent(data) && !tryScheduleNotifiers(yy, mm, dd, tt, ln, data, pos)) {
299299
ErrorDialog.Builder errorBuilder = new ErrorDialog.Builder();
300300
errorBuilder.setDialogMessage("Invalid assignment")
301301
.setShowSuggestions(true)

app/src/main/java/com/noah/timely/assignment/AssignmentModel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public void setDescription(String description) {
110110
this.description = description;
111111
}
112112

113-
String getDate() {
113+
public String getDate() {
114114
return date;
115115
}
116116

app/src/main/java/com/noah/timely/core/SchoolDatabase.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ private void createAlarmTable(SQLiteDatabase db) {
193193

194194
db.execSQL(createAlarmDB_stmt);
195195
}
196-
197196
// CREATE ASSIGNMENT DATA TABLE
198197
private void createAssignmentTable(SQLiteDatabase db) {
199198
String createAssignmentDB_stmt
@@ -337,7 +336,7 @@ public boolean addAssignmentData(AssignmentModel assignment) {
337336
*
338337
* @return true if a duplicate assignment was found
339338
*/
340-
public boolean isAssignmentPresent(AssignmentModel model) {
339+
public boolean isAssignmentAbsent(AssignmentModel model) {
341340
String findAssignmentStmt = "SELECT * FROM " + ASSIGNMENT_TABLE
342341
+ " WHERE " + COLUMN_ASSIGNMENT_TITLE + " = '" + sanitizeEntry(model.getTitle())
343342
+ "' AND " + COLUMN_SUBMISSION_DATE + " = '" + model.getSubmissionDate()
@@ -347,9 +346,9 @@ public boolean isAssignmentPresent(AssignmentModel model) {
347346
SQLiteDatabase db = getReadableDatabase();
348347

349348
Cursor findCursor = db.rawQuery(findAssignmentStmt, null);
349+
boolean isAbsent = findCursor.getCount() == 0;
350350
findCursor.close();
351-
352-
return findCursor.getColumnCount() > 0;
351+
return isAbsent;
353352
}
354353

355354
private String sanitizeEntry(String data) {

app/src/main/java/com/noah/timely/courses/CourseModel.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.noah.timely.courses;
22

33
import com.noah.timely.core.DataModel;
4+
import com.noah.timely.core.SchoolDatabase;
45

56
@SuppressWarnings("unused")
67
public class CourseModel extends DataModel {
@@ -71,4 +72,8 @@ public String toString() {
7172
", chronologicalOrder=" + chronologicalOrder +
7273
'}';
7374
}
75+
76+
public int getSemesterIndex() {
77+
return semester.equals(SchoolDatabase.FIRST_SEMESTER) ? 0 : 1;
78+
}
7479
}

app/src/main/java/com/noah/timely/exam/ExamModel.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ public int getDayIndex() {
118118
}
119119
}
120120

121+
public int getWeekIndex() {
122+
return Integer.parseInt(week.substring(week.indexOf('_') + 1)) - 1;
123+
}
124+
121125
public int getStartAsInt() {
122126
String[] ss = start.split(":");
123127
return Integer.parseInt(ss[0] + ss[1]);

0 commit comments

Comments
 (0)