/* * Copyright (C) 2012 Eyal LEZMY (http://www.eyal.fr) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package fr.eyal.lib.service; import java.util.ArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Process; abstract public class MultiThreadService extends Service { public static final String INTENT_EXTRA_REQUEST_ID = "requestId"; public static final String INTENT_EXTRA_RECEIVER = "receiver"; public static final int SUCCESS_CODE = 1337; public static final int ERROR_CODE = -1; private ExecutorService mThreadPool; private int mMaxThreads; @SuppressWarnings("rawtypes") private ArrayList<Future> mFutureList; private Handler mHandler; public MultiThreadService(final int maxThreads) { mMaxThreads = maxThreads; } /** * Callback used when a thread has finished working */ final Runnable mHasFinishedWorkingRunnable = new Runnable() { @SuppressWarnings("rawtypes") @Override public void run() { final ArrayList<Future> futureList = mFutureList; for (int i = 0; i < futureList.size(); i++) { if (futureList.get(i).isDone()) { futureList.remove(i); i--; } } if (futureList.isEmpty()) { stopSelf(); } } }; @SuppressWarnings("rawtypes") @Override public void onCreate() { super.onCreate(); mThreadPool = Executors.newFixedThreadPool(mMaxThreads); mHandler = new Handler(); mFutureList = new ArrayList<Future>(); } @Override public void onStart(final Intent intent, final int startId) { IntentRunnable runnable = new IntentRunnable(intent); mFutureList.add(mThreadPool.submit(runnable)); } @Override public int onStartCommand(final Intent intent, final int flags, final int startId) { onStart(intent, startId); return START_STICKY; } @Override public IBinder onBind(final Intent intent) { return null; } private class IntentRunnable implements Runnable { private Intent mIntent; public IntentRunnable(final Intent intent) { mIntent = intent; } @Override public void run() { //we set the thread as background Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); onHandleIntent(mIntent); mHandler.post(mHasFinishedWorkingRunnable); } } /** * This method is invoked on the worker thread with a request to process. * The processing happens on a worker thread that runs independently from * other application logic. * * @param intent The value passed to {@link Content#startService(Intent)}. */ abstract protected void onHandleIntent(Intent intent); }