package in.co.praveenkumar.mdroid.service;
import in.co.praveenkumar.R;
import in.co.praveenkumar.mdroid.activity.NotificationActivity;
import in.co.praveenkumar.mdroid.helper.ImageDecoder;
import in.co.praveenkumar.mdroid.model.MoodleCourse;
import in.co.praveenkumar.mdroid.model.MoodleDiscussion;
import in.co.praveenkumar.mdroid.model.MoodleForum;
import in.co.praveenkumar.mdroid.model.MoodleSiteInfo;
import in.co.praveenkumar.mdroid.task.ContactSyncTask;
import in.co.praveenkumar.mdroid.task.CourseContentSyncTask;
import in.co.praveenkumar.mdroid.task.DiscussionSyncTask;
import in.co.praveenkumar.mdroid.task.EventSyncTask;
import in.co.praveenkumar.mdroid.task.ForumSyncTask;
import in.co.praveenkumar.mdroid.task.MessageSyncTask;
import in.co.praveenkumar.mdroid.task.PostSyncTask;
import in.co.praveenkumar.mdroid.task.UserSyncTask;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
public class MDroidService extends Service {
final String DEBUG_TAG = "MDroid Services";
/**
* Service Params and extras
*/
Boolean forceCheck = false;
Boolean notifications = true;
long siteid = -1;
int courseid = -1;
protected int startId;
SharedPreferences settings;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(DEBUG_TAG, "Started service!");
this.startId = startId;
settings = PreferenceManager.getDefaultSharedPreferences(this);
// Check if the service started from NotificationActivity
Bundle extras = intent.getExtras();
if (extras != null) {
forceCheck = extras.getBoolean("forceCheck", false);
notifications = extras.getBoolean("notifications", true);
siteid = extras.getLong("siteid", -1);
courseid = extras.getInt("courseid", -1);
}
// Check for new contents
new ContentCheckerBg().execute("");
return Service.START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* Does the actual content checking. Loops through all the available
* accounts and checks for new contents in each account.
*
* @author praveen
*/
private class ContentCheckerBg extends AsyncTask<String, Integer, Boolean> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
protected Boolean doInBackground(String... credentials) {
int contentCount = 0;
int forumCount = 0;
int discussionCount = 0;
int postCount = 0;
int contactCount = 0;
int participantCount = 0;
int messageCount = 0;
int eventCount = 0;
List<MoodleSiteInfo> mSites = new ArrayList<>();
MoodleSiteInfo site;
// Get list of accounts in app if no siteid param is passed
if (siteid == -1)
mSites = MoodleSiteInfo.listAll(MoodleSiteInfo.class);
else {
site = MoodleSiteInfo.findById(MoodleSiteInfo.class, siteid);
mSites.add(site);
}
if (mSites == null || mSites.isEmpty())
return false;
// Loop through all sites for checking contents
for (int i = 0; i < mSites.size(); i++) {
site = mSites.get(i);
List<MoodleCourse> mCourses = new ArrayList<>();
// Get list of favourites courses if no courseid is passed
if (courseid == -1)
mCourses = MoodleCourse.find(MoodleCourse.class,
"siteid = ? and is_fav_course = ?", String.valueOf(site.getId())
, "1");
else
mCourses = MoodleCourse.find(MoodleCourse.class,
"siteid = ? and courseid = ?", String.valueOf(site.getId()),
String.valueOf(courseid));
// Contents sync
if (settings.getBoolean("notify_coursecontents", true))
contentCount = syncCourseContents(site, mCourses);
// Forums sync
if (settings.getBoolean("notify_forums", true))
forumCount = syncForums(site, mCourses);
// Discussion sync
if (settings.getBoolean("notify_forumtopics", true))
discussionCount = syncDiscussions(site, mCourses);
// Forum posts (replies) sync
if (settings.getBoolean("notify_forumposts", true))
postCount = syncPosts(site, mCourses);
// Events sync
if (settings.getBoolean("notify_events", true))
eventCount = syncEvents(site, mCourses);
// Participants sync
if (settings.getBoolean("notify_participants", false))
participantCount = syncParticipants(site, mCourses);
/**
* The below two sync ops have additional constraints. Don't
* sync if the service is passed with a courseid. That means
* only a course data sync.
*/
// Contact sync
if (settings.getBoolean("notify_contacts", false)
&& courseid == -1)
contactCount = syncContacts(site);
// Message sync.
if (settings.getBoolean("notify_messages", true)
&& courseid == -1)
messageCount = syncMessages(site);
setNotificationWithCounts(site, contentCount, forumCount,
discussionCount, postCount, contactCount,
participantCount, messageCount, eventCount);
}
return true;
}
/**
* Sync course contents in a site for given courses.
*
* @param site
* MoodleSite
* @param mCourses
* MoodleCourses whose contents need to be synced
* @return Notification count
*/
private int syncCourseContents(MoodleSiteInfo site,
List<MoodleCourse> mCourses) {
if (mCourses == null || mCourses.isEmpty())
return 0;
CourseContentSyncTask ccst = new CourseContentSyncTask(
site.getSiteurl(), site.getToken(), site.getId(),
notifications);
for (int i = 0; i < mCourses.size(); i++)
ccst.syncCourseContents(mCourses.get(i).getCourseid());
return ccst.getNotificationcount();
}
/**
* Sync forums in a site for given courses.
*
* @param site
* MoodleSite
* @param mCourses
* MoodleCourses whose forums need to be synced
* @return Notification count
*/
private int syncForums(MoodleSiteInfo site, List<MoodleCourse> mCourses) {
if (mCourses == null || mCourses.isEmpty())
return 0;
ArrayList<String> courseids = new ArrayList<>();
ForumSyncTask fst = new ForumSyncTask(site.getSiteurl(),
site.getToken(), site.getId(), notifications);
for (int i = 0; i < mCourses.size(); i++)
courseids.add(mCourses.get(i).getCourseid() + "");
fst.syncForums(courseids);
return fst.getNotificationcount();
}
/**
* Sync discussions in a site for given courses.
*
* @param site
* MoodleSite
* @param mCourses
* MoodleCourses whose forums need to be synced
* @return Notification count
*/
private int syncDiscussions(MoodleSiteInfo site,
List<MoodleCourse> mCourses) {
if (mCourses == null || mCourses.isEmpty())
return 0;
DiscussionSyncTask dst = new DiscussionSyncTask(site.getSiteurl(),
site.getToken(), site.getId(), notifications);
List<MoodleForum> forums = new ArrayList<>();
// Get list of discussions to sync
for (int i = 0; i < mCourses.size(); i++)
forums.addAll(MoodleForum.find(MoodleForum.class,
"courseid = ? and siteid = ?", mCourses.get(i)
.getCourseid() + "", site.getId() + ""));
// Make an Arraylist of ids for above discussions
ArrayList<String> forumids = new ArrayList<>();
for (int i = 0; i < forums.size(); i++)
forumids.add(forums.get(i).getForumid() + "");
dst.syncDiscussions(forumids);
return dst.getNotificationcount();
}
/**
* Sync posts in a site for given courses - all forum discussions.
*
* @param site
* MoodleSite
* @param mCourses
* MoodleCourses whose forums need to be synced
* @return Notification count
*/
private int syncPosts(MoodleSiteInfo site, List<MoodleCourse> mCourses) {
if (mCourses == null || mCourses.isEmpty())
return 0;
PostSyncTask pst = new PostSyncTask(site.getSiteurl(),
site.getToken(), site.getId(), notifications);
List<MoodleDiscussion> discussions = new ArrayList<>();
// Get list of discussions to sync
for (int i = 0; i < mCourses.size(); i++)
discussions.addAll(MoodleDiscussion.find(
MoodleDiscussion.class, "courseid = ? and siteid = ?",
mCourses.get(i).getCourseid() + "", site.getId() + ""));
// Make an Arraylist of ids for above discussions
ArrayList<Integer> discussionids = new ArrayList<>();
for (int i = 0; i < discussions.size(); i++)
discussionids.add(discussions.get(i).getDiscussionid());
pst.syncPosts(discussionids);
return pst.getNotificationcount();
}
/**
* Sync messages of user
*
* @param site
* MoodleSite
* @return Notification count
*/
private int syncMessages(MoodleSiteInfo site) {
MessageSyncTask mst = new MessageSyncTask(site.getSiteurl(),
site.getToken(), site.getId(), notifications);
mst.syncMessages(site.getUserid());
return mst.getNotificationcount();
}
/**
* Sync events in the site for given courses. Global (not specific to
* any course) events will be included too.
*
* @param site
* MoodleSite
* @param mCourses
* MoodleCourses whose events need to be synced
* @return Notification count
*/
private int syncEvents(MoodleSiteInfo site, List<MoodleCourse> mCourses) {
if (mCourses == null || mCourses.isEmpty())
return 0;
ArrayList<String> courseids = new ArrayList<>();
EventSyncTask est = new EventSyncTask(site.getSiteurl(),
site.getToken(), site.getId(), notifications);
for (int i = 0; i < mCourses.size(); i++)
courseids.add(mCourses.get(i).getCourseid() + "");
est.syncEvents(courseids);
return est.getNotificationcount();
}
/**
* Sync participants in the site for given courses.
*
* @param site
* MoodleSite
* @param mCourses
* MoodleCourses whose events need to be synced
* @return Notification count
*/
private int syncParticipants(MoodleSiteInfo site,
List<MoodleCourse> mCourses) {
if (mCourses == null || mCourses.isEmpty())
return 0;
UserSyncTask ust = new UserSyncTask(site.getSiteurl(),
site.getToken(), site.getId(), notifications);
for (int i = 0; i < mCourses.size(); i++)
ust.syncUsers(mCourses.get(i).getCourseid());
return ust.getNotificationcount();
}
/**
* Sync contacts of user in the given site
*
* @param site
* MoodleSite
* @return Notification count
*/
private int syncContacts(MoodleSiteInfo site) {
ContactSyncTask cst = new ContactSyncTask(site.getSiteurl(),
site.getToken(), site.getId(), notifications);
cst.syncAllContacts();
return cst.getNotificationcount();
}
@Override
protected void onPostExecute(Boolean result) {
Log.d(DEBUG_TAG, "MDroidservice exiting itself.");
// Log the time of checking
SharedPreferences.Editor editor = settings.edit();
editor.putLong("notifications_lastchecked",
System.currentTimeMillis());
editor.commit();
stopSelf(startId);
}
}
/**
* Set a notification for the given counts in the given site
*
* @param site
* MoodleSite
* @param contentCount
* @param forumCount
* @param discussionCount
* @param postCount
* @param contactCount
* @param participantCount
* @param messageCount
* @param eventCount
*/
private void setNotificationWithCounts(MoodleSiteInfo site,
int contentCount, int forumCount, int discussionCount,
int postCount, int contactCount, int participantCount,
int messageCount, int eventCount) {
int total = contentCount + forumCount + discussionCount + postCount
+ contactCount + participantCount + messageCount + eventCount;
int totalForums = postCount + forumCount + discussionCount;
int totalOthers = contactCount + eventCount + participantCount;
final String spaces = " ";
String contentTitle = total + " updates for " + site.getFirstname();
String contentText = "Contents : " + contentCount + spaces
+ " Messages : " + messageCount;
String subText = "Forums : " + totalForums + spaces + " Others : "
+ totalOthers;
String contentInfo = site.getSitename();
Bitmap largeIcon = ImageDecoder.decodeImage(new File(Environment
.getExternalStorageDirectory() + "/MDroid/." + site.getId()));
if (total != 0)
showNotification(contentTitle, contentText, subText, contentInfo,
true, largeIcon, site.getId());
else if (forceCheck)
showNotification("No updated found", "Did you star your courses ?",
"Open courses section to star a course", "", true,
largeIcon, site.getId());
}
/**
*
* @param contentTitle
* @param contentText
* @param subText
* @param contentInfo
* @param autoCancel
* If true, notification is cancels itself on click. Not to be
* confused with Notification persistancy.
* @param largeIcon
* Largeicon bitmap for the notification. Pass null if you want
* to use the app icon instead.
* @param siteid
* Id of the account to which this notification corresponds to.
* Pass -1 if not applicable.
*/
private void showNotification(String contentTitle, String contentText,
String subText, String contentInfo, Boolean autoCancel,
Bitmap largeIcon, long siteid) {
int requestID = (int) System.currentTimeMillis();
// Sent intent and extras as needed
Intent intent = new Intent(this, NotificationActivity.class);
if (siteid != -1)
intent.putExtra("siteid", siteid);
PendingIntent pIntent = PendingIntent.getActivity(this, requestID,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Define sound URI
Uri soundUri = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notification = new NotificationCompat.Builder(
this).setContentTitle(contentTitle).setContentText(contentText)
.setSmallIcon(R.drawable.ic_actionbar_icon).setSubText(subText)
.setContentInfo(contentInfo).setContentIntent(pIntent)
.setAutoCancel(autoCancel).setSound(soundUri);
if (largeIcon == null)
largeIcon = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
notification.setLargeIcon(largeIcon);
NotificationManager notificationManager = getNotificationManager();
notificationManager.notify(requestID, notification.build());
}
// Building notifications
private NotificationManager getNotificationManager() {
return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
}