AlarmReceiver.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. package com.ivalentin.margolariak;
  2. import android.app.Activity;
  3. import android.app.AlarmManager;
  4. import android.app.NotificationManager;
  5. import android.app.PendingIntent;
  6. import android.content.ComponentName;
  7. import android.content.Context;
  8. import android.content.Intent;
  9. import android.content.SharedPreferences;
  10. import android.content.pm.PackageManager;
  11. import android.database.Cursor;
  12. import android.database.sqlite.SQLiteDatabase;
  13. import android.graphics.BitmapFactory;
  14. import android.media.RingtoneManager;
  15. import android.support.v4.app.NotificationCompat;
  16. import android.support.v4.app.TaskStackBuilder;
  17. import android.content.BroadcastReceiver;
  18. import android.util.Log;
  19. /**
  20. * Manages alarms to perform actions in the background, such as sync and receive notifications.
  21. *
  22. * @see BroadcastReceiver
  23. *
  24. * @author Iñigo Valentin
  25. *
  26. */
  27. public class AlarmReceiver extends BroadcastReceiver {
  28. /**
  29. * Actions to be performed when an alarm is received.
  30. * Performs a full sync, and gets the pending notifications.
  31. *
  32. * @param context Context of the activity or application
  33. * @param intent Receiver intent
  34. *
  35. * @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
  36. */
  37. @Override
  38. @SuppressWarnings("deprecation")
  39. public void onReceive(Context context, Intent intent) {
  40. //Open the preferences to be available several times later.
  41. SharedPreferences preferences = context.getSharedPreferences(GM.PREFERENCES.PREFERNCES, Context.MODE_PRIVATE);
  42. FetchURL fu;
  43. //Check if the user wants to receive notifications
  44. if (preferences.getBoolean(GM.PREFERENCES.KEY.NOTIFICATIONS, GM.PREFERENCES.DEFAULT.NOTIFICATIONS)){
  45. //Get the file
  46. try{
  47. fu = new FetchURL();
  48. fu.Run(GM.API.SERVER + GM.API.NOTIFICATION.PATH);
  49. Log.d("NOTIFICATIONS", "Fetched notifications");
  50. //Parse info
  51. String o = fu.getOutput().toString();
  52. //Open database
  53. SQLiteDatabase db = context.openOrCreateDatabase(GM.DB.NAME, Activity.MODE_PRIVATE, null);
  54. if (db.isReadOnly()){
  55. Log.e("NOTIFICATIONS", "Database is locked and in read only mode.");
  56. return;
  57. }
  58. Cursor cursor;
  59. //Variables for parsing
  60. String not, title_es, title_en, title_eu, text_es, text_en, text_eu, dtime, action;
  61. int id, gm, duration;
  62. //Variables for showinfg the notification
  63. String lang = GM.getLang();
  64. String title, text;
  65. int counter = 0;
  66. while (counter < 10 && o.contains("\"}")){
  67. //Get the notifications
  68. not = o.substring(o.indexOf("{\"") + 2, o.indexOf("\"}"));
  69. //Extract data
  70. id = Integer.valueOf(not.substring(not.indexOf("\"id\":") + 6, not.indexOf("\",")));
  71. title_es = not.substring(not.indexOf("\"title_es\":") + 12, not.indexOf("\"", not.indexOf("\"title_es\":") + 13));
  72. title_en = not.substring(not.indexOf("\"title_en\":") + 12, not.indexOf("\"", not.indexOf("\"title_en\":") + 13));
  73. title_eu = not.substring(not.indexOf("\"title_eu\":") + 12, not.indexOf("\"", not.indexOf("\"title_eu\":") + 13));
  74. text_es = not.substring(not.indexOf("\"text_es\":") + 11, not.indexOf("\"", not.indexOf("\"text_es\":") + 12));
  75. text_en = not.substring(not.indexOf("\"text_en\":") + 11, not.indexOf("\"", not.indexOf("\"text_en\":") + 12));
  76. text_eu = not.substring(not.indexOf("\"text_eu\":") + 11, not.indexOf("\"", not.indexOf("\"text_eu\":") + 12));
  77. dtime = not.substring(not.indexOf("\"dtime\":") + 9, not.indexOf("\"", not.indexOf("\"dtime\":") + 10));
  78. action = not.substring(not.indexOf("\"action\":") + 10, not.indexOf("\"", not.indexOf("\"action\":") + 11));
  79. gm = Integer.valueOf(not.substring(not.indexOf("\"gm\":") + 6, not.indexOf("\"", not.indexOf("\"gm\":") + 7)));
  80. duration = Integer.valueOf(not.substring(not.indexOf("\"duration\":") + 12, not.indexOf("\"", not.indexOf("\"duration\":") + 13)));
  81. //Compare with the database
  82. cursor = db.rawQuery("SELECT id FROM notification WHERE id = " + id + ";", null);
  83. if (cursor.getCount() == 0) {
  84. db.execSQL("INSERT INTO notification (id, title_es, title_en, title_eu, text_es, text_en, text_eu, dtime, internal, duration, action) VALUES " +
  85. "(" + id + ", \"" + title_es + "\", \"" + title_en + "\", \"" + title_eu + "\", \"" + text_es + "\", \"" + text_en + "\", \"" + text_eu + "\", \"" + dtime + "\", " + gm + ", " + duration + ", \"" + action + "\");");
  86. //TODO: Show notification;
  87. switch (lang) {
  88. case "en":
  89. title = title_en;
  90. text = text_en;
  91. break;
  92. case "eu":
  93. title = title_eu;
  94. text = text_eu;
  95. break;
  96. default:
  97. title = title_es;
  98. text = text_es;
  99. break;
  100. }
  101. //Get the notification manager ready
  102. NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
  103. //Variables to create intents for each notification
  104. Intent resultIntent;
  105. TaskStackBuilder stackBuilder;
  106. //Send the notification.
  107. NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
  108. .setSmallIcon(R.drawable.ic_notification)
  109. .setContentTitle(title)
  110. .setAutoCancel(true)
  111. .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher))
  112. .setVibrate((new long[]{400, 400, 400}))
  113. .setColor(context.getResources().getColor(R.color.background_notification))
  114. .setSubText(context.getString(R.string.app_name))
  115. .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
  116. .setContentText(text);
  117. // Creates an intent for an Activity to be launched from the notification.
  118. resultIntent = new Intent(context, MainActivity.class);
  119. resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
  120. //Set extras depending on type.
  121. resultIntent.putExtra(GM.EXTRA.TEXT, text);
  122. resultIntent.putExtra(GM.EXTRA.TITLE, title);
  123. resultIntent.putExtra(GM.EXTRA.ACTION, action);
  124. //Add the intent to the notification.
  125. stackBuilder = TaskStackBuilder.create(context);
  126. stackBuilder.addParentStack(MainActivity.class);
  127. // Adds the Intent that starts the Activity to the top of the stack.
  128. stackBuilder.addNextIntent(resultIntent);
  129. PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
  130. mBuilder.setContentIntent(resultPendingIntent);
  131. //Actually send the notification.
  132. mNotificationManager.notify(id, mBuilder.build());
  133. }
  134. cursor.close();
  135. o = o.substring(o.indexOf("\"}") + 3);
  136. counter ++;
  137. }
  138. db.close();
  139. //Parse info
  140. /*String o = fu.getOutput().toString();
  141. while (o.contains("<notification>")){
  142. //Get non-language-dependant fields
  143. String notification = o.substring(o.indexOf("<notification>") + 14, o.indexOf("</notification>"));
  144. String id = notification.substring(notification.indexOf("<id>") + 4, notification.indexOf("</id>"));
  145. String action = notification.substring(notification.indexOf("<action>") + 8, notification.indexOf("</action>"));
  146. //Is the notification seen already?
  147. //TODO: Create a db table for this
  148. //Get data from database
  149. SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(GM.DB.NAME).getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
  150. final Cursor cursor;
  151. cursor = db.rawQuery("SELECT id, seen FROM notification WHERE id = " + id + ";", null);
  152. if (cursor.getCount() == 0){
  153. }
  154. else {
  155. if (cursor.getInt(1) == 0) {
  156. String lang = GM.getLang();
  157. String title = notification.substring(notification.indexOf("<title_" + lang + ">") + 10, notification.indexOf("</title_" + lang + ">"));
  158. String text = notification.substring(notification.indexOf("<text_" + lang + ">") + 9, notification.indexOf("</text_" + lang + ">"));
  159. //Get the notification manager ready
  160. NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
  161. //Variables to create intents for each notification
  162. Intent resultIntent;
  163. TaskStackBuilder stackBuilder;
  164. //Send the notification.
  165. NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
  166. .setSmallIcon(R.drawable.ic_notification)
  167. .setContentTitle(title)
  168. .setAutoCancel(true)
  169. .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher))
  170. .setVibrate((new long[]{400, 400, 400}))
  171. .setColor(context.getResources().getColor(R.color.background_notification))
  172. .setSubText(context.getString(R.string.app_name))
  173. .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
  174. .setContentText(text);
  175. // Creates an intent for an Activity to be launched from the notification.
  176. resultIntent = new Intent(context, MainActivity.class);
  177. resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
  178. //Set extras depending on type.
  179. resultIntent.putExtra(GM.EXTRA.TEXT, text);
  180. resultIntent.putExtra(GM.EXTRA.TITLE, title);
  181. resultIntent.putExtra(GM.EXTRA.ACTION, action);
  182. //Add the intent to the notification.
  183. stackBuilder = TaskStackBuilder.create(context);
  184. stackBuilder.addParentStack(MainActivity.class);
  185. // Adds the Intent that starts the Activity to the top of the stack.
  186. stackBuilder.addNextIntent(resultIntent);
  187. PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
  188. mBuilder.setContentIntent(resultPendingIntent);
  189. //Actually send the notification.
  190. mNotificationManager.notify(Integer.parseInt(id), mBuilder.build());
  191. //Mark as notified
  192. db.execSQL("UPDATE notification SET seen = 1 WHERE id = " + id);
  193. }
  194. }
  195. o = o.substring(o.indexOf("</notification>") + 15);
  196. }*/
  197. }
  198. catch(NumberFormatException ex) {
  199. Log.e("NOTIFICATION", "Error parsing remote file: " + ex.toString());
  200. }
  201. catch (Exception ex){
  202. Log.e("NOTIFICATION", "Error fetching notifications: " + ex.toString());
  203. }
  204. }
  205. //Perform a background sync
  206. new Sync(context).execute();
  207. }
  208. /**
  209. * Sets a repeating alarm.
  210. * When the alarm fires, the app broadcasts an Intent to this WakefulBroadcastReceiver.
  211. * @param context The context of the app
  212. */
  213. public void setAlarm(Context context) {
  214. //Only do this if the preference is enabled
  215. SharedPreferences prefs = context.getSharedPreferences(GM.PREFERENCES.PREFERNCES, Context.MODE_PRIVATE);
  216. if (prefs.getBoolean(GM.PREFERENCES.KEY.SYNC, GM.PREFERENCES.DEFAULT.SYNC)) {
  217. AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
  218. Intent intent = new Intent(context, AlarmReceiver.class);
  219. PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
  220. //Set the alarm cycle.
  221. //TODO: Set the most appropiate interval
  222. alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, GM.PERIOD_SYNC.FESTIVALS, GM.PERIOD_SYNC.FESTIVALS, alarmIntent);
  223. // Enable SampleBootReceiver to automatically restart the alarm when the device is rebooted.
  224. ComponentName receiver = new ComponentName(context, BootReceiver.class);
  225. PackageManager pm = context.getPackageManager();
  226. pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
  227. }
  228. }
  229. }