package io.myweb;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
public class TempServiceConnection implements ServiceConnection {
private static final int DEFAULT_TIMEOUT = 60000;
private static final Map<String, TempServiceConnection> serviceMap =
Collections.synchronizedMap(new HashMap<String, TempServiceConnection>());
private final Context context;
private final int timeout;
private CountDownLatch serviceConnected = new CountDownLatch(1);
private volatile Object service;
private CancelableUnbindTask unbindTask;
private ExecutorService executor;
private class CancelableUnbindTask implements Runnable {
private boolean canceled = false;
@Override
public void run() {
synchronized (this) {
try {
wait(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!canceled) context.unbindService(TempServiceConnection.this);
}
}
public synchronized void cancel() {
canceled = true;
notify();
}
public synchronized void perform() {
notifyAll();
}
}
public TempServiceConnection(Context ctx, Class<?> c, ExecutorService executor) {
this(ctx, c, executor, DEFAULT_TIMEOUT);
}
public TempServiceConnection(Context ctx, Class<?> c, ExecutorService executor, int timeout) {
this(ctx, new ComponentName(ctx.getPackageName(), c.getName()), executor, timeout);
}
public TempServiceConnection(Context ctx, ComponentName name, ExecutorService executor) {
this(ctx, name, executor, DEFAULT_TIMEOUT);
}
public TempServiceConnection(Context ctx, ComponentName name, ExecutorService executor, int timeout) {
context = ctx;
this.timeout = timeout;
this.executor = executor;
serviceMap.put(name.getClassName(), this);
Intent intent = new Intent();
intent.setComponent(name);
context.bindService(intent, this, Context.BIND_AUTO_CREATE);
}
private void scheduleUnbindTask() {
if (unbindTask!=null) unbindTask.cancel();
if (executor != null) {
unbindTask = new CancelableUnbindTask();
executor.submit(unbindTask);
}
}
private void terminate() {
if (unbindTask != null) unbindTask.perform();
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (service instanceof LocalService.Binder)
this.service =((LocalService.Binder) service).getService();
else this.service = service;
serviceConnected.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
service = null;
serviceMap.remove(name.getClassName());
serviceConnected.countDown();
}
public Object getServiceObject() {
try {
serviceConnected.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (service != null) {
scheduleUnbindTask();
}
return service;
}
public static TempServiceConnection get(String className) {
return serviceMap.get(className);
}
public static void terminateAll() {
for (TempServiceConnection conn: serviceMap.values()) {
conn.terminate();
}
}
}