package net.ggelardi.flucso.serv; import net.ggelardi.flucso.MainActivity; import net.ggelardi.flucso.R; import net.ggelardi.flucso.serv.Commons.PK; import net.ggelardi.flucso.serv.FFAPI.Comment; import net.ggelardi.flucso.serv.FFAPI.Entry; import net.ggelardi.flucso.serv.FFAPI.Feed; import net.ggelardi.flucso.serv.FFAPI.Feed.Realtime; import retrofit.RetrofitError; import android.annotation.TargetApi; import android.app.IntentService; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Build; import android.os.PowerManager; import android.support.v4.app.NotificationCompat; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; public class FFService extends IntentService implements OnSharedPreferenceChangeListener { public static final String SERVICE_ERROR = "net.ggelardi.flucso.FFService.SERVICE_ERROR"; public static final String PROFILE_READY = "net.ggelardi.flucso.FFService.PROFILE_READY"; public static final String DM_BASE_NOTIF = "net.ggelardi.flucso.FFService.DM_BASE_NOTIF"; public static final int NOTIFICATION_ID = 1; private FFSession session; private LocalBroadcastManager notifier; private Boolean terminated = false; private long printv; // profile update interval (ms) private long dmintv; // direct messages update interval (ms) private int dmnotf; // direct messages notification type private Realtime dmlast; public FFService() { super("FFService"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); return START_STICKY; } @Override protected void onHandleIntent(Intent intent) { Log.v("FFService", "onHandleIntent()"); session = FFSession.getInstance(this); notifier = LocalBroadcastManager.getInstance(this); printv = session.getPrefs().getInt(PK.SERV_PROF, 0); dmintv = session.getPrefs().getInt(PK.SERV_MSGS, 0); dmnotf = session.getPrefs().getInt(PK.SERV_NOTF, 0); session.getPrefs().registerOnSharedPreferenceChangeListener(this); int waitTime = 500; try { while (!terminated) { if (isLollipopPSorSO()) waitTime = 60000; else if (!session.hasAccount()) waitTime = 2000; else if (!checkProfile()) terminated = true; else { checkMessages(); checkFeedCache(); waitTime = 50000; } Thread.sleep(waitTime); } } catch (Exception e) { terminated = true; notifyError(e); } finally { stopSelf(); } } @Override public void onDestroy() { Log.v("FFService", "onDestroy()"); session.getPrefs().unregisterOnSharedPreferenceChangeListener(this); super.onDestroy(); } private void notifyError(Throwable error) { String text; try { text = error instanceof RetrofitError ? Commons.retrofitErrorText((RetrofitError) error) : error.getMessage(); } catch (Exception err) { text = "Unknown error"; } notifier.sendBroadcast(new Intent().setAction(SERVICE_ERROR).putExtra("message", text)); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private boolean isLollipopPSorSO() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return false; PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); return pm.isPowerSaveMode() || !pm.isInteractive(); } private boolean checkProfile() { if (session.hasProfile() && session.getProfile().getAge() <= printv * 60000) return true; Log.v("FFService", "checkProfile()"); session.setProfile(FFAPI.client_profile(session).get_profile_sync("me")); session.setNavigation(FFAPI.client_profile(session).get_navigation_sync()); notifier.sendBroadcast(new Intent(PROFILE_READY)); return true; } private void checkMessages() { if (dmnotf == 0) return; long chk = dmlast != null ? dmlast.timestamp : session.getPrefs().getLong(PK.SERV_MSGS_TIME, 0); if (chk > 0 && System.currentTimeMillis() - chk <= dmintv * 60000) return; Log.v("FFService", "checkMessages()"); String cursor = dmlast != null ? dmlast.cursor : session.getPrefs().getString(PK.SERV_MSGS_CURS, ""); Feed data = FFAPI.client_msgs(session).get_feed_updates("filter/direct", 50, cursor, 0, 1); dmlast = data.realtime; // save the token SharedPreferences.Editor editor = session.getPrefs().edit(); editor.putString(PK.SERV_MSGS_CURS, dmlast.cursor); editor.putLong(PK.SERV_MSGS_TIME, System.currentTimeMillis()); editor.commit(); // check for updates boolean news = false; boolean upds = false; for (Entry e : data.entries) { if (news) break; if (e.from.isMe()) { if (!upds && replied(e)) upds = true; } else if (dmnotf == 2 || (e.to.length == 1 && e.to[0].isMe())) { if (e.created) news = true; else if (!upds && (e.updated || replied(e))) upds = true; } } if (news || upds) { PendingIntent rpi = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class).setAction(DM_BASE_NOTIF), PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder ncb = new NotificationCompat.Builder(this).setSmallIcon( R.drawable.ic_launcher).setContentTitle(getResources().getString(R.string.app_name)).setContentText( getResources().getString(news ? R.string.notif_dm_new : R.string.notif_dm_upd)).setContentIntent(rpi); NotificationManager nmg = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); nmg.notify(NOTIFICATION_ID, ncb.build()); } } private void checkFeedCache() { if (!Commons.isOnWIFI(this) || (session.cachedFeed != null && session.cachedFeed.getAge() < 10*60*1000)) return; Log.v("FFService", "checkFeedCache()"); String fid = session.cachedFeed != null ? session.cachedFeed.id : session.getPrefs().getString(PK.STARTUP, "home"); String cur = session.cachedFeed != null && session.cachedFeed.realtime != null ? session.cachedFeed.realtime.cursor : ""; if (cur == "") { session.cachedFeed = FFAPI.client_feed(session).get_feed_normal(fid, 0, 20); session.cachedFeed.realtime = FFAPI.client_feed(session).get_feed_updates(fid, 20, "", 0, 1).realtime; } else { session.cachedFeed.update(FFAPI.client_feed(session).get_feed_updates(fid, session.cachedFeed.entries.size(), session.cachedFeed.realtime.cursor, 0, 1), true); } } private static boolean replied(Entry e) { for (Comment c: e.comments) if ((c.created || c.updated) && !c.from.isMe()) return true; return false; } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(PK.SERV_PROF)) { printv = sharedPreferences.getInt(PK.SERV_PROF, 0); Log.v("FFService", "printv: " + Long.toString(printv)); } else if (key.equals(PK.SERV_NOTF)) { dmnotf = session.getPrefs().getInt(PK.SERV_NOTF, 0); Log.v("FFService", "dmnotf: " + Integer.toString(dmnotf)); } else if (key.equals(PK.SERV_MSGS)) { dmintv = sharedPreferences.getInt(PK.SERV_MSGS, 0); Log.v("FFService", "dmintv: " + Long.toString(dmintv)); } } }