package com.hexonxons.leprawatch.system; import java.util.ArrayList; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.koroed.lepra.Lepra; import org.koroed.lepra.content.LepraComment; import org.koroed.lepra.content.LepraPost; import org.koroed.lepra.content.LepraProfile; import org.koroed.lepra.content.LepraUser; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; public class NetService extends Service { private final SynchronousQueue<Runnable> mMultiThreadQueue = new SynchronousQueue<Runnable>(); private final ThreadPoolExecutor mMultiThreadExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, mMultiThreadQueue); private Multimap<String, String> mPendingTasks = Multimaps.synchronizedListMultimap(ArrayListMultimap.<String, String>create()); private Multimap<String, String> mRunningTasks = Multimaps.synchronizedListMultimap(ArrayListMultimap.<String, String>create()); public interface NetworkInterface { public boolean isPending(String action, String id); public boolean isRunning(String action, String id); } private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, final Intent intent) { switch(intent.getAction()) { case Constants.INTENT_FILTER.ACTION_AUTH: { // Check if task is already queued or running if(mPendingTasks.get(Constants.INTENT_FILTER.ACTION_AUTH).size() == 0 && mRunningTasks.get(Constants.INTENT_FILTER.ACTION_AUTH).size() == 0) { mPendingTasks.put(Constants.INTENT_FILTER.ACTION_AUTH, Constants.INTENT_FILTER.ACTION_AUTH); mMultiThreadExecutor.submit(new Runnable() { @Override public void run() { mPendingTasks.removeAll(Constants.INTENT_FILTER.ACTION_AUTH); mRunningTasks.put(Constants.INTENT_FILTER.ACTION_AUTH, Constants.INTENT_FILTER.ACTION_AUTH); String username = intent.getStringExtra(Constants.BUNDLE.KEY_USERNAME); String password = intent.getStringExtra(Constants.BUNDLE.KEY_PASSWORD); Intent result = null; try { Lepra.getInstance().login(username, password, true); result = new Intent(Constants.INTENT_FILTER.ACTION_AUTH_SUCCESS); } catch (Exception e) { e.printStackTrace(); result = new Intent(Constants.INTENT_FILTER.ACTION_AUTH_FAIL); } finally { LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result); mRunningTasks.removeAll(Constants.INTENT_FILTER.ACTION_AUTH); } } }); } break; } case Constants.INTENT_FILTER.ACTION_LOGOUT: { // Check if task is already queued or running if(mPendingTasks.get(Constants.INTENT_FILTER.ACTION_LOGOUT).size() == 0 && mRunningTasks.get(Constants.INTENT_FILTER.ACTION_LOGOUT).size() == 0) { mPendingTasks.put(Constants.INTENT_FILTER.ACTION_LOGOUT, Constants.INTENT_FILTER.ACTION_LOGOUT); mMultiThreadExecutor.submit(new Runnable() { @Override public void run() { mPendingTasks.removeAll(Constants.INTENT_FILTER.ACTION_LOGOUT); mRunningTasks.put(Constants.INTENT_FILTER.ACTION_LOGOUT, Constants.INTENT_FILTER.ACTION_LOGOUT); Intent result = null; try { Lepra.getInstance().logout(getApplicationContext()); result = new Intent(Constants.INTENT_FILTER.ACTION_LOGOUT_SUCCESS); } catch (Exception e) { e.printStackTrace(); result = new Intent(Constants.INTENT_FILTER.ACTION_LOGOUT_FAIL); } finally { LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result); mRunningTasks.removeAll(Constants.INTENT_FILTER.ACTION_LOGOUT); } } }); } break; } case Constants.INTENT_FILTER.ACTION_GET_POSTS: { // Check if task is already queued or running if(mPendingTasks.get(Constants.INTENT_FILTER.ACTION_GET_POSTS).size() == 0 && mRunningTasks.get(Constants.INTENT_FILTER.ACTION_GET_POSTS).size() == 0) { mPendingTasks.put(Constants.INTENT_FILTER.ACTION_GET_POSTS, Constants.INTENT_FILTER.ACTION_GET_POSTS); mMultiThreadExecutor.submit(new Runnable() { @Override public void run() { mPendingTasks.removeAll(Constants.INTENT_FILTER.ACTION_GET_POSTS); mRunningTasks.put(Constants.INTENT_FILTER.ACTION_GET_POSTS, Constants.INTENT_FILTER.ACTION_GET_POSTS); Intent result = null; try { ArrayList<LepraPost> posts = Lepra.getInstance().loadPosts(null, "last_activity"); result = new Intent(Constants.INTENT_FILTER.ACTION_GET_POSTS_RESULT_SUCCESS); result.putParcelableArrayListExtra(Constants.BUNDLE.KEY_POSTS, posts); } catch (Exception e) { e.printStackTrace(); result = new Intent(Constants.INTENT_FILTER.ACTION_GET_POSTS_RESULT_FAIL); } finally { LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result); mRunningTasks.removeAll(Constants.INTENT_FILTER.ACTION_GET_POSTS); } } }); } break; } case Constants.INTENT_FILTER.ACTION_GET_POST_COMMENTS: { final LepraPost post = intent.getParcelableExtra(Constants.BUNDLE.KEY_POST); // Check if task is already queued or running if(!mPendingTasks.containsEntry(Constants.INTENT_FILTER.ACTION_GET_POST_COMMENTS, Integer.toString(post.id)) && !mRunningTasks.containsEntry(Constants.INTENT_FILTER.ACTION_GET_PROFILE, Integer.toString(post.id))) { mPendingTasks.put(Constants.INTENT_FILTER.ACTION_GET_POST_COMMENTS, Integer.toString(post.id)); mMultiThreadExecutor.submit(new Runnable() { @Override public void run() { mPendingTasks.remove(Constants.INTENT_FILTER.ACTION_GET_POST_COMMENTS, Integer.toString(post.id)); mRunningTasks.put(Constants.INTENT_FILTER.ACTION_GET_POST_COMMENTS, Integer.toString(post.id)); Intent result = null; try { ArrayList<LepraComment> comments = Lepra.getInstance().loadPostComments(post.id); result = new Intent(Constants.INTENT_FILTER.ACTION_GET_POST_COMMENTS_RESULT_SUCCESS); result.putParcelableArrayListExtra(Constants.BUNDLE.KEY_COMMENTS, comments); } catch (Exception e) { e.printStackTrace(); result = new Intent(Constants.INTENT_FILTER.ACTION_GET_POST_COMMENTS_RESULT_FAIL); } finally { LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result); mRunningTasks.remove(Constants.INTENT_FILTER.ACTION_GET_POST_COMMENTS, Integer.toString(post.id)); } } }); } break; } case Constants.INTENT_FILTER.ACTION_GET_PROFILE: { final LepraUser user = intent.getParcelableExtra(Constants.BUNDLE.KEY_USER); // Check if task is already queued or running if(!mPendingTasks.containsEntry(Constants.INTENT_FILTER.ACTION_GET_PROFILE, user.login) && !mRunningTasks.containsEntry(Constants.INTENT_FILTER.ACTION_GET_PROFILE, user.login)) { mPendingTasks.put(Constants.INTENT_FILTER.ACTION_GET_PROFILE, user.login); mMultiThreadExecutor.submit(new Runnable() { @Override public void run() { mPendingTasks.remove(Constants.INTENT_FILTER.ACTION_GET_PROFILE, user.login); mRunningTasks.put(Constants.INTENT_FILTER.ACTION_GET_PROFILE, user.login); Intent result = null; try { LepraProfile profile = Lepra.getInstance().loadProfile(user.login); result = new Intent(Constants.INTENT_FILTER.ACTION_GET_PROFILE_RESULT_SUCCESS); result.putExtra(Constants.BUNDLE.KEY_USER_PROFILE, profile); } catch (Exception e) { e.printStackTrace(); result = new Intent(Constants.INTENT_FILTER.ACTION_GET_PROFILE_RESULT_FAIL); } finally { LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result); mRunningTasks.remove(Constants.INTENT_FILTER.ACTION_GET_PROFILE, user.login); } } }); } break; } } } }; public void onCreate() { IntentFilter filter = new IntentFilter(); filter.addAction(Constants.INTENT_FILTER.ACTION_AUTH); filter.addAction(Constants.INTENT_FILTER.ACTION_LOGOUT); filter.addAction(Constants.INTENT_FILTER.ACTION_GET_POSTS); filter.addAction(Constants.INTENT_FILTER.ACTION_GET_PROFILE); filter.addAction(Constants.INTENT_FILTER.ACTION_GET_POST_COMMENTS); LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mBroadcastReceiver, filter); }; @Override public IBinder onBind(Intent arg0) { return new NwBinder(); } private class NwBinder extends Binder implements NetworkInterface { public boolean isPending(String action, String id) { return mPendingTasks.containsEntry(action, id); } public boolean isRunning(String action, String id) { return mRunningTasks.containsEntry(action, id); } } }