package org.kde.connect; import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.os.Binder; import android.os.IBinder; import android.util.Log; import org.kde.connect.ComputerLinks.BaseComputerLink; import org.kde.connect.LinkProviders.AvahiTcpLinkProvider; import org.kde.connect.LinkProviders.BaseLinkProvider; import org.kde.connect.LinkProviders.AvahiLinkProvider; import org.kde.connect.PackageEmitters.BasePackageEmitter; import org.kde.connect.PackageEmitters.CallPackageEmitter; import org.kde.connect.PackageEmitters.PingPackageEmitter; import org.kde.connect.PackageReceivers.BasePackageReceiver; import org.kde.connect.PackageReceivers.PingPackageReceiver; import java.util.ArrayList; import java.util.Dictionary; import java.util.HashMap; public class BackgroundService extends Service { SharedPreferences settings; ArrayList locators = new ArrayList(); ArrayList emitters = new ArrayList(); ArrayList receivers = new ArrayList(); HashMap devices = new HashMap(); PingPackageEmitter pingEmitter; private void registerEmitters() { if (settings.getBoolean("emit_call", true)) { emitters.add(new CallPackageEmitter(getApplicationContext())); } if (settings.getBoolean("emit_ping", true)) { emitters.add(pingEmitter); } } private void registerReceivers() { if (settings.getBoolean("receive_ping", true)) { receivers.add(new PingPackageReceiver(getApplicationContext())); } } public void registerAnnouncers() { /*if (settings.getBoolean("announce_avahi", true)) { locators.add(new AvahiLinkProvider(this)); }*/ if (settings.getBoolean("announce_avahi_tcp", true)) { locators.add(new AvahiTcpLinkProvider(this)); } } public ArrayList getVisibleDevices() { ArrayList list = new ArrayList(); for(Device d : devices.values()) { list.add(d.getName()); } return list; } //This will be called for each intent launch, even if the service is already started and is reused @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e("BackgroundService","Running callbacks waiting service to be ready"); for (InstanceCallback c : callbacks) { c.onServiceStart(this); } callbacks.clear(); return Service.START_STICKY; } private void startDiscovery() { Log.e("StartDiscovery","Registering connection receivers"); for (BaseLinkProvider a : locators) { Log.e("Registerign", a.toString()); a.reachComputers(new BaseLinkProvider.ConnectionReceiver() { @Override public void onConnectionAccepted(String deviceId, String name, BaseComputerLink link) { Log.e("BackgroundService", "Connection accepted!"); if (devices.containsKey(deviceId)) { Log.e("BackgroundService", "known device"); devices.get(deviceId).addLink(link); } else { Log.e("BackgroundService", "unknown device"); Device device = new Device(deviceId, name, link); devices.put(deviceId, device); for (BasePackageEmitter pe : emitters) pe.addDevice(device); for (BasePackageReceiver pr : receivers) device.addPackageReceiver(pr); } } @Override public void onConnectionLost(BaseComputerLink link) { Device d = devices.get(link.getDeviceId()); if (d != null) { d.removeLink(link); //if (d.countLinkedDevices() == 0) devices.remove(link.getDeviceId); } } }); } } public void sendPing() { pingEmitter.sendPing(); } //This will called only once, even if we launch the service intent several times @Override public void onCreate() { super.onCreate(); Log.e("BackgroundService","Service not started yet, initializing..."); settings = getSharedPreferences("KdeConnect", 0); pingEmitter = new PingPackageEmitter(getApplicationContext()); registerEmitters(); registerReceivers(); registerAnnouncers(); startDiscovery(); } public void restart() { devices.clear(); startDiscovery(); } @Override public void onDestroy() { Log.e("BackgroundService", "Destroying"); super.onDestroy(); } @Override public IBinder onBind (Intent intent) { return new Binder(); } //To use the service from the gui public interface InstanceCallback { void onServiceStart(BackgroundService service); } private static ArrayList callbacks = new ArrayList(); public static void Start(Context c) { RunCommand(c, null); } public static void RunCommand(Context c, final InstanceCallback callback) { if (callback != null) callbacks.add(callback); Intent serviceIntent = new Intent(c, BackgroundService.class); c.startService(serviceIntent); } }