package com.xorcode.andtweet;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetProvider;
import android.content.BroadcastReceiver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteConstraintException;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import com.xorcode.andtweet.TwitterUser.CredentialsVerified;
import com.xorcode.andtweet.appwidget.AndTweetAppWidgetProvider;
import com.xorcode.andtweet.data.AndTweetDatabase;
import com.xorcode.andtweet.data.AndTweetPreferences;
import com.xorcode.andtweet.data.FriendTimeline;
import com.xorcode.andtweet.data.AndTweetDatabase.Tweets;
import com.xorcode.andtweet.net.ConnectionException;
import com.xorcode.andtweet.util.ForegroundCheckTask;
import com.xorcode.andtweet.util.I18n;
private static final String TAG = AndTweetService.class.getSimpleName();
public static final String APPTAG = "AndTweet";
private static final String packageName = AndTweetService.class.getPackage().getName();
private static final String ACTIONPREFIX = packageName + ".action.";
public static final String ACTION_APPWIDGET_UPDATE = ACTIONPREFIX + "APPWIDGET_UPDATE";
public static final String ACTION_ALARM = ACTIONPREFIX + "ALARM";
public static final String ACTION_SERVICE_STOPPED = ACTIONPREFIX + "SERVICE_STOPPED";
public static final String ACTION_GO = ACTIONPREFIX + "GO";
public static final String EXTRA_MSGTYPE = packageName + ".MSGTYPE";
public static final String EXTRA_TWEETID = packageName + ".TWEETID";
public static final String EXTRA_STATUS = packageName + ".STATUS";
public static final String EXTRA_USERNAME = packageName + ".USERNAME";
public static final String EXTRA_PREFERENCE_KEY = packageName + ".PREFERENCE_KEY";
public static final String EXTRA_PREFERENCE_VALUE = packageName + ".PREFERENCE_VALUE";
public static final String EXTRA_INREPLYTOID = packageName + ".INREPLYTOID";
public static final String EXTRA_NUMTWEETS = packageName + ".NUMTWEETS";
public static final String EXTRA_TIMELINE_TYPE = packageName + ".TIMELINE_TYPE";
public enum CommandEnum {
UNKNOWN("unknown"),
EMPTY("empty"),
AUTOMATIC_UPDATE("automatic-update"),
FETCH_TIMELINE("fetch-timeline"),
FETCH_MESSAGES("fetch-messages"),
START_ALARM("start-alarm"),
STOP_ALARM("stop-alarm"),
RESTART_ALARM("restart-alarm"),
CREATE_FAVORITE("create-favorite"), DESTROY_FAVORITE("destroy-favorite"),
UPDATE_STATUS("update-status"), DESTROY_STATUS("destroy-status"),
RATE_LIMIT_STATUS("rate-limit-status"),
NOTIFY_QUEUE("notify-queue"),
NOTIFY_DIRECT_MESSAGE("notify-direct-message"), NOTIFY_TIMELINE("notify-timeline"), NOTIFY_REPLIES(
"notify-replies"),
NOTIFY_CLEAR("notify-clear"),
PREFERENCES_CHANGED("preferences-changed"),
PUT_BOOLEAN_PREFERENCE("put-boolean-preference"), PUT_LONG_PREFERENCE("put-long-preference"), PUT_STRING_PREFERENCE(
"put-string-preference");
private String code;
code = codeIn;
}
return code;
}
public static CommandEnum
load(String strCode) {
for (CommandEnum serviceCommand : CommandEnum.values()) {
if (serviceCommand.code.equals(strCode)) {
return serviceCommand;
}
}
return UNKNOWN;
}
}
public CommandEnum command;
public long itemId = 0;
public Bundle bundle = new Bundle();
private int hashcode = 0;
public int retriesLeft = 0;
command = commandIn;
}
public CommandData(CommandEnum commandIn,
long itemIdIn) {
command = commandIn;
itemId = itemIdIn;
}
public CommandData(String preferenceKey,
boolean value, String username) {
command = CommandEnum.PUT_BOOLEAN_PREFERENCE;
bundle.putString(EXTRA_PREFERENCE_KEY, preferenceKey);
bundle.putBoolean(EXTRA_PREFERENCE_VALUE, value);
if (username != null) {
bundle.putString(EXTRA_USERNAME, username);
}
}
public CommandData(String preferenceKey,
long value, String username) {
command = CommandEnum.PUT_LONG_PREFERENCE;
bundle.putString(EXTRA_PREFERENCE_KEY, preferenceKey);
bundle.putLong(EXTRA_PREFERENCE_VALUE, value);
if (username != null) {
bundle.putString(EXTRA_USERNAME, username);
}
}
public CommandData(String preferenceKey, String value, String username) {
command = CommandEnum.PUT_STRING_PREFERENCE;
bundle.putString(EXTRA_PREFERENCE_KEY, preferenceKey);
bundle.putString(EXTRA_PREFERENCE_VALUE, value);
if (username != null) {
bundle.putString(EXTRA_USERNAME, username);
}
}
bundle = intent.getExtras();
String strCommand = "(no command)";
if (bundle != null) {
strCommand = bundle.getString(EXTRA_MSGTYPE);
itemId = bundle.getLong(EXTRA_TWEETID);
}
command = CommandEnum.load(strCommand);
}
@Override
if (hashcode == 0) {
String text = Long.toString(command.ordinal());
if (itemId != 0) {
text += Long.toString(itemId);
}
switch (command) {
case UPDATE_STATUS:
text += bundle.getString(EXTRA_STATUS);
break;
case PUT_BOOLEAN_PREFERENCE:
text += bundle.getString(EXTRA_PREFERENCE_KEY)
+ bundle.getString(EXTRA_USERNAME)
+ bundle.getBoolean(EXTRA_PREFERENCE_VALUE);
break;
case PUT_LONG_PREFERENCE:
text += bundle.getString(EXTRA_PREFERENCE_KEY)
+ bundle.getString(EXTRA_USERNAME)
+ bundle.getLong(EXTRA_PREFERENCE_VALUE);
break;
case PUT_STRING_PREFERENCE:
text += bundle.getString(EXTRA_PREFERENCE_KEY)
+ bundle.getString(EXTRA_USERNAME)
+ bundle.getString(EXTRA_PREFERENCE_VALUE);
break;
}
hashcode = text.hashCode();
}
return hashcode;
}
@Override
return "CommandData [" + "command=" + command.save()
+ (itemId == 0 ? "" : "; id=" + itemId) + ", hashCode=" + hashCode() + "]";
}
return toIntent(null);
}
public Intent
toIntent(Intent intent_in) {
Intent intent = intent_in;
if (intent == null) {
intent = new Intent(AndTweetService.ACTION_GO);
}
if (bundle == null) {
bundle = new Bundle();
}
bundle.putString(AndTweetService.EXTRA_MSGTYPE, command.save());
if (itemId != 0) {
bundle.putLong(AndTweetService.EXTRA_TWEETID, itemId);
}
intent.putExtras(bundle);
return intent;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}
return (this.hashCode() == ((CommandData) obj).hashCode());
}
}
final RemoteCallbackList<IAndTweetServiceCallback> mCallbacks = new RemoteCallbackList<IAndTweetServiceCallback>();
private static final int MILLISECONDS = 1000;
public static boolean updateWidgetsOnEveryUpdate = true;
private boolean mNotificationsEnabled;
private boolean mNotificationsVibrate;
private BlockingQueue<CommandData> mCommands = new ArrayBlockingQueue<CommandData>(100, true);
private BlockingQueue<CommandData> mRetryQueue = new ArrayBlockingQueue<CommandData>(100, true);
private Set<CommandExecutor> mExecutors = new HashSet<CommandExecutor>();
private volatile int mBroadcastListenerCount = 0;
private volatile PowerManager.WakeLock mWakeLock = null;
protected long preferencesChangeTime = 0;
protected long preferencesExamineTime = 0;
private SharedPreferences
getSp() {
return AndTweetPreferences.getDefaultSharedPreferences();
}
return AndTweetPreferences.getSharedPreferences(TAG, MODE_PRIVATE);
}
@Override
AndTweetPreferences.initialize(this, this);
preferencesChangeTime = AndTweetPreferences.getDefaultSharedPreferences().getLong(PreferencesActivity.KEY_PREFERENCES_CHANGE_TIME, 0);
preferencesExamineTime = getServiceSp().getLong(PreferencesActivity.KEY_PREFERENCES_EXAMINE_TIME, 0);
d(TAG, "Service created, preferencesChangeTime=" + preferencesChangeTime + ", examined=" + preferencesExamineTime);
registerReceiver(intentReceiver, new IntentFilter(ACTION_GO));
}
private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context arg0, Intent intent) {
v(TAG, "onReceive " + intent.toString());
receiveCommand(intent);
}
};
@Override
sendBroadcast(new Intent(ACTION_SERVICE_STOPPED));
mCallbacks.kill();
unregisterReceiver(intentReceiver);
int count = notifyOfQueue(true);
AndTweetPreferences.forget();
d(TAG, "Service destroyed" + (count>0 ? ", " + count + " msg in the Queue" : ""));
}
@Override
public IBinder
onBind(Intent intent) {
if (IAndTweetService.class.getName().equals(intent.getAction())) {
return mBinder;
}
return null;
}
@Override
public void onStart(Intent intent,
int startId) {
super.onStart(intent, startId);
d(TAG, "onStart(): startid: " + startId);
receiveCommand(intent);
}
long preferencesChangeTimeNew = AndTweetPreferences.getDefaultSharedPreferences().getLong(
PreferencesActivity.KEY_PREFERENCES_CHANGE_TIME, 0);
if (preferencesChangeTime != preferencesChangeTimeNew
|| preferencesExamineTime < preferencesChangeTimeNew) {
examinePreferences();
}
if (mCommands.isEmpty()) {
while (!mRetryQueue.isEmpty()) {
CommandData commandData = mRetryQueue.poll();
if (!mCommands.contains(commandData)) {
if (!mCommands.offer(commandData)) {
Log.e(TAG, "mCommands is full?");
}
}
}
}
if (intent != null) {
CommandData commandData = new CommandData(intent);
if (commandData.command == CommandEnum.UNKNOWN) {
} else if (processCommandImmediately(commandData)) {
} else if (mCommands.contains(commandData)) {
d(TAG, "Duplicated " + commandData);
} else {
d(TAG, "Adding to the queue " + commandData);
if (!mCommands.offer(commandData)) {
Log.e(TAG, "mCommands is full?");
}
}
}
startEndStuff(true, null, null);
}
boolean processed = false;
boolean ok = true;
boolean skipped = false;
boolean putPreferences = false;
processed = (commandData == null);
if (!processed) {
processed = true;
switch (commandData.command) {
case START_ALARM:
ok = scheduleRepeatingAlarm();
break;
case STOP_ALARM:
ok = cancelRepeatingAlarm();
break;
case RESTART_ALARM:
ok = cancelRepeatingAlarm();
ok = scheduleRepeatingAlarm();
break;
case UNKNOWN:
case EMPTY:
break;
case PREFERENCES_CHANGED:
examinePreferences();
break;
case PUT_BOOLEAN_PREFERENCE:
if (!putPreferences) {
skipped = true;
break;
}
String key = commandData.bundle.getString(EXTRA_PREFERENCE_KEY);
boolean boolValue = commandData.bundle.getBoolean(EXTRA_PREFERENCE_VALUE);
String username = commandData.bundle.getString(EXTRA_USERNAME);
v(TAG, "Put boolean Preference '" + key + "'=" + boolValue
+ ((username != null) ? " user='" + username + "'" : " global"));
SharedPreferences sp = null;
if (username != null) {
sp = TwitterUser.getTwitterUser(username).getSharedPreferences();
} else {
sp = getSp();
}
synchronized (sp) {
sp.edit().putBoolean(key, boolValue).commit();
}
break;
case PUT_LONG_PREFERENCE:
if (!putPreferences) {
skipped = true;
break;
}
key = commandData.bundle.getString(EXTRA_PREFERENCE_KEY);
long longValue = commandData.bundle.getLong(EXTRA_PREFERENCE_VALUE);
username = commandData.bundle.getString(EXTRA_USERNAME);
v(TAG, "Put long Preference '" + key + "'=" + longValue
+ ((username != null) ? " user='" + username + "'" : " global"));
if (username != null) {
sp = TwitterUser.getTwitterUser(username).getSharedPreferences();
} else {
sp = getSp();
}
synchronized (sp) {
sp.edit().putLong(key, longValue).commit();
}
break;
case PUT_STRING_PREFERENCE:
if (!putPreferences) {
skipped = true;
break;
}
key = commandData.bundle.getString(EXTRA_PREFERENCE_KEY);
String stringValue = commandData.bundle.getString(EXTRA_PREFERENCE_VALUE);
username = commandData.bundle.getString(EXTRA_USERNAME);
v(TAG, "Put String Preference '" + key + "'=" + stringValue
+ ((username != null) ? " user='" + username + "'" : " global"));
if (username != null) {
sp = TwitterUser.getTwitterUser(username).getSharedPreferences();
} else {
sp = getSp();
}
synchronized (sp) {
sp.edit().putString(key, stringValue).commit();
}
break;
default:
processed = false;
break;
}
if (processed) {
d(TAG, (skipped ? "Skipped" : (ok ? "Succeeded" : "Failed")) + " " + commandData);
}
}
return processed;
}
boolean ok = true;
long preferencesChangeTimeNew = AndTweetPreferences.getDefaultSharedPreferences().getLong(PreferencesActivity.KEY_PREFERENCES_CHANGE_TIME, 0);
long preferencesExamineTimeNew = java.lang.System.currentTimeMillis();
if (preferencesChangeTimeNew > preferencesExamineTime) {
d(TAG, "Examine at=" + preferencesExamineTimeNew + " Preferences changed at=" + preferencesChangeTimeNew);
} else if (preferencesChangeTimeNew > preferencesChangeTime) {
d(TAG, "Preferences changed at=" + preferencesChangeTimeNew);
} else if (preferencesChangeTimeNew == preferencesChangeTime) {
d(TAG, "Preferences didn't change, still at=" + preferencesChangeTimeNew);
} else {
Log.e(TAG, "Preferences change time error, time=" + preferencesChangeTimeNew);
}
preferencesChangeTime = preferencesChangeTimeNew;
preferencesExamineTime = preferencesExamineTimeNew;
getServiceSp().edit().putLong(PreferencesActivity.KEY_PREFERENCES_EXAMINE_TIME, preferencesExamineTime).commit();
AndTweetPreferences.forget();
AndTweetPreferences.initialize(this, this);
ok = cancelRepeatingAlarm();
SharedPreferences sp = AndTweetPreferences.getDefaultSharedPreferences();
if (sp.contains("automatic_updates") && sp.getBoolean("automatic_updates", false)) {
ok = scheduleRepeatingAlarm();
}
return ok;
}
private synchronized void startEndStuff(
boolean start, CommandExecutor executorIn, String logMsg) {
if (start) {
SharedPreferences sp = getSp();
mNotificationsEnabled = sp.getBoolean("notifications_enabled", false);
mNotificationsVibrate = sp.getBoolean("vibration", false);
sp = null;
if (!mCommands.isEmpty()) {
if (isOnline()) {
if (mExecutors.isEmpty()) {
CommandExecutor executor;
if (executorIn != null) {
executor = executorIn;
} else {
executor = new CommandExecutor();
}
if (logMsg != null) {
d(TAG, logMsg);
}
mExecutors.add(executor);
if (mExecutors.size() == 1) {
mWakeLock = getWakeLock();
mBroadcastListenerCount = mCallbacks.beginBroadcast();
d(TAG, "No other threads running so starting new broadcast for "
+ mBroadcastListenerCount + " listeners");
}
executor.execute();
}
} else {
notifyOfQueue(false);
}
}
} else {
if (logMsg != null) {
d(TAG, logMsg);
}
mExecutors.remove(executorIn);
if (mExecutors.size() == 0) {
d(TAG, "Ending last thread so also ending broadcast.");
mWakeLock.release();
mCallbacks.finishBroadcast();
if (notifyOfQueue(false) == 0) {
if (! ForegroundCheckTask.isAppOnForeground(AndTweetPreferences.getContext())) {
d(TAG, "App is on Background so stop this Service");
stopSelf();
}
}
}
}
}
int count = mRetryQueue.size() + mCommands.size();
NotificationManager nM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (count == 0 || clearNotification) {
nM.cancel(CommandEnum.NOTIFY_QUEUE.ordinal());
} else if (mNotificationsEnabled) {
if (mRetryQueue.size() > 0) {
d(TAG, mRetryQueue.size() + " commands in Retry Queue.");
}
if (mCommands.size() > 0) {
d(TAG, mCommands.size() + " commands in Main Queue.");
}
Notification notification = new Notification(R.drawable.notification_icon,
(String) getText(R.string.notification_title), System.currentTimeMillis());
int messageTitle;
String aMessage = "";
aMessage = I18n.formatQuantityMessage(getApplicationContext(),
R.string.notification_queue_format, count, R.array.notification_queue_patterns,
R.array.notification_queue_formats);
messageTitle = R.string.notification_title_queue;
notification.tickerText = aMessage;
PendingIntent pi = PendingIntent.getBroadcast(this, 0, new CommandData(
CommandEnum.EMPTY).toIntent(), 0);
notification.setLatestEventInfo(this, getText(messageTitle), aMessage, pi);
nM.notify(CommandEnum.NOTIFY_QUEUE.ordinal(), notification);
}
return count;
}
@Override
}
@Override
JSONObject jso = null;
int what = 0;
String message = "";
d(TAG, "CommandExecutor, " + mCommands.size() + " commands to process");
do {
boolean ok = false;
CommandData commandData = mCommands.poll();
if (commandData == null) {
break;
}
commandData.retriesLeft -= 1;
boolean retry = false;
d(TAG, "Executing " + commandData);
switch (commandData.command) {
case AUTOMATIC_UPDATE:
d(TAG, "Getting tweets, replies and messages");
ok = loadTimeline(true, true);
break;
case FETCH_TIMELINE:
d(TAG, "Getting tweets and replies");
ok = loadTimeline(true, false);
break;
case FETCH_MESSAGES:
d(TAG, "Getting messages");
ok = loadTimeline(false, true);
break;
case CREATE_FAVORITE:
case DESTROY_FAVORITE:
ok = createOrDestroyFavorite(
commandData.command == CommandEnum.CREATE_FAVORITE,
commandData.itemId);
retry = !ok;
break;
case UPDATE_STATUS:
String status = commandData.bundle.getString(EXTRA_STATUS).trim();
long inReplyToId = commandData.bundle.getLong(EXTRA_INREPLYTOID);
ok = updateStatus(status, inReplyToId);
retry = !ok;
break;
case DESTROY_STATUS:
ok = destroyStatus(commandData.itemId);
retry = !ok;
break;
case RATE_LIMIT_STATUS:
ok = rateLimitStatus();
break;
default:
Log.e(TAG, "Unexpected command here " + commandData);
}
d(TAG, (ok ? "Succeeded" : "Failed") + " " + commandData);
if (retry) {
if (commandData.retriesLeft < 0) {
commandData.retriesLeft = 9;
}
if (commandData.retriesLeft > 0) {
if (!mRetryQueue.contains(commandData)) {
if (!mRetryQueue.offer(commandData)) {
Log.e(TAG, "mRetryQueue is full?");
}
}
} else {
Log.e(TAG, "Couldn't execute " + commandData);
}
}
if (!ok && !isOnline()) {
break;
}
} while (true);
try {
jso = new JSONObject();
jso.put("what", what);
jso.put("message", message);
} catch (JSONException e) {
e.printStackTrace();
}
return jso;
}
String message = null;
if (jso != null) {
try {
int what = jso.getInt("what");
message = jso.getString("message");
switch (what) {
case 0:
break;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
startEndStuff(false, this, message);
}
boolean ok = false;
JSONObject result = new JSONObject();
try {
if (create) {
result = TwitterUser.getTwitterUser().getConnection().createFavorite(statusId);
} else {
result = TwitterUser.getTwitterUser().getConnection().destroyFavorite(statusId);
}
ok = (result != null);
} catch (ConnectionException e) {
Log.e(TAG,
(create ? "create" : "destroy") + "Favorite Connection Exception: "
+ e.toString());
}
if (ok) {
try {
Uri uri = ContentUris.withAppendedId(Tweets.CONTENT_URI, result.getLong("id"));
Cursor c = getContentResolver().query(uri, new String[] {
Tweets._ID, Tweets.AUTHOR_ID, Tweets.TWEET_TYPE
}, null, null, null);
try {
c.moveToFirst();
FriendTimeline fl = new FriendTimeline(
AndTweetService.this.getApplicationContext(), c.getInt(c
.getColumnIndex(Tweets.TWEET_TYPE)));
fl.insertFromJSONObject(result, true);
} catch (Exception e) {
Log.e(TAG, "e: " + e.toString());
} finally {
if (c != null && !c.isClosed())
c.close();
}
} catch (JSONException e) {
Log.e(TAG,
"Error marking as " + (create ? "" : "not ") + "favorite: "
+ e.toString());
}
}
d(TAG, (create ? "Creating" : "Destroying") + " favorite "
+ (ok ? "succeded" : "failed") + ", id=" + statusId);
return ok;
}
boolean ok = false;
JSONObject result = new JSONObject();
try {
result = TwitterUser.getTwitterUser().getConnection().destroyStatus(statusId);
ok = (result != null);
} catch (ConnectionException e) {
Log.e(TAG, "destroyStatus Connection Exception: " + e.toString());
}
if (ok) {
try {
FriendTimeline fl = new FriendTimeline(
AndTweetService.this.getApplicationContext(),
AndTweetDatabase.Tweets.TIMELINE_TYPE_FRIENDS);
fl.destroyStatus(statusId);
} catch (Exception e) {
Log.e(TAG, "Error destroying status locally: " + e.toString());
}
}
d(TAG, "Destroying status " + (ok ? "succeded" : "failed") + ", id=" + statusId);
return ok;
}
private boolean updateStatus(String status,
long inReplyToId) {
boolean ok = false;
JSONObject result = new JSONObject();
try {
result = TwitterUser.getTwitterUser().getConnection()
.updateStatus(status.trim(), inReplyToId);
ok = (result != null);
} catch (ConnectionException e) {
Log.e(TAG, "updateStatus Exception: " + e.toString());
}
if (ok) {
FriendTimeline fl = new FriendTimeline(
AndTweetService.this.getApplicationContext(),
AndTweetDatabase.Tweets.TIMELINE_TYPE_FRIENDS);
try {
fl.insertFromJSONObject(result, true);
} catch (JSONException e) {
Log.e(TAG, "updateStatus JSONException: " + e.toString());
}
}
return ok;
}
public boolean (boolean loadTweets, boolean loadMessages) {
boolean ok = false;
int aNewTweets = 0;
int aReplyCount = 0;
int aNewMessages = 0;
if (TwitterUser.getTwitterUser().getCredentialsVerified() == CredentialsVerified.SUCCEEDED) {
String descr = "(starting)";
try {
FriendTimeline fl = null;
ok = true;
if (ok && loadTweets) {
descr = "loading Mentions";
fl = new FriendTimeline(AndTweetService.this.getApplicationContext(),
AndTweetDatabase.Tweets.TIMELINE_TYPE_MENTIONS);
ok = fl.loadTimeline();
aReplyCount = fl.replyCount();
if (ok) {
descr = "loading Friends";
fl = new FriendTimeline(AndTweetService.this.getApplicationContext(),
AndTweetDatabase.Tweets.TIMELINE_TYPE_FRIENDS);
ok = fl.loadTimeline();
aNewTweets = fl.newCount();
aReplyCount += fl.replyCount();
}
fl.pruneOldRecords();
}
if (ok && loadMessages) {
descr = "loading Messages";
fl = new FriendTimeline(AndTweetService.this.getApplicationContext(),
AndTweetDatabase.Tweets.TIMELINE_TYPE_MESSAGES);
ok = fl.loadTimeline();
aNewMessages = fl.newCount();
fl.pruneOldRecords();
}
} catch (ConnectionException e) {
Log.e(TAG, descr + ", Connection Exception: " + e.toString());
} catch (SQLiteConstraintException e) {
Log.e(TAG, descr + ", SQLite Exception: " + e.toString());
}
}
if (ok) {
notifyOfUpdatedTimeline(aNewTweets, aReplyCount, aNewMessages);
}
String message = (ok ? "Succeeded" : "Failed") + " getting ";
if (loadTweets) {
message += aNewTweets + " tweets, " + aReplyCount + " replies";
}
if (loadMessages) {
if (loadTweets) {
message += " and ";
}
message += aNewMessages + " messages";
}
AndTweetService.d(TAG, message);
return ok;
}
private void (int tweetsChanged, int repliesChanged,
int messagesChanged) {
int N = mBroadcastListenerCount;
for (int i = 0; i < N; i++) {
try {
d(TAG, "finishUpdateTimeline, Notifying callback no. " + i);
IAndTweetServiceCallback cb = mCallbacks.getBroadcastItem(i);
if (cb != null) {
if (tweetsChanged > 0) {
cb.tweetsChanged(tweetsChanged);
}
if (repliesChanged > 0) {
cb.repliesChanged(repliesChanged);
}
if (messagesChanged > 0) {
cb.messagesChanged(messagesChanged);
}
cb.dataLoading(0);
}
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
}
boolean notified = false;
if (repliesChanged > 0) {
notifyOfNewTweets(repliesChanged, CommandEnum.NOTIFY_REPLIES);
notified = true;
}
if (messagesChanged > 0) {
notifyOfNewTweets(messagesChanged, CommandEnum.NOTIFY_DIRECT_MESSAGE);
notified = true;
}
if (tweetsChanged > 0 || !notified) {
notifyOfNewTweets(tweetsChanged, CommandEnum.NOTIFY_TIMELINE);
notified = true;
}
}
d(TAG, "notifyOfNewTweets n=" + numTweets + "; msgType=" + msgType);
if (updateWidgetsOnEveryUpdate) {
updateWidgets(numTweets, msgType);
}
if (!mNotificationsEnabled || numTweets == 0) {
return;
}
boolean notificationsMessages = false;
boolean notificationsReplies = false;
boolean notificationsTimeline = false;
String ringtone = null;
SharedPreferences sp = getSp();
synchronized (sp) {
notificationsMessages = sp.getBoolean("notifications_messages", false);
notificationsReplies = sp.getBoolean("notifications_mentions", false);
notificationsTimeline = sp.getBoolean("notifications_timeline", false);
ringtone = sp.getString(PreferencesActivity.KEY_RINGTONE_PREFERENCE, null);
}
sp = null;
switch (msgType) {
case NOTIFY_REPLIES:
if (!notificationsReplies)
return;
break;
case NOTIFY_DIRECT_MESSAGE:
if (!notificationsMessages)
return;
break;
case NOTIFY_TIMELINE:
if (!notificationsTimeline)
return;
break;
}
Notification notification = new Notification(R.drawable.notification_icon,
(String) getText(R.string.notification_title), System.currentTimeMillis());
notification.vibrate = null;
if (mNotificationsVibrate) {
notification.vibrate = new long[] {
200, 300, 200, 300
};
}
notification.flags = Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_AUTO_CANCEL;
notification.ledOffMS = 1000;
notification.ledOnMS = 500;
notification.ledARGB = Color.GREEN;
if ("".equals(ringtone) || ringtone == null) {
notification.sound = null;
} else {
Uri ringtoneUri = Uri.parse(ringtone);
notification.sound = ringtoneUri;
}
PendingIntent contentIntent;
int messageTitle;
Intent intent;
String aMessage = "";
switch (msgType) {
case NOTIFY_REPLIES:
aMessage = I18n.formatQuantityMessage(getApplicationContext(),
R.string.notification_new_mention_format, numTweets,
R.array.notification_mention_patterns,
R.array.notification_mention_formats);
messageTitle = R.string.notification_title_mentions;
intent = new Intent(getApplicationContext(), TweetListActivity.class);
intent.putExtra(AndTweetService.EXTRA_TIMELINE_TYPE,
AndTweetDatabase.Tweets.TIMELINE_TYPE_MENTIONS);
contentIntent = PendingIntent.getActivity(getApplicationContext(), numTweets,
intent, 0);
break;
case NOTIFY_DIRECT_MESSAGE:
aMessage = I18n.formatQuantityMessage(getApplicationContext(),
R.string.notification_new_message_format, numTweets,
R.array.notification_message_patterns,
R.array.notification_message_formats);
messageTitle = R.string.notification_title_messages;
intent = new Intent(getApplicationContext(), MessageListActivity.class);
intent.putExtra(AndTweetService.EXTRA_TIMELINE_TYPE,
AndTweetDatabase.Tweets.TIMELINE_TYPE_MESSAGES);
contentIntent = PendingIntent.getActivity(getApplicationContext(), numTweets,
intent, 0);
break;
case NOTIFY_TIMELINE:
default:
aMessage = I18n
.formatQuantityMessage(getApplicationContext(),
R.string.notification_new_tweet_format, numTweets,
R.array.notification_tweet_patterns,
R.array.notification_tweet_formats);
messageTitle = R.string.notification_title;
intent = new Intent(getApplicationContext(), TweetListActivity.class);
intent.putExtra(AndTweetService.EXTRA_TIMELINE_TYPE,
AndTweetDatabase.Tweets.TIMELINE_TYPE_FRIENDS);
contentIntent = PendingIntent.getActivity(getApplicationContext(), numTweets,
intent, 0);
break;
}
notification.tickerText = aMessage;
notification.setLatestEventInfo(AndTweetService.this, getText(messageTitle), aMessage,
contentIntent);
NotificationManager nM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nM.notify(msgType.ordinal(), notification);
}
Intent intent = new Intent(ACTION_APPWIDGET_UPDATE);
intent.putExtra(EXTRA_MSGTYPE, msgType.save());
intent.putExtra(EXTRA_NUMTWEETS, numTweets);
sendBroadcast(intent);
}
boolean ok = false;
JSONObject result = new JSONObject();
try {
result = TwitterUser.getTwitterUser().getConnection().rateLimitStatus();
ok = (result != null);
} catch (ConnectionException e) {
Log.e(TAG, "rateLimitStatus Exception: " + e.toString());
}
if (ok) {
for (int i = 0; i < mBroadcastListenerCount; i++) {
try {
IAndTweetServiceCallback cb = mCallbacks.getBroadcastItem(i);
if (cb != null) {
cb.rateLimitStatus(result.getInt("remaining_hits"),
result.getInt("hourly_limit"));
}
} catch (RemoteException e) {
d(TAG, e.toString());
} catch (JSONException e) {
Log.e(TAG, e.toString());
}
}
}
return ok;
}
}
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wakeLock.acquire();
return wakeLock;
}
int frequencyS = Integer.parseInt(getSp().getString("fetch_frequency", "180"));
return (frequencyS * MILLISECONDS);
}
final AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
final PendingIntent pIntent = getRepeatingIntent();
final int frequencyMs = getFetchFrequencyS();
final long firstTime = SystemClock.elapsedRealtime() + frequencyMs;
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, frequencyMs, pIntent);
d(TAG, "Started repeating alarm in a " + frequencyMs + "ms rhythm.");
return true;
}
final AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
final PendingIntent pIntent = getRepeatingIntent();
am.cancel(pIntent);
d(TAG, "Cancelled repeating alarm.");
return true;
}
Intent intent = new Intent(ACTION_ALARM);
intent.putExtra(AndTweetService.EXTRA_MSGTYPE, CommandEnum.AUTOMATIC_UPDATE.save());
PendingIntent pIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
return pIntent;
}
private final IAndTweetService.Stub mBinder = new IAndTweetService.Stub() {
public void registerCallback(IAndTweetServiceCallback cb) {
if (cb != null)
mCallbacks.register(cb);
}
public void unregisterCallback(IAndTweetServiceCallback cb) {
if (cb != null)
mCallbacks.unregister(cb);
}
};
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isAvailable()
&& cm.getActiveNetworkInfo().isConnected()) {
return true;
} else {
v(TAG, "Internet Connection Not Present");
return false;
}
}
public static int d(String tag, String msg) {
int i = 0;
if (Log.isLoggable(AndTweetService.APPTAG, Log.DEBUG)) {
i = Log.d(tag, msg);
}
return i;
}
public static int d(String tag, String msg, Throwable tr) {
int i = 0;
if (Log.isLoggable(AndTweetService.APPTAG, Log.DEBUG)) {
i = Log.d(tag, msg, tr);
}
return i;
}
public static int v(String tag, String msg) {
int i = 0;
if (Log.isLoggable(AndTweetService.APPTAG, Log.VERBOSE)) {
i = Log.v(tag, msg);
}
return i;
}
}