2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-25 03:17:09 +00:00

Use lambdas where possible

Summary: Let Android Studio replace anonymous types with lambdas. No manual code change.

Test Plan: Compile and superficial behaviour test

Reviewers: #kde_connect, philipc

Reviewed By: #kde_connect, philipc

Subscribers: philipc, #kde_connect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D12229
This commit is contained in:
Nicolas Fella 2018-05-09 14:02:56 +02:00
parent 7536eb7427
commit e712c69e15
31 changed files with 1077 additions and 1615 deletions

View File

@ -23,10 +23,8 @@ android {
javaMaxHeapSize "2g" javaMaxHeapSize "2g"
} }
compileOptions { compileOptions {
// Use Java 1.7, requires minSdk 8 sourceCompatibility JavaVersion.VERSION_1_8
//SSHD requires mina when running on JDK < 7 targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
} }
sourceSets { sourceSets {
main { main {

View File

@ -89,34 +89,31 @@ public class LanLink extends BaseLink {
//Log.e("LanLink", "Start listening"); //Log.e("LanLink", "Start listening");
//Create a thread to take care of incoming data for the new socket //Create a thread to take care of incoming data for the new socket
new Thread(new Runnable() { new Thread(() -> {
@Override try {
public void run() { BufferedReader reader = new BufferedReader(new InputStreamReader(newSocket.getInputStream(), StringsHelper.UTF8));
try { while (true) {
BufferedReader reader = new BufferedReader(new InputStreamReader(newSocket.getInputStream(), StringsHelper.UTF8)); String packet;
while (true) { try {
String packet; packet = reader.readLine();
try { } catch (SocketTimeoutException e) {
packet = reader.readLine(); continue;
} catch (SocketTimeoutException e) {
continue;
}
if (packet == null) {
throw new IOException("End of stream");
}
if (packet.isEmpty()) {
continue;
}
NetworkPacket np = NetworkPacket.unserialize(packet);
receivedNetworkPacket(np);
} }
} catch (Exception e) { if (packet == null) {
Log.i("LanLink", "Socket closed: " + newSocket.hashCode() + ". Reason: " + e.getMessage()); throw new IOException("End of stream");
try { Thread.sleep(300); } catch (InterruptedException ignored) {} // Wait a bit because we might receive a new socket meanwhile
boolean thereIsaANewSocket = (newSocket != socket);
if (!thereIsaANewSocket) {
callback.linkDisconnected(LanLink.this);
} }
if (packet.isEmpty()) {
continue;
}
NetworkPacket np = NetworkPacket.unserialize(packet);
receivedNetworkPacket(np);
}
} catch (Exception e) {
Log.i("LanLink", "Socket closed: " + newSocket.hashCode() + ". Reason: " + e.getMessage());
try { Thread.sleep(300); } catch (InterruptedException ignored) {} // Wait a bit because we might receive a new socket meanwhile
boolean thereIsaANewSocket = (newSocket != socket);
if (!thereIsaANewSocket) {
callback.linkDisconnected(LanLink.this);
} }
} }
}).start(); }).start();

View File

@ -221,59 +221,47 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
if (isDeviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) { if (isDeviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) {
//Device paired with and old version, we can't use it as we lack the certificate //Device paired with and old version, we can't use it as we lack the certificate
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(context, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { if (device == null) return;
Device device = service.getDevice(deviceId); device.unpair();
if (device == null) return; //Retry as unpaired
device.unpair(); identityPacketReceived(identityPacket, socket, connectionStarted);
//Retry as unpaired
identityPacketReceived(identityPacket, socket, connectionStarted);
}
}); });
} }
Log.i("KDE/LanLinkProvider", "Starting SSL handshake with " + identityPacket.getString("deviceName") + " trusted:" + isDeviceTrusted); Log.i("KDE/LanLinkProvider", "Starting SSL handshake with " + identityPacket.getString("deviceName") + " trusted:" + isDeviceTrusted);
final SSLSocket sslsocket = SslHelper.convertToSslSocket(context, socket, deviceId, isDeviceTrusted, clientMode); final SSLSocket sslsocket = SslHelper.convertToSslSocket(context, socket, deviceId, isDeviceTrusted, clientMode);
sslsocket.addHandshakeCompletedListener(new HandshakeCompletedListener() { sslsocket.addHandshakeCompletedListener(event -> {
@Override String mode = clientMode ? "client" : "server";
public void handshakeCompleted(HandshakeCompletedEvent event) { try {
String mode = clientMode ? "client" : "server"; Certificate certificate = event.getPeerCertificates()[0];
try { identityPacket.set("certificate", Base64.encodeToString(certificate.getEncoded(), 0));
Certificate certificate = event.getPeerCertificates()[0]; Log.i("KDE/LanLinkProvider", "Handshake as " + mode + " successful with " + identityPacket.getString("deviceName") + " secured with " + event.getCipherSuite());
identityPacket.set("certificate", Base64.encodeToString(certificate.getEncoded(), 0)); addLink(identityPacket, sslsocket, connectionStarted);
Log.i("KDE/LanLinkProvider", "Handshake as " + mode + " successful with " + identityPacket.getString("deviceName") + " secured with " + event.getCipherSuite()); } catch (Exception e) {
addLink(identityPacket, sslsocket, connectionStarted); Log.e("KDE/LanLinkProvider", "Handshake as " + mode + " failed with " + identityPacket.getString("deviceName"));
} catch (Exception e) { e.printStackTrace();
Log.e("KDE/LanLinkProvider", "Handshake as " + mode + " failed with " + identityPacket.getString("deviceName")); BackgroundService.RunCommand(context, service -> {
e.printStackTrace(); Device device = service.getDevice(deviceId);
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() { if (device == null) return;
@Override device.unpair();
public void onServiceStart(BackgroundService service) { });
Device device = service.getDevice(deviceId);
if (device == null) return;
device.unpair();
}
});
}
} }
}); });
//Handshake is blocking, so do it on another thread and free this thread to keep receiving new connection //Handshake is blocking, so do it on another thread and free this thread to keep receiving new connection
new Thread(new Runnable() { new Thread(() -> {
@Override try {
public void run() { sslsocket.startHandshake();
try { } catch (Exception e) {
sslsocket.startHandshake(); Log.e("KDE/LanLinkProvider", "Handshake failed with " + identityPacket.getString("deviceName"));
} catch (Exception e) { e.printStackTrace();
Log.e("KDE/LanLinkProvider", "Handshake failed with " + identityPacket.getString("deviceName"));
e.printStackTrace();
//String[] ciphers = sslsocket.getSupportedCipherSuites(); //String[] ciphers = sslsocket.getSupportedCipherSuites();
//for (String cipher : ciphers) { //for (String cipher : ciphers) {
// Log.i("SupportedCiphers","cipher: " + cipher); // Log.i("SupportedCiphers","cipher: " + cipher);
//} //}
}
} }
}).start(); }).start();
} else { } else {
@ -331,23 +319,20 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
new Thread(new Runnable() { new Thread(() -> {
@Override while (listening) {
public void run() { final int bufferSize = 1024 * 512;
while (listening) { byte[] data = new byte[bufferSize];
final int bufferSize = 1024 * 512; DatagramPacket packet = new DatagramPacket(data, bufferSize);
byte[] data = new byte[bufferSize]; try {
DatagramPacket packet = new DatagramPacket(data, bufferSize); server.receive(packet);
try { udpPacketReceived(packet);
server.receive(packet); } catch (Exception e) {
udpPacketReceived(packet); e.printStackTrace();
} catch (Exception e) { Log.e("LanLinkProvider", "UdpReceive exception");
e.printStackTrace();
Log.e("LanLinkProvider", "UdpReceive exception");
}
} }
Log.w("UdpListener", "Stopping UDP listener");
} }
Log.w("UdpListener", "Stopping UDP listener");
}).start(); }).start();
return server; return server;
} }
@ -356,21 +341,18 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
try { try {
tcpServer = openServerSocketOnFreePort(MIN_PORT); tcpServer = openServerSocketOnFreePort(MIN_PORT);
new Thread(new Runnable() { new Thread(() -> {
@Override while (listening) {
public void run() { try {
while (listening) { Socket socket = tcpServer.accept();
try { configureSocket(socket);
Socket socket = tcpServer.accept(); tcpPacketReceived(socket);
configureSocket(socket); } catch (Exception e) {
tcpPacketReceived(socket); e.printStackTrace();
} catch (Exception e) { Log.e("LanLinkProvider", "TcpReceive exception");
e.printStackTrace();
Log.e("LanLinkProvider", "TcpReceive exception");
}
} }
Log.w("TcpListener", "Stopping TCP listener");
} }
Log.w("TcpListener", "Stopping TCP listener");
}).start(); }).start();
} catch (Exception e) { } catch (Exception e) {
@ -401,51 +383,48 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
return; return;
} }
new Thread(new Runnable() { new Thread(() -> {
@Override
public void run() {
String deviceListPrefs = PreferenceManager.getDefaultSharedPreferences(context).getString(CustomDevicesActivity.KEY_CUSTOM_DEVLIST_PREFERENCE, ""); String deviceListPrefs = PreferenceManager.getDefaultSharedPreferences(context).getString(CustomDevicesActivity.KEY_CUSTOM_DEVLIST_PREFERENCE, "");
ArrayList<String> iplist = new ArrayList<>(); ArrayList<String> iplist = new ArrayList<>();
if (!deviceListPrefs.isEmpty()) { if (!deviceListPrefs.isEmpty()) {
iplist = CustomDevicesActivity.deserializeIpList(deviceListPrefs); iplist = CustomDevicesActivity.deserializeIpList(deviceListPrefs);
} }
iplist.add("255.255.255.255"); //Default: broadcast. iplist.add("255.255.255.255"); //Default: broadcast.
NetworkPacket identity = NetworkPacket.createIdentityPacket(context); NetworkPacket identity = NetworkPacket.createIdentityPacket(context);
identity.set("tcpPort", MIN_PORT); identity.set("tcpPort", MIN_PORT);
DatagramSocket socket = null; DatagramSocket socket = null;
byte[] bytes = null; byte[] bytes = null;
try { try {
socket = new DatagramSocket(); socket = new DatagramSocket();
socket.setReuseAddress(true); socket.setReuseAddress(true);
socket.setBroadcast(true); socket.setBroadcast(true);
bytes = identity.serialize().getBytes(StringsHelper.UTF8); bytes = identity.serialize().getBytes(StringsHelper.UTF8);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Log.e("KDE/LanLinkProvider", "Failed to create DatagramSocket"); Log.e("KDE/LanLinkProvider", "Failed to create DatagramSocket");
} }
if (bytes != null) { if (bytes != null) {
//Log.e("KDE/LanLinkProvider","Sending packet to "+iplist.size()+" ips"); //Log.e("KDE/LanLinkProvider","Sending packet to "+iplist.size()+" ips");
for (String ipstr : iplist) { for (String ipstr : iplist) {
try { try {
InetAddress client = InetAddress.getByName(ipstr); InetAddress client = InetAddress.getByName(ipstr);
socket.send(new DatagramPacket(bytes, bytes.length, client, MIN_PORT)); socket.send(new DatagramPacket(bytes, bytes.length, client, MIN_PORT));
socket.send(new DatagramPacket(bytes, bytes.length, client, MIN_PORT_LEGACY)); socket.send(new DatagramPacket(bytes, bytes.length, client, MIN_PORT_LEGACY));
//Log.i("KDE/LanLinkProvider","Udp identity package sent to address "+client); //Log.i("KDE/LanLinkProvider","Udp identity package sent to address "+client);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Log.e("KDE/LanLinkProvider", "Sending udp identity package failed. Invalid address? (" + ipstr + ")"); Log.e("KDE/LanLinkProvider", "Sending udp identity package failed. Invalid address? (" + ipstr + ")");
}
} }
} }
if (socket != null) {
socket.close();
}
} }
if (socket != null) {
socket.close();
}
}).start(); }).start();
} }

View File

@ -87,24 +87,18 @@ public class BackgroundService extends Service {
} }
public static void addGuiInUseCounter(final Context activity, final boolean forceNetworkRefresh) { public static void addGuiInUseCounter(final Context activity, final boolean forceNetworkRefresh) {
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(activity, service -> {
@Override boolean refreshed = service.acquireDiscoveryMode(activity);
public void onServiceStart(BackgroundService service) { if (!refreshed && forceNetworkRefresh) {
boolean refreshed = service.acquireDiscoveryMode(activity); service.onNetworkChange();
if (!refreshed && forceNetworkRefresh) {
service.onNetworkChange();
}
} }
}); });
} }
public static void removeGuiInUseCounter(final Context activity) { public static void removeGuiInUseCounter(final Context activity) {
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(activity, service -> {
@Override //If no user interface is open, close the connections open to other devices
public void onServiceStart(BackgroundService service) { service.releaseDiscoveryMode(activity);
//If no user interface is open, close the connections open to other devices
service.releaseDiscoveryMode(activity);
}
}); });
} }
@ -167,13 +161,10 @@ public class BackgroundService extends Service {
} }
private void cleanDevices() { private void cleanDevices() {
new Thread(new Runnable() { new Thread(() -> {
@Override for (Device d : devices.values()) {
public void run() { if (!d.isPaired() && !d.isPairRequested() && !d.isPairRequestedByPeer() && !d.deviceShouldBeKeptAlive()) {
for (Device d : devices.values()) { d.disconnect();
if (!d.isPaired() && !d.isPairRequested() && !d.isPairRequestedByPeer() && !d.deviceShouldBeKeptAlive()) {
d.disconnect();
}
} }
} }
}).start(); }).start();
@ -328,20 +319,17 @@ public class BackgroundService extends Service {
} }
public static void RunCommand(final Context c, final InstanceCallback callback) { public static void RunCommand(final Context c, final InstanceCallback callback) {
new Thread(new Runnable() { new Thread(() -> {
@Override if (callback != null) {
public void run() { mutex.lock();
if (callback != null) { try {
mutex.lock(); callbacks.add(callback);
try { } finally {
callbacks.add(callback); mutex.unlock();
} finally {
mutex.unlock();
}
} }
Intent serviceIntent = new Intent(c, BackgroundService.class);
c.startService(serviceIntent);
} }
Intent serviceIntent = new Intent(c, BackgroundService.class);
c.startService(serviceIntent);
}).start(); }).start();
} }

View File

@ -638,12 +638,7 @@ public class Device implements BaseLink.PacketReceiver {
//Async //Async
public void sendPacket(final NetworkPacket np, final SendPacketStatusCallback callback) { public void sendPacket(final NetworkPacket np, final SendPacketStatusCallback callback) {
new Thread(new Runnable() { new Thread(() -> sendPacketBlocking(np, callback)).start();
@Override
public void run() {
sendPacketBlocking(np, callback);
}
}).start();
} }
public boolean sendPacketBlocking(final NetworkPacket np, final SendPacketStatusCallback callback) { public boolean sendPacketBlocking(final NetworkPacket np, final SendPacketStatusCallback callback) {

View File

@ -43,41 +43,27 @@ public class KdeConnectBroadcastReceiver extends BroadcastReceiver {
Log.i("KdeConnect", "Ignoring, it's not me!"); Log.i("KdeConnect", "Ignoring, it's not me!");
return; return;
} }
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(context, service -> {
@Override
public void onServiceStart(BackgroundService service) {
}
}); });
break; break;
case Intent.ACTION_BOOT_COMPLETED: case Intent.ACTION_BOOT_COMPLETED:
Log.i("KdeConnect", "KdeConnectBroadcastReceiver"); Log.i("KdeConnect", "KdeConnectBroadcastReceiver");
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(context, service -> {
@Override
public void onServiceStart(BackgroundService service) {
}
}); });
break; break;
case WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION: case WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION:
case WifiManager.WIFI_STATE_CHANGED_ACTION: case WifiManager.WIFI_STATE_CHANGED_ACTION:
case ConnectivityManager.CONNECTIVITY_ACTION: case ConnectivityManager.CONNECTIVITY_ACTION:
Log.i("KdeConnect", "Connection state changed, trying to connect"); Log.i("KdeConnect", "Connection state changed, trying to connect");
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(context, service -> {
@Override service.onDeviceListChanged();
public void onServiceStart(BackgroundService service) { service.onNetworkChange();
service.onDeviceListChanged();
service.onNetworkChange();
}
}); });
break; break;
case Intent.ACTION_SCREEN_ON: case Intent.ACTION_SCREEN_ON:
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(context, BackgroundService::onNetworkChange);
@Override
public void onServiceStart(BackgroundService service) {
service.onNetworkChange();
}
});
break; break;
default: default:
Log.i("BroadcastReceiver", "Ignoring broadcast event: " + intent.getAction()); Log.i("BroadcastReceiver", "Ignoring broadcast event: " + intent.getAction());

View File

@ -69,35 +69,29 @@ public class ClipboardListener {
return; return;
} }
new Handler(Looper.getMainLooper()).post(new Runnable() { new Handler(Looper.getMainLooper()).post(() -> {
@Override cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
public void run() { listener = () -> {
cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); try {
listener = new ClipboardManager.OnPrimaryClipChangedListener() {
@Override
public void onPrimaryClipChanged() {
try {
ClipData.Item item = cm.getPrimaryClip().getItemAt(0); ClipData.Item item = cm.getPrimaryClip().getItemAt(0);
String content = item.coerceToText(context).toString(); String content = item.coerceToText(context).toString();
if (content.equals(currentContent)) { if (content.equals(currentContent)) {
return; return;
}
currentContent = content;
for (ClipboardObserver observer : observers) {
observer.clipboardChanged(content);
}
} catch (Exception e) {
//Probably clipboard was not text
}
} }
};
cm.addPrimaryClipChangedListener(listener); currentContent = content;
}
for (ClipboardObserver observer : observers) {
observer.clipboardChanged(content);
}
} catch (Exception e) {
//Probably clipboard was not text
}
};
cm.addPrimaryClipChangedListener(listener);
}); });
} }

View File

@ -53,13 +53,10 @@ public class ClipboardPlugin extends Plugin {
return true; return true;
} }
private ClipboardListener.ClipboardObserver observer = new ClipboardListener.ClipboardObserver() { private ClipboardListener.ClipboardObserver observer = content -> {
@Override NetworkPacket np = new NetworkPacket(ClipboardPlugin.PACKET_TYPE_CLIPBOARD);
public void clipboardChanged(String content) { np.set("content", content);
NetworkPacket np = new NetworkPacket(ClipboardPlugin.PACKET_TYPE_CLIPBOARD); device.sendPacket(np);
np.set("content", content);
device.sendPacket(np);
}
}; };
@Override @Override

View File

@ -67,12 +67,7 @@ public class FindMyPhoneActivity extends Activity {
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
findViewById(R.id.bFindMyPhone).setOnClickListener(new View.OnClickListener() { findViewById(R.id.bFindMyPhone).setOnClickListener(view -> finish());
@Override
public void onClick(View view) {
finish();
}
});
} }
@Override @Override

View File

@ -109,14 +109,11 @@ public class KeyListenerView extends View {
} }
private void sendKeyPressPacket(final NetworkPacket np) { private void sendKeyPressPacket(final NetworkPacket np) {
BackgroundService.RunCommand(getContext(), new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(getContext(), service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
Device device = service.getDevice(deviceId); if (mousePadPlugin == null) return;
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class); mousePadPlugin.sendKeyboardPacket(np);
if (mousePadPlugin == null) return;
mousePadPlugin.sendKeyboardPacket(np);
}
}); });
} }

View File

@ -135,27 +135,24 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
final View decorView = getWindow().getDecorView(); final View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { decorView.setOnSystemUiVisibilityChangeListener(visibility -> {
@Override if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
int fullscreenType = 0; int fullscreenType = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
fullscreenType |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; fullscreenType |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
fullscreenType |= View.SYSTEM_UI_FLAG_FULLSCREEN;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
fullscreenType |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
getWindow().getDecorView().setSystemUiVisibility(fullscreenType);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
fullscreenType |= View.SYSTEM_UI_FLAG_FULLSCREEN;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
fullscreenType |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
getWindow().getDecorView().setSystemUiVisibility(fullscreenType);
} }
}); });
} }
@ -214,16 +211,13 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_MOVE:
mCurrentX = event.getX(); mCurrentX = event.getX();
mCurrentY = event.getY(); mCurrentY = event.getY();
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
Device device = service.getDevice(deviceId); if (mousePadPlugin == null) return;
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class); mousePadPlugin.sendMouseDelta(mCurrentX - mPrevX, mCurrentY - mPrevY, mCurrentSensitivity);
if (mousePadPlugin == null) return; mPrevX = mCurrentX;
mousePadPlugin.sendMouseDelta(mCurrentX - mPrevX, mCurrentY - mPrevY, mCurrentSensitivity); mPrevY = mCurrentY;
mPrevX = mCurrentX;
mPrevY = mCurrentY;
}
}); });
break; break;
} }
@ -287,14 +281,11 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
getWindow().getDecorView().performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); getWindow().getDecorView().performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
Device device = service.getDevice(deviceId); if (mousePadPlugin == null) return;
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class); mousePadPlugin.sendSingleHold();
if (mousePadPlugin == null) return;
mousePadPlugin.sendSingleHold();
}
}); });
} }
@ -305,28 +296,22 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
@Override @Override
public boolean onSingleTapConfirmed(MotionEvent e) { public boolean onSingleTapConfirmed(MotionEvent e) {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
Device device = service.getDevice(deviceId); if (mousePadPlugin == null) return;
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class); mousePadPlugin.sendSingleClick();
if (mousePadPlugin == null) return;
mousePadPlugin.sendSingleClick();
}
}); });
return true; return true;
} }
@Override @Override
public boolean onDoubleTap(MotionEvent e) { public boolean onDoubleTap(MotionEvent e) {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
Device device = service.getDevice(deviceId); if (mousePadPlugin == null) return;
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class); mousePadPlugin.sendDoubleClick();
if (mousePadPlugin == null) return;
mousePadPlugin.sendDoubleClick();
}
}); });
return true; return true;
} }
@ -366,50 +351,38 @@ public class MousePadActivity extends AppCompatActivity implements GestureDetect
private void sendMiddleClick() { private void sendMiddleClick() {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
Device device = service.getDevice(deviceId); if (mousePadPlugin == null) return;
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class); mousePadPlugin.sendMiddleClick();
if (mousePadPlugin == null) return;
mousePadPlugin.sendMiddleClick();
}
}); });
} }
private void sendRightClick() { private void sendRightClick() {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
Device device = service.getDevice(deviceId); if (mousePadPlugin == null) return;
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class); mousePadPlugin.sendRightClick();
if (mousePadPlugin == null) return;
mousePadPlugin.sendRightClick();
}
}); });
} }
private void sendSingleHold() { private void sendSingleHold() {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
Device device = service.getDevice(deviceId); if (mousePadPlugin == null) return;
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class); mousePadPlugin.sendSingleHold();
if (mousePadPlugin == null) return;
mousePadPlugin.sendSingleHold();
}
}); });
} }
private void sendScroll(final float y) { private void sendScroll(final float y) {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class);
Device device = service.getDevice(deviceId); if (mousePadPlugin == null) return;
MousePadPlugin mousePadPlugin = device.getPlugin(MousePadPlugin.class); mousePadPlugin.sendScroll(0, y);
if (mousePadPlugin == null) return;
mousePadPlugin.sendScroll(0, y);
}
}); });
} }

View File

@ -78,105 +78,94 @@ public class MprisActivity extends AppCompatActivity {
protected void connectToPlugin(final String targetPlayerName) { protected void connectToPlugin(final String targetPlayerName) {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override
public void onServiceStart(BackgroundService service) {
final Device device = service.getDevice(deviceId);
final MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) {
Log.e("MprisActivity", "device has no mpris plugin!");
return;
}
targetPlayer = mpris.getPlayerStatus(targetPlayerName);
mpris.setPlayerStatusUpdatedHandler("activity", new Handler() {
@Override
public void handleMessage(Message msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
updatePlayerStatus(mpris);
}
});
}
});
mpris.setPlayerListUpdatedHandler("activity", new Handler() {
@Override
public void handleMessage(Message msg) {
final List<String> playerList = mpris.getPlayerList();
final ArrayAdapter<String> adapter = new ArrayAdapter<>(MprisActivity.this,
android.R.layout.simple_spinner_item,
playerList.toArray(new String[playerList.size()])
);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
runOnUiThread(new Runnable() {
@Override
public void run() {
Spinner spinner = (Spinner) findViewById(R.id.player_spinner);
//String prevPlayer = (String)spinner.getSelectedItem();
spinner.setAdapter(adapter);
if (playerList.isEmpty()) {
findViewById(R.id.no_players).setVisibility(View.VISIBLE);
spinner.setVisibility(View.GONE);
((TextView) findViewById(R.id.now_playing_textview)).setText("");
} else {
findViewById(R.id.no_players).setVisibility(View.GONE);
spinner.setVisibility(View.VISIBLE);
}
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int pos, long id) {
if (pos >= playerList.size()) return;
String player = playerList.get(pos);
if (targetPlayer != null && player.equals(targetPlayer.getPlayer())) {
return; //Player hasn't actually changed
}
targetPlayer = mpris.getPlayerStatus(player);
updatePlayerStatus(mpris);
if (targetPlayer.isPlaying()) {
MprisMediaSession.getInstance().playerSelected(targetPlayer);
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
targetPlayer = null;
}
});
if (targetPlayer == null) {
//If no player is selected, try to select a playing player
targetPlayer = mpris.getPlayingPlayer();
}
//Try to select the specified player
if (targetPlayer != null) {
int targetIndex = adapter.getPosition(targetPlayer.getPlayer());
if (targetIndex >= 0) {
spinner.setSelection(targetIndex);
} else {
targetPlayer = null;
}
}
//If no player selected, select the first one (if any)
if (targetPlayer == null && !playerList.isEmpty()) {
targetPlayer = mpris.getPlayerStatus(playerList.get(0));
spinner.setSelection(0);
}
updatePlayerStatus(mpris);
}
});
}
});
final Device device = service.getDevice(deviceId);
final MprisPlugin mpris = device.getPlugin(MprisPlugin.class);
if (mpris == null) {
Log.e("MprisActivity", "device has no mpris plugin!");
return;
} }
targetPlayer = mpris.getPlayerStatus(targetPlayerName);
mpris.setPlayerStatusUpdatedHandler("activity", new Handler() {
@Override
public void handleMessage(Message msg) {
runOnUiThread(() -> updatePlayerStatus(mpris));
}
});
mpris.setPlayerListUpdatedHandler("activity", new Handler() {
@Override
public void handleMessage(Message msg) {
final List<String> playerList = mpris.getPlayerList();
final ArrayAdapter<String> adapter = new ArrayAdapter<>(MprisActivity.this,
android.R.layout.simple_spinner_item,
playerList.toArray(new String[playerList.size()])
);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
runOnUiThread(() -> {
Spinner spinner = (Spinner) findViewById(R.id.player_spinner);
//String prevPlayer = (String)spinner.getSelectedItem();
spinner.setAdapter(adapter);
if (playerList.isEmpty()) {
findViewById(R.id.no_players).setVisibility(View.VISIBLE);
spinner.setVisibility(View.GONE);
((TextView) findViewById(R.id.now_playing_textview)).setText("");
} else {
findViewById(R.id.no_players).setVisibility(View.GONE);
spinner.setVisibility(View.VISIBLE);
}
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int pos, long id) {
if (pos >= playerList.size()) return;
String player = playerList.get(pos);
if (targetPlayer != null && player.equals(targetPlayer.getPlayer())) {
return; //Player hasn't actually changed
}
targetPlayer = mpris.getPlayerStatus(player);
updatePlayerStatus(mpris);
if (targetPlayer.isPlaying()) {
MprisMediaSession.getInstance().playerSelected(targetPlayer);
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
targetPlayer = null;
}
});
if (targetPlayer == null) {
//If no player is selected, try to select a playing player
targetPlayer = mpris.getPlayingPlayer();
}
//Try to select the specified player
if (targetPlayer != null) {
int targetIndex = adapter.getPosition(targetPlayer.getPlayer());
if (targetIndex >= 0) {
spinner.setSelection(targetIndex);
} else {
targetPlayer = null;
}
}
//If no player selected, select the first one (if any)
if (targetPlayer == null && !playerList.isEmpty()) {
targetPlayer = mpris.getPlayerStatus(playerList.get(0));
spinner.setSelection(0);
}
updatePlayerStatus(mpris);
});
}
});
}); });
} }
@ -196,12 +185,7 @@ public class MprisActivity extends AppCompatActivity {
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(MprisActivity.this, service -> service.removeConnectionListener(connectionReceiver));
@Override
public void onServiceStart(BackgroundService service) {
service.removeConnectionListener(connectionReceiver);
}
});
} }
private void updatePlayerStatus(MprisPlugin mpris) { private void updatePlayerStatus(MprisPlugin mpris) {
@ -327,78 +311,33 @@ public class MprisActivity extends AppCompatActivity {
getString(R.string.mpris_time_default)); getString(R.string.mpris_time_default));
final int interval_time = Integer.parseInt(interval_time_str); final int interval_time = Integer.parseInt(interval_time_str);
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(MprisActivity.this, service -> service.addConnectionListener(connectionReceiver));
@Override
public void onServiceStart(BackgroundService service) {
service.addConnectionListener(connectionReceiver);
}
});
connectToPlugin(targetPlayerName); connectToPlugin(targetPlayerName);
findViewById(R.id.play_button).setOnClickListener(new View.OnClickListener() { findViewById(R.id.play_button).setOnClickListener(view -> BackgroundService.RunCommand(MprisActivity.this, service -> {
@Override if (targetPlayer == null) return;
public void onClick(View view) { targetPlayer.playPause();
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { }));
@Override
public void onServiceStart(BackgroundService service) {
if (targetPlayer == null) return;
targetPlayer.playPause();
}
});
}
});
findViewById(R.id.prev_button).setOnClickListener(new View.OnClickListener() { findViewById(R.id.prev_button).setOnClickListener(view -> BackgroundService.RunCommand(MprisActivity.this, service -> {
@Override if (targetPlayer == null) return;
public void onClick(View view) { targetPlayer.previous();
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { }));
@Override
public void onServiceStart(BackgroundService service) {
if (targetPlayer == null) return;
targetPlayer.previous();
}
});
}
});
findViewById(R.id.rew_button).setOnClickListener(new View.OnClickListener() { findViewById(R.id.rew_button).setOnClickListener(view -> BackgroundService.RunCommand(MprisActivity.this, service -> {
@Override if (targetPlayer == null) return;
public void onClick(View view) { targetPlayer.seek(interval_time * -1);
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { }));
@Override
public void onServiceStart(BackgroundService service) {
if (targetPlayer == null) return;
targetPlayer.seek(interval_time * -1);
}
});
}
});
findViewById(R.id.ff_button).setOnClickListener(new View.OnClickListener() { findViewById(R.id.ff_button).setOnClickListener(view -> BackgroundService.RunCommand(MprisActivity.this, service -> {
@Override if (targetPlayer == null) return;
public void onClick(View view) { targetPlayer.seek(interval_time);
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { }));
@Override
public void onServiceStart(BackgroundService service) {
if (targetPlayer == null) return;
targetPlayer.seek(interval_time);
}
});
}
});
findViewById(R.id.next_button).setOnClickListener(new View.OnClickListener() { findViewById(R.id.next_button).setOnClickListener(view -> BackgroundService.RunCommand(MprisActivity.this, service -> {
@Override if (targetPlayer == null) return;
public void onClick(View view) { targetPlayer.next();
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { }));
@Override
public void onServiceStart(BackgroundService service) {
if (targetPlayer == null) return;
targetPlayer.next();
}
});
}
});
((SeekBar) findViewById(R.id.volume_seek)).setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { ((SeekBar) findViewById(R.id.volume_seek)).setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override @Override
@ -411,33 +350,23 @@ public class MprisActivity extends AppCompatActivity {
@Override @Override
public void onStopTrackingTouch(final SeekBar seekBar) { public void onStopTrackingTouch(final SeekBar seekBar) {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(MprisActivity.this, service -> {
@Override if (targetPlayer == null) return;
public void onServiceStart(BackgroundService service) { targetPlayer.setVolume(seekBar.getProgress());
if (targetPlayer == null) return;
targetPlayer.setVolume(seekBar.getProgress());
}
}); });
} }
}); });
positionSeekUpdateRunnable = new Runnable() { positionSeekUpdateRunnable = () -> {
@Override final SeekBar positionSeek = (SeekBar) findViewById(R.id.positionSeek);
public void run() { BackgroundService.RunCommand(MprisActivity.this, service -> {
final SeekBar positionSeek = (SeekBar) findViewById(R.id.positionSeek); if (targetPlayer != null) {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { positionSeek.setProgress((int) (targetPlayer.getPosition()));
@Override }
public void onServiceStart(BackgroundService service) { positionSeekUpdateHandler.removeCallbacks(positionSeekUpdateRunnable);
if (targetPlayer != null) { positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 1000);
positionSeek.setProgress((int) (targetPlayer.getPosition())); });
}
positionSeekUpdateHandler.removeCallbacks(positionSeekUpdateRunnable);
positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 1000);
}
});
}
}; };
positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 200); positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 200);
@ -454,14 +383,11 @@ public class MprisActivity extends AppCompatActivity {
@Override @Override
public void onStopTrackingTouch(final SeekBar seekBar) { public void onStopTrackingTouch(final SeekBar seekBar) {
BackgroundService.RunCommand(MprisActivity.this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(MprisActivity.this, service -> {
@Override if (targetPlayer != null) {
public void onServiceStart(BackgroundService service) { targetPlayer.setPosition(seekBar.getProgress());
if (targetPlayer != null) {
targetPlayer.setPosition(seekBar.getProgress());
}
positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 200);
} }
positionSeekUpdateHandler.postDelayed(positionSeekUpdateRunnable, 200);
}); });
} }

View File

@ -211,190 +211,187 @@ public class MprisMediaSession implements SharedPreferences.OnSharedPreferenceCh
* Update the media control notification * Update the media control notification
*/ */
private void updateMediaNotification() { private void updateMediaNotification() {
BackgroundService.RunCommand(context, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(context, service -> {
@Override //If the user disabled the media notification, do not show it
public void onServiceStart(BackgroundService service) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
//If the user disabled the media notification, do not show it if (!prefs.getBoolean(context.getString(R.string.mpris_notification_key), true)) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); closeMediaNotification();
if (!prefs.getBoolean(context.getString(R.string.mpris_notification_key), true)) { return;
closeMediaNotification();
return;
}
//Make sure our information is up-to-date
updateCurrentPlayer(service);
//If the player disappeared (and no other playing one found), just remove the notification
if (notificationPlayer == null) {
closeMediaNotification();
return;
}
//Update the metadata and playback status
if (mediaSession == null) {
mediaSession = new MediaSessionCompat(context, MPRIS_MEDIA_SESSION_TAG);
mediaSession.setCallback(mediaSessionCallback);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
}
MediaMetadataCompat.Builder metadata = new MediaMetadataCompat.Builder();
//Fallback because older KDE connect versions do not support getTitle()
if (!notificationPlayer.getTitle().isEmpty()) {
metadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, notificationPlayer.getTitle());
} else {
metadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, notificationPlayer.getCurrentSong());
}
if (!notificationPlayer.getArtist().isEmpty()) {
metadata.putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, notificationPlayer.getArtist());
}
if (!notificationPlayer.getAlbum().isEmpty()) {
metadata.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, notificationPlayer.getAlbum());
}
if (notificationPlayer.getLength() > 0) {
metadata.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, notificationPlayer.getLength());
}
Bitmap albumArt = notificationPlayer.getAlbumArt();
if (albumArt != null) {
metadata.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt);
}
mediaSession.setMetadata(metadata.build());
PlaybackStateCompat.Builder playbackState = new PlaybackStateCompat.Builder();
if (notificationPlayer.isPlaying()) {
playbackState.setState(PlaybackStateCompat.STATE_PLAYING, notificationPlayer.getPosition(), 1.0f);
} else {
playbackState.setState(PlaybackStateCompat.STATE_PAUSED, notificationPlayer.getPosition(), 0.0f);
}
//Create all actions (previous/play/pause/next)
Intent iPlay = new Intent(service, MprisMediaNotificationReceiver.class);
iPlay.setAction(MprisMediaNotificationReceiver.ACTION_PLAY);
iPlay.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iPlay.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piPlay = PendingIntent.getBroadcast(service, 0, iPlay, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aPlay = new NotificationCompat.Action.Builder(
R.drawable.ic_play_white, service.getString(R.string.mpris_play), piPlay);
Intent iPause = new Intent(service, MprisMediaNotificationReceiver.class);
iPause.setAction(MprisMediaNotificationReceiver.ACTION_PAUSE);
iPause.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iPause.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piPause = PendingIntent.getBroadcast(service, 0, iPause, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aPause = new NotificationCompat.Action.Builder(
R.drawable.ic_pause_white, service.getString(R.string.mpris_pause), piPause);
Intent iPrevious = new Intent(service, MprisMediaNotificationReceiver.class);
iPrevious.setAction(MprisMediaNotificationReceiver.ACTION_PREVIOUS);
iPrevious.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iPrevious.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piPrevious = PendingIntent.getBroadcast(service, 0, iPrevious, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aPrevious = new NotificationCompat.Action.Builder(
R.drawable.ic_previous_white, service.getString(R.string.mpris_previous), piPrevious);
Intent iNext = new Intent(service, MprisMediaNotificationReceiver.class);
iNext.setAction(MprisMediaNotificationReceiver.ACTION_NEXT);
iNext.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iNext.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piNext = PendingIntent.getBroadcast(service, 0, iNext, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aNext = new NotificationCompat.Action.Builder(
R.drawable.ic_next_white, service.getString(R.string.mpris_next), piNext);
Intent iOpenActivity = new Intent(service, MprisActivity.class);
iOpenActivity.putExtra("deviceId", notificationDevice);
iOpenActivity.putExtra("player", notificationPlayer.getPlayer());
PendingIntent piOpenActivity = PendingIntent.getActivity(service, 0, iOpenActivity, PendingIntent.FLAG_UPDATE_CURRENT);
//Create the notification
final NotificationCompat.Builder notification = new NotificationCompat.Builder(service);
notification
.setAutoCancel(false)
.setContentIntent(piOpenActivity)
.setSmallIcon(R.drawable.ic_play_white)
.setShowWhen(false)
.setColor(service.getResources().getColor(R.color.primary))
.setVisibility(android.support.v4.app.NotificationCompat.VISIBILITY_PUBLIC);
if (!notificationPlayer.getTitle().isEmpty()) {
notification.setContentTitle(notificationPlayer.getTitle());
} else {
notification.setContentTitle(notificationPlayer.getCurrentSong());
}
//Only set the notification body text if we have an author and/or album
if (!notificationPlayer.getArtist().isEmpty() && !notificationPlayer.getAlbum().isEmpty()) {
notification.setContentText(notificationPlayer.getArtist() + " - " + notificationPlayer.getAlbum() + " (" + notificationPlayer.getPlayer() + ")");
} else if (!notificationPlayer.getArtist().isEmpty()) {
notification.setContentText(notificationPlayer.getArtist() + " (" + notificationPlayer.getPlayer() + ")");
} else if (!notificationPlayer.getAlbum().isEmpty()) {
notification.setContentText(notificationPlayer.getAlbum() + " (" + notificationPlayer.getPlayer() + ")");
} else {
notification.setContentText(notificationPlayer.getPlayer());
}
if (albumArt != null) {
notification.setLargeIcon(albumArt);
}
if (!notificationPlayer.isPlaying()) {
Intent iCloseNotification = new Intent(service, MprisMediaNotificationReceiver.class);
iCloseNotification.setAction(MprisMediaNotificationReceiver.ACTION_CLOSE_NOTIFICATION);
iCloseNotification.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iCloseNotification.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piCloseNotification = PendingIntent.getActivity(service, 0, iCloseNotification, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setDeleteIntent(piCloseNotification);
}
//Add media control actions
int numActions = 0;
long playbackActions = 0;
if (notificationPlayer.isGoPreviousAllowed()) {
notification.addAction(aPrevious.build());
playbackActions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
++numActions;
}
if (notificationPlayer.isPlaying() && notificationPlayer.isPauseAllowed()) {
notification.addAction(aPause.build());
playbackActions |= PlaybackStateCompat.ACTION_PAUSE;
++numActions;
}
if (!notificationPlayer.isPlaying() && notificationPlayer.isPlayAllowed()) {
notification.addAction(aPlay.build());
playbackActions |= PlaybackStateCompat.ACTION_PLAY;
++numActions;
}
if (notificationPlayer.isGoNextAllowed()) {
notification.addAction(aNext.build());
playbackActions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
++numActions;
}
playbackState.setActions(playbackActions);
mediaSession.setPlaybackState(playbackState.build());
//Only allow deletion if no music is notificationPlayer
if (notificationPlayer.isPlaying()) {
notification.setOngoing(true);
} else {
notification.setOngoing(false);
}
//Use the MediaStyle notification, so it feels like other media players. That also allows adding actions
NotificationCompat.MediaStyle mediaStyle = new NotificationCompat.MediaStyle();
if (numActions == 1) {
mediaStyle.setShowActionsInCompactView(0);
} else if (numActions == 2) {
mediaStyle.setShowActionsInCompactView(0, 1);
} else if (numActions >= 3) {
mediaStyle.setShowActionsInCompactView(0, 1, 2);
}
mediaStyle.setMediaSession(mediaSession.getSessionToken());
notification.setStyle(mediaStyle);
//Display the notification
mediaSession.setActive(true);
final NotificationManager nm = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(MPRIS_MEDIA_NOTIFICATION_ID, notification.build());
} }
//Make sure our information is up-to-date
updateCurrentPlayer(service);
//If the player disappeared (and no other playing one found), just remove the notification
if (notificationPlayer == null) {
closeMediaNotification();
return;
}
//Update the metadata and playback status
if (mediaSession == null) {
mediaSession = new MediaSessionCompat(context, MPRIS_MEDIA_SESSION_TAG);
mediaSession.setCallback(mediaSessionCallback);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
}
MediaMetadataCompat.Builder metadata = new MediaMetadataCompat.Builder();
//Fallback because older KDE connect versions do not support getTitle()
if (!notificationPlayer.getTitle().isEmpty()) {
metadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, notificationPlayer.getTitle());
} else {
metadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, notificationPlayer.getCurrentSong());
}
if (!notificationPlayer.getArtist().isEmpty()) {
metadata.putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, notificationPlayer.getArtist());
}
if (!notificationPlayer.getAlbum().isEmpty()) {
metadata.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, notificationPlayer.getAlbum());
}
if (notificationPlayer.getLength() > 0) {
metadata.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, notificationPlayer.getLength());
}
Bitmap albumArt = notificationPlayer.getAlbumArt();
if (albumArt != null) {
metadata.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt);
}
mediaSession.setMetadata(metadata.build());
PlaybackStateCompat.Builder playbackState = new PlaybackStateCompat.Builder();
if (notificationPlayer.isPlaying()) {
playbackState.setState(PlaybackStateCompat.STATE_PLAYING, notificationPlayer.getPosition(), 1.0f);
} else {
playbackState.setState(PlaybackStateCompat.STATE_PAUSED, notificationPlayer.getPosition(), 0.0f);
}
//Create all actions (previous/play/pause/next)
Intent iPlay = new Intent(service, MprisMediaNotificationReceiver.class);
iPlay.setAction(MprisMediaNotificationReceiver.ACTION_PLAY);
iPlay.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iPlay.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piPlay = PendingIntent.getBroadcast(service, 0, iPlay, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aPlay = new NotificationCompat.Action.Builder(
R.drawable.ic_play_white, service.getString(R.string.mpris_play), piPlay);
Intent iPause = new Intent(service, MprisMediaNotificationReceiver.class);
iPause.setAction(MprisMediaNotificationReceiver.ACTION_PAUSE);
iPause.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iPause.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piPause = PendingIntent.getBroadcast(service, 0, iPause, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aPause = new NotificationCompat.Action.Builder(
R.drawable.ic_pause_white, service.getString(R.string.mpris_pause), piPause);
Intent iPrevious = new Intent(service, MprisMediaNotificationReceiver.class);
iPrevious.setAction(MprisMediaNotificationReceiver.ACTION_PREVIOUS);
iPrevious.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iPrevious.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piPrevious = PendingIntent.getBroadcast(service, 0, iPrevious, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aPrevious = new NotificationCompat.Action.Builder(
R.drawable.ic_previous_white, service.getString(R.string.mpris_previous), piPrevious);
Intent iNext = new Intent(service, MprisMediaNotificationReceiver.class);
iNext.setAction(MprisMediaNotificationReceiver.ACTION_NEXT);
iNext.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iNext.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piNext = PendingIntent.getBroadcast(service, 0, iNext, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder aNext = new NotificationCompat.Action.Builder(
R.drawable.ic_next_white, service.getString(R.string.mpris_next), piNext);
Intent iOpenActivity = new Intent(service, MprisActivity.class);
iOpenActivity.putExtra("deviceId", notificationDevice);
iOpenActivity.putExtra("player", notificationPlayer.getPlayer());
PendingIntent piOpenActivity = PendingIntent.getActivity(service, 0, iOpenActivity, PendingIntent.FLAG_UPDATE_CURRENT);
//Create the notification
final NotificationCompat.Builder notification = new NotificationCompat.Builder(service);
notification
.setAutoCancel(false)
.setContentIntent(piOpenActivity)
.setSmallIcon(R.drawable.ic_play_white)
.setShowWhen(false)
.setColor(service.getResources().getColor(R.color.primary))
.setVisibility(android.support.v4.app.NotificationCompat.VISIBILITY_PUBLIC);
if (!notificationPlayer.getTitle().isEmpty()) {
notification.setContentTitle(notificationPlayer.getTitle());
} else {
notification.setContentTitle(notificationPlayer.getCurrentSong());
}
//Only set the notification body text if we have an author and/or album
if (!notificationPlayer.getArtist().isEmpty() && !notificationPlayer.getAlbum().isEmpty()) {
notification.setContentText(notificationPlayer.getArtist() + " - " + notificationPlayer.getAlbum() + " (" + notificationPlayer.getPlayer() + ")");
} else if (!notificationPlayer.getArtist().isEmpty()) {
notification.setContentText(notificationPlayer.getArtist() + " (" + notificationPlayer.getPlayer() + ")");
} else if (!notificationPlayer.getAlbum().isEmpty()) {
notification.setContentText(notificationPlayer.getAlbum() + " (" + notificationPlayer.getPlayer() + ")");
} else {
notification.setContentText(notificationPlayer.getPlayer());
}
if (albumArt != null) {
notification.setLargeIcon(albumArt);
}
if (!notificationPlayer.isPlaying()) {
Intent iCloseNotification = new Intent(service, MprisMediaNotificationReceiver.class);
iCloseNotification.setAction(MprisMediaNotificationReceiver.ACTION_CLOSE_NOTIFICATION);
iCloseNotification.putExtra(MprisMediaNotificationReceiver.EXTRA_DEVICE_ID, notificationDevice);
iCloseNotification.putExtra(MprisMediaNotificationReceiver.EXTRA_MPRIS_PLAYER, notificationPlayer.getPlayer());
PendingIntent piCloseNotification = PendingIntent.getActivity(service, 0, iCloseNotification, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setDeleteIntent(piCloseNotification);
}
//Add media control actions
int numActions = 0;
long playbackActions = 0;
if (notificationPlayer.isGoPreviousAllowed()) {
notification.addAction(aPrevious.build());
playbackActions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
++numActions;
}
if (notificationPlayer.isPlaying() && notificationPlayer.isPauseAllowed()) {
notification.addAction(aPause.build());
playbackActions |= PlaybackStateCompat.ACTION_PAUSE;
++numActions;
}
if (!notificationPlayer.isPlaying() && notificationPlayer.isPlayAllowed()) {
notification.addAction(aPlay.build());
playbackActions |= PlaybackStateCompat.ACTION_PLAY;
++numActions;
}
if (notificationPlayer.isGoNextAllowed()) {
notification.addAction(aNext.build());
playbackActions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
++numActions;
}
playbackState.setActions(playbackActions);
mediaSession.setPlaybackState(playbackState.build());
//Only allow deletion if no music is notificationPlayer
if (notificationPlayer.isPlaying()) {
notification.setOngoing(true);
} else {
notification.setOngoing(false);
}
//Use the MediaStyle notification, so it feels like other media players. That also allows adding actions
NotificationCompat.MediaStyle mediaStyle = new NotificationCompat.MediaStyle();
if (numActions == 1) {
mediaStyle.setShowActionsInCompactView(0);
} else if (numActions == 2) {
mediaStyle.setShowActionsInCompactView(0, 1);
} else if (numActions >= 3) {
mediaStyle.setShowActionsInCompactView(0, 1, 2);
}
mediaStyle.setMediaSession(mediaSession.getSessionToken());
notification.setStyle(mediaStyle);
//Display the notification
mediaSession.setActive(true);
final NotificationManager nm = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(MPRIS_MEDIA_NOTIFICATION_ID, notification.build());
}); });
} }

View File

@ -98,38 +98,25 @@ public class NotificationFilterActivity extends AppCompatActivity {
setContentView(R.layout.activity_notification_filter); setContentView(R.layout.activity_notification_filter);
appDatabase = new AppDatabase(NotificationFilterActivity.this, false); appDatabase = new AppDatabase(NotificationFilterActivity.this, false);
new Thread(new Runnable() { new Thread(() -> {
@Override
public void run() {
PackageManager packageManager = getPackageManager(); PackageManager packageManager = getPackageManager();
List<ApplicationInfo> appList = packageManager.getInstalledApplications(0); List<ApplicationInfo> appList = packageManager.getInstalledApplications(0);
int count = appList.size(); int count = appList.size();
apps = new AppListInfo[count]; apps = new AppListInfo[count];
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
ApplicationInfo appInfo = appList.get(i); ApplicationInfo appInfo = appList.get(i);
apps[i] = new AppListInfo(); apps[i] = new AppListInfo();
apps[i].pkg = appInfo.packageName; apps[i].pkg = appInfo.packageName;
apps[i].name = appInfo.loadLabel(packageManager).toString(); apps[i].name = appInfo.loadLabel(packageManager).toString();
apps[i].icon = resizeIcon(appInfo.loadIcon(packageManager), 48); apps[i].icon = resizeIcon(appInfo.loadIcon(packageManager), 48);
apps[i].isEnabled = appDatabase.isEnabled(appInfo.packageName); apps[i].isEnabled = appDatabase.isEnabled(appInfo.packageName);
}
Arrays.sort(apps, new Comparator<AppListInfo>() {
@Override
public int compare(AppListInfo lhs, AppListInfo rhs) {
return StringsHelper.compare(lhs.name, rhs.name);
}
});
runOnUiThread(new Runnable() {
@Override
public void run() {
displayAppList();
}
});
} }
Arrays.sort(apps, (lhs, rhs) -> StringsHelper.compare(lhs.name, rhs.name));
runOnUiThread(this::displayAppList);
}).start(); }).start();
} }
@ -140,13 +127,10 @@ public class NotificationFilterActivity extends AppCompatActivity {
AppListAdapter adapter = new AppListAdapter(); AppListAdapter adapter = new AppListAdapter();
listView.setAdapter(adapter); listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { listView.setOnItemClickListener((adapterView, view, i, l) -> {
@Override boolean checked = listView.isItemChecked(i);
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { appDatabase.setEnabled(apps[i].pkg, checked);
boolean checked = listView.isItemChecked(i); apps[i].isEnabled = checked;
appDatabase.setEnabled(apps[i].pkg, checked);
apps[i].isEnabled = checked;
}
}); });
for (int i = 0; i < apps.length; i++) { for (int i = 0; i < apps.length; i++) {

View File

@ -108,17 +108,14 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
appDatabase = new AppDatabase(context, true); appDatabase = new AppDatabase(context, true);
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() { NotificationReceiver.RunCommand(context, service -> {
@Override
public void onServiceStart(NotificationReceiver service) {
service.addListener(NotificationsPlugin.this); service.addListener(NotificationsPlugin.this);
serviceReady = service.isConnected(); serviceReady = service.isConnected();
if (serviceReady) { if (serviceReady) {
sendCurrentNotifications(service); sendCurrentNotifications(service);
}
} }
}); });
@ -128,12 +125,7 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
@Override @Override
public void onDestroy() { public void onDestroy() {
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() { NotificationReceiver.RunCommand(context, service -> service.removeListener(NotificationsPlugin.this));
@Override
public void onServiceStart(NotificationReceiver service) {
service.removeListener(NotificationsPlugin.this);
}
});
} }
@Override @Override
@ -461,22 +453,14 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
if (np.getBoolean("request")) { if (np.getBoolean("request")) {
if (serviceReady) { if (serviceReady) {
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() { NotificationReceiver.RunCommand(context, this::sendCurrentNotifications);
@Override
public void onServiceStart(NotificationReceiver service) {
sendCurrentNotifications(service);
}
});
} }
} else if (np.has("cancel")) { } else if (np.has("cancel")) {
NotificationReceiver.RunCommand(context, new NotificationReceiver.InstanceCallback() { NotificationReceiver.RunCommand(context, service -> {
@Override String dismissedId = np.getString("cancel");
public void onServiceStart(NotificationReceiver service) { cancelNotificationCompat(service, dismissedId);
String dismissedId = np.getString("cancel");
cancelNotificationCompat(service, dismissedId);
}
}); });
} else if (np.has("requestReplyId") && np.has("message")) { } else if (np.has("requestReplyId") && np.has("message")) {
@ -497,18 +481,12 @@ public class NotificationsPlugin extends Plugin implements NotificationReceiver.
return new AlertDialog.Builder(deviceActivity) return new AlertDialog.Builder(deviceActivity)
.setTitle(R.string.pref_plugin_notifications) .setTitle(R.string.pref_plugin_notifications)
.setMessage(R.string.no_permissions) .setMessage(R.string.no_permissions)
.setPositiveButton(R.string.open_settings, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.open_settings, (dialogInterface, i) -> {
@Override Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
public void onClick(DialogInterface dialogInterface, int i) { deviceActivity.startActivityForResult(intent, MainActivity.RESULT_NEEDS_RELOAD);
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
deviceActivity.startActivityForResult(intent, MainActivity.RESULT_NEEDS_RELOAD);
}
}) })
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { .setNegativeButton(R.string.cancel, (dialogInterface, i) -> {
@Override //Do nothing
public void onClick(DialogInterface dialogInterface, int i) {
//Do nothing
}
}) })
.create(); .create();

View File

@ -202,12 +202,7 @@ public abstract class Plugin {
if (!hasMainActivity()) return null; if (!hasMainActivity()) return null;
Button b = new Button(activity); Button b = new Button(activity);
b.setText(getActionName()); b.setText(getActionName());
b.setOnClickListener(new View.OnClickListener() { b.setOnClickListener(view -> startMainActivity(activity));
@Override
public void onClick(View view) {
startMainActivity(activity);
}
});
return b; return b;
} }
@ -242,17 +237,9 @@ public abstract class Plugin {
return new AlertDialog.Builder(activity) return new AlertDialog.Builder(activity)
.setTitle(getDisplayName()) .setTitle(getDisplayName())
.setMessage(reason) .setMessage(reason)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.ok, (dialogInterface, i) -> ActivityCompat.requestPermissions(activity, permissions, 0))
@Override .setNegativeButton(R.string.cancel, (dialogInterface, i) -> {
public void onClick(DialogInterface dialogInterface, int i) { //Do nothing
ActivityCompat.requestPermissions(activity, permissions, 0);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//Do nothing
}
}) })
.create(); .create();
} }

View File

@ -121,12 +121,7 @@ public class RemoteKeyboardPlugin extends Plugin {
releaseInstances(); releaseInstances();
} }
if (RemoteKeyboardService.instance != null) if (RemoteKeyboardService.instance != null)
RemoteKeyboardService.instance.handler.post(new Runnable() { RemoteKeyboardService.instance.handler.post(() -> RemoteKeyboardService.instance.updateInputView());
@Override
public void run() {
RemoteKeyboardService.instance.updateInputView();
}
});
return true; return true;
} }
@ -137,12 +132,7 @@ public class RemoteKeyboardPlugin extends Plugin {
if (instances.contains(this)) { if (instances.contains(this)) {
instances.remove(this); instances.remove(this);
if (instances.size() < 1 && RemoteKeyboardService.instance != null) if (instances.size() < 1 && RemoteKeyboardService.instance != null)
RemoteKeyboardService.instance.handler.post(new Runnable() { RemoteKeyboardService.instance.handler.post(() -> RemoteKeyboardService.instance.updateInputView());
@Override
public void run() {
RemoteKeyboardService.instance.updateInputView();
}
});
} }
} finally { } finally {
releaseInstances(); releaseInstances();

View File

@ -35,21 +35,17 @@ public class AddCommandDialog extends DialogFragment {
builder.setView(view); builder.setView(view);
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { builder.setPositiveButton(R.string.ok, (dialog, id) -> {
public void onClick(DialogInterface dialog, int id) {
if (getActivity() instanceof RunCommandActivity) { if (getActivity() instanceof RunCommandActivity) {
String name = nameField.getText().toString(); String name = nameField.getText().toString();
String command = commandField.getText().toString(); String command = commandField.getText().toString();
((RunCommandActivity) getActivity()).dialogResult(name, command); ((RunCommandActivity) getActivity()).dialogResult(name, command);
}
} }
}); });
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { builder.setNegativeButton(R.string.cancel, (dialog, id) -> {
public void onClick(DialogInterface dialog, int id) {
}
}); });
return builder.create(); return builder.create();

View File

@ -45,71 +45,54 @@ import java.util.Comparator;
public class RunCommandActivity extends AppCompatActivity { public class RunCommandActivity extends AppCompatActivity {
private String deviceId; private String deviceId;
private final RunCommandPlugin.CommandsChangedCallback commandsChangedCallback = new RunCommandPlugin.CommandsChangedCallback() { private final RunCommandPlugin.CommandsChangedCallback commandsChangedCallback = this::updateView;
@Override
public void update() {
updateView();
}
};
private void updateView() { private void updateView() {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override
public void onServiceStart(final BackgroundService service) {
final Device device = service.getDevice(deviceId); final Device device = service.getDevice(deviceId);
final RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class); final RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class);
if (plugin == null) { if (plugin == null) {
Log.e("RunCommandActivity", "device has no runcommand plugin!"); Log.e("RunCommandActivity", "device has no runcommand plugin!");
return; return;
}
runOnUiThread(() -> {
ListView view = (ListView) findViewById(R.id.runcommandslist);
final ArrayList<ListAdapter.Item> commandItems = new ArrayList<>();
for (JSONObject obj : plugin.getCommandList()) {
try {
commandItems.add(new CommandEntry(obj.getString("name"),
obj.getString("command"), obj.getString("key")));
} catch (JSONException e) {
e.printStackTrace();
}
} }
runOnUiThread(new Runnable() { Collections.sort(commandItems, (lhs, rhs) -> {
@Override String lName = ((CommandEntry) lhs).getName();
public void run() { String rName = ((CommandEntry) rhs).getName();
ListView view = (ListView) findViewById(R.id.runcommandslist); return lName.compareTo(rName);
final ArrayList<ListAdapter.Item> commandItems = new ArrayList<>();
for (JSONObject obj : plugin.getCommandList()) {
try {
commandItems.add(new CommandEntry(obj.getString("name"),
obj.getString("command"), obj.getString("key")));
} catch (JSONException e) {
e.printStackTrace();
}
}
Collections.sort(commandItems, new Comparator<ListAdapter.Item>() {
@Override
public int compare(ListAdapter.Item lhs, ListAdapter.Item rhs) {
String lName = ((CommandEntry) lhs).getName();
String rName = ((CommandEntry) rhs).getName();
return lName.compareTo(rName);
}
});
ListAdapter adapter = new ListAdapter(RunCommandActivity.this, commandItems);
view.setAdapter(adapter);
view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
CommandEntry entry = (CommandEntry) commandItems.get(i);
plugin.runCommand(entry.getKey());
}
});
TextView explanation = (TextView) findViewById(R.id.addcomand_explanation);
String text = getString(R.string.addcommand_explanation);
if (!plugin.canAddCommand()) {
text += "\n" + getString(R.string.addcommand_explanation2);
}
explanation.setText(text);
explanation.setVisibility(commandItems.isEmpty() ? View.VISIBLE : View.GONE);
}
}); });
}
ListAdapter adapter = new ListAdapter(RunCommandActivity.this, commandItems);
view.setAdapter(adapter);
view.setOnItemClickListener((adapterView, view1, i, l) -> {
CommandEntry entry = (CommandEntry) commandItems.get(i);
plugin.runCommand(entry.getKey());
});
TextView explanation = (TextView) findViewById(R.id.addcomand_explanation);
String text = getString(R.string.addcommand_explanation);
if (!plugin.canAddCommand()) {
text += "\n" + getString(R.string.addcommand_explanation2);
}
explanation.setText(text);
explanation.setVisibility(commandItems.isEmpty() ? View.VISIBLE : View.GONE);
});
}); });
} }
@ -125,12 +108,7 @@ public class RunCommandActivity extends AppCompatActivity {
FloatingActionButton addCommandButton = (FloatingActionButton) findViewById(R.id.add_command_button); FloatingActionButton addCommandButton = (FloatingActionButton) findViewById(R.id.add_command_button);
addCommandButton.setVisibility(canAddCommands ? View.VISIBLE : View.GONE); addCommandButton.setVisibility(canAddCommands ? View.VISIBLE : View.GONE);
addCommandButton.setOnClickListener(new View.OnClickListener() { addCommandButton.setOnClickListener(view -> new AddCommandDialog().show(getSupportFragmentManager(), "addcommanddialog"));
@Override
public void onClick(View view) {
new AddCommandDialog().show(getSupportFragmentManager(), "addcommanddialog");
}
});
updateView(); updateView();
} }
@ -139,18 +117,15 @@ public class RunCommandActivity extends AppCompatActivity {
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override
public void onServiceStart(final BackgroundService service) {
final Device device = service.getDevice(deviceId); final Device device = service.getDevice(deviceId);
final RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class); final RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class);
if (plugin == null) { if (plugin == null) {
Log.e("RunCommandActivity", "device has no runcommand plugin!"); Log.e("RunCommandActivity", "device has no runcommand plugin!");
return; return;
}
plugin.addCommandsUpdatedCallback(commandsChangedCallback);
} }
plugin.addCommandsUpdatedCallback(commandsChangedCallback);
}); });
} }
@ -158,30 +133,24 @@ public class RunCommandActivity extends AppCompatActivity {
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override
public void onServiceStart(final BackgroundService service) {
final Device device = service.getDevice(deviceId); final Device device = service.getDevice(deviceId);
final RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class); final RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class);
if (plugin == null) { if (plugin == null) {
Log.e("RunCommandActivity", "device has no runcommand plugin!"); Log.e("RunCommandActivity", "device has no runcommand plugin!");
return; return;
}
plugin.removeCommandsUpdatedCallback(commandsChangedCallback);
} }
plugin.removeCommandsUpdatedCallback(commandsChangedCallback);
}); });
} }
public void dialogResult(final String cmdName, final String cmdCmd) { public void dialogResult(final String cmdName, final String cmdCmd) {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class);
Device device = service.getDevice(deviceId); if(!cmdName.isEmpty() && !cmdCmd.isEmpty()) {
RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class); plugin.addCommand(cmdName, cmdCmd);
if(!cmdName.isEmpty() && !cmdCmd.isEmpty()) {
plugin.addCommand(cmdName, cmdCmd);
}
} }
}); });
} }

View File

@ -89,17 +89,14 @@ public class SendFileActivity extends AppCompatActivity {
if (uris.isEmpty()) { if (uris.isEmpty()) {
Log.w("SendFileActivity", "No files to send?"); Log.w("SendFileActivity", "No files to send?");
} else { } else {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(mDeviceId);
public void onServiceStart(BackgroundService service) { if (device == null) {
Device device = service.getDevice(mDeviceId); Log.e("SendFileActivity", "Device is null");
if (device == null) { finish();
Log.e("SendFileActivity", "Device is null"); return;
finish();
return;
}
SharePlugin.queuedSendUriList(getApplicationContext(), device, uris);
} }
SharePlugin.queuedSendUriList(getApplicationContext(), device, uris);
}); });
} }
} }

View File

@ -15,8 +15,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.kde.kdeconnect.Plugins.SharePlugin; package org.kde.kdeconnect.Plugins.SharePlugin;
@ -70,28 +70,15 @@ public class ShareActivity extends AppCompatActivity {
private void updateComputerListAction() { private void updateComputerListAction() {
updateComputerList(); updateComputerList();
BackgroundService.RunCommand(ShareActivity.this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(ShareActivity.this, BackgroundService::onNetworkChange);
@Override
public void onServiceStart(BackgroundService service) {
service.onNetworkChange();
}
});
mSwipeRefreshLayout.setRefreshing(true); mSwipeRefreshLayout.setRefreshing(true);
new Thread(new Runnable() { new Thread(() -> {
@Override try {
public void run() { Thread.sleep(1500);
try { } catch (InterruptedException ignored) {
Thread.sleep(1500);
} catch (InterruptedException ignored) {
}
runOnUiThread(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
}
});
} }
runOnUiThread(() -> mSwipeRefreshLayout.setRefreshing(false));
}).start(); }).start();
} }
@ -105,41 +92,32 @@ public class ShareActivity extends AppCompatActivity {
return; return;
} }
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override
public void onServiceStart(final BackgroundService service) {
Collection<Device> devices = service.getDevices().values(); Collection<Device> devices = service.getDevices().values();
final ArrayList<Device> devicesList = new ArrayList<>(); final ArrayList<Device> devicesList = new ArrayList<>();
final ArrayList<ListAdapter.Item> items = new ArrayList<>(); final ArrayList<ListAdapter.Item> items = new ArrayList<>();
items.add(new SectionItem(getString(R.string.share_to))); items.add(new SectionItem(getString(R.string.share_to)));
for (Device d : devices) { for (Device d : devices) {
if (d.isReachable() && d.isPaired()) { if (d.isReachable() && d.isPaired()) {
devicesList.add(d); devicesList.add(d);
items.add(new EntryItem(d.getName())); items.add(new EntryItem(d.getName()));
}
} }
runOnUiThread(new Runnable() {
@Override
public void run() {
ListView list = (ListView) findViewById(R.id.devices_list);
list.setAdapter(new ListAdapter(ShareActivity.this, items));
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Device device = devicesList.get(i - 1); //NOTE: -1 because of the title!
SharePlugin.share(intent, device);
finish();
}
});
}
});
} }
runOnUiThread(() -> {
ListView list = (ListView) findViewById(R.id.devices_list);
list.setAdapter(new ListAdapter(ShareActivity.this, items));
list.setOnItemClickListener((adapterView, view, i, l) -> {
Device device = devicesList.get(i - 1); //NOTE: -1 because of the title!
SharePlugin.share(intent, device);
finish();
});
});
}); });
} }
@ -154,12 +132,7 @@ public class ShareActivity extends AppCompatActivity {
ActionBar actionBar = getSupportActionBar(); ActionBar actionBar = getSupportActionBar();
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_list_layout); mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_list_layout);
mSwipeRefreshLayout.setOnRefreshListener( mSwipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() { this::updateComputerListAction
@Override
public void onRefresh() {
updateComputerListAction();
}
}
); );
if (actionBar != null) { if (actionBar != null) {
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM); actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
@ -176,32 +149,20 @@ public class ShareActivity extends AppCompatActivity {
if (deviceId != null) { if (deviceId != null) {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
Log.d("DirectShare", "sharing to " + service.getDevice(deviceId).getName());
@Override Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { if (device.isReachable() && device.isPaired()) {
Log.d("DirectShare", "sharing to " + service.getDevice(deviceId).getName()); SharePlugin.share(intent, device);
Device device = service.getDevice(deviceId);
if (device.isReachable() && device.isPaired()) {
SharePlugin.share(intent, device);
}
finish();
} }
finish();
}); });
} else { } else {
BackgroundService.addGuiInUseCounter(this); BackgroundService.addGuiInUseCounter(this);
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override service.onNetworkChange();
public void onServiceStart(BackgroundService service) { service.addDeviceListChangedCallback("ShareActivity", this::updateComputerList);
service.onNetworkChange();
service.addDeviceListChangedCallback("ShareActivity", new BackgroundService.DeviceListChangedCallback() {
@Override
public void onDeviceListChanged() {
updateComputerList();
}
});
}
}); });
updateComputerList(); updateComputerList();
} }
@ -210,12 +171,7 @@ public class ShareActivity extends AppCompatActivity {
@Override @Override
protected void onStop() { protected void onStop() {
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> service.removeDeviceListChangedCallback("ShareActivity"));
@Override
public void onServiceStart(BackgroundService service) {
service.removeDeviceListChangedCallback("ShareActivity");
}
});
BackgroundService.removeGuiInUseCounter(this); BackgroundService.removeGuiInUseCounter(this);
super.onStop(); super.onStop();
} }

View File

@ -219,64 +219,61 @@ public class SharePlugin extends Plugin {
final ShareNotification notification = new ShareNotification(device, filename); final ShareNotification notification = new ShareNotification(device, filename);
notification.show(); notification.show();
new Thread(new Runnable() { new Thread(() -> {
@Override try {
public void run() { byte data[] = new byte[4096];
try { long progress = 0, prevProgressPercentage = -1;
byte data[] = new byte[4096]; int count;
long progress = 0, prevProgressPercentage = -1; long lastUpdate = 0;
int count; while ((count = input.read(data)) >= 0) {
long lastUpdate = 0; progress += count;
while ((count = input.read(data)) >= 0) { destinationOutput.write(data, 0, count);
progress += count; if (fileLength > 0) {
destinationOutput.write(data, 0, count); if (progress >= fileLength) break;
if (fileLength > 0) { long progressPercentage = (progress * 100 / fileLength);
if (progress >= fileLength) break; if (progressPercentage != prevProgressPercentage &&
long progressPercentage = (progress * 100 / fileLength); System.currentTimeMillis() - lastUpdate > 100) {
if (progressPercentage != prevProgressPercentage && prevProgressPercentage = progressPercentage;
System.currentTimeMillis() - lastUpdate > 100) { lastUpdate = System.currentTimeMillis();
prevProgressPercentage = progressPercentage;
lastUpdate = System.currentTimeMillis();
notification.setProgress((int) progressPercentage); notification.setProgress((int) progressPercentage);
notification.show(); notification.show();
}
} }
//else Log.e("SharePlugin", "Infinite loop? :D");
} }
//else Log.e("SharePlugin", "Infinite loop? :D");
}
destinationOutput.flush(); destinationOutput.flush();
Log.i("SharePlugin", "Transfer finished: " + destinationUri.getPath()); Log.i("SharePlugin", "Transfer finished: " + destinationUri.getPath());
//Update the notification and allow to open the file from it //Update the notification and allow to open the file from it
notification.setFinished(true); notification.setFinished(true);
notification.setURI(destinationUri, mimeType); notification.setURI(destinationUri, mimeType);
notification.show(); notification.show();
if (!customDestination && Build.VERSION.SDK_INT >= 12) { if (!customDestination && Build.VERSION.SDK_INT >= 12) {
Log.i("SharePlugin", "Adding to downloads"); Log.i("SharePlugin", "Adding to downloads");
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
manager.addCompletedDownload(destinationUri.getLastPathSegment(), device.getName(), true, mimeType, destinationUri.getPath(), fileLength, false); manager.addCompletedDownload(destinationUri.getLastPathSegment(), device.getName(), true, mimeType, destinationUri.getPath(), fileLength, false);
} else { } else {
//Make sure it is added to the Android Gallery anyway //Make sure it is added to the Android Gallery anyway
MediaStoreHelper.indexFile(context, destinationUri); MediaStoreHelper.indexFile(context, destinationUri);
} }
} catch (Exception e) {
Log.e("SharePlugin", "Receiver thread exception");
e.printStackTrace();
notification.setFinished(false);
notification.show();
} finally {
try {
destinationOutput.close();
} catch (Exception e) {
}
try {
input.close();
} catch (Exception e) { } catch (Exception e) {
Log.e("SharePlugin", "Receiver thread exception");
e.printStackTrace();
notification.setFinished(false);
notification.show();
} finally {
try {
destinationOutput.close();
} catch (Exception e) {
}
try {
input.close();
} catch (Exception e) {
}
} }
} }
}).start(); }).start();
@ -302,21 +299,18 @@ public class SharePlugin extends Plugin {
final NotificationUpdateCallback notificationUpdateCallback = new NotificationUpdateCallback(context, device, toSend); final NotificationUpdateCallback notificationUpdateCallback = new NotificationUpdateCallback(context, device, toSend);
//Do the sending in background //Do the sending in background
new Thread(new Runnable() { new Thread(() -> {
@Override //Actually send the files
public void run() { try {
//Actually send the files for (NetworkPacket np : toSend) {
try { boolean success = device.sendPacketBlocking(np, notificationUpdateCallback);
for (NetworkPacket np : toSend) { if (!success) {
boolean success = device.sendPacketBlocking(np, notificationUpdateCallback); Log.e("SharePlugin", "Error sending files");
if (!success) { return;
Log.e("SharePlugin", "Error sending files");
return;
}
} }
} catch (Exception e) {
e.printStackTrace();
} }
} catch (Exception e) {
e.printStackTrace();
} }
}).start(); }).start();

View File

@ -36,20 +36,14 @@ public class ShareSettingsActivity extends PluginSettingsActivity {
filePicker = findPreference("share_destination_folder_preference"); filePicker = findPreference("share_destination_folder_preference");
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) { if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) {
customDownloads.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { customDownloads.setOnPreferenceChangeListener((preference, newValue) -> {
@Override updateFilePickerStatus((Boolean) newValue);
public boolean onPreferenceChange(Preference preference, Object newValue) { return true;
updateFilePickerStatus((Boolean) newValue);
return true;
}
}); });
filePicker.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { filePicker.setOnPreferenceClickListener(preference -> {
@Override Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
public boolean onPreferenceClick(Preference preference) { startActivityForResult(intent, RESULT_PICKER);
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); return true;
startActivityForResult(intent, RESULT_PICKER);
return true;
}
}); });
} else { } else {
customDownloads.setEnabled(false); customDownloads.setEnabled(false);

View File

@ -65,66 +65,48 @@ public class CustomDevicesActivity extends AppCompatActivity {
list.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, ipAddressList)); list.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, ipAddressList));
findViewById(android.R.id.button1).setOnClickListener(new View.OnClickListener() { findViewById(android.R.id.button1).setOnClickListener(v -> addNewDevice());
@Override
public void onClick(View v) {
addNewDevice();
}
});
EditText ipEntryBox = (EditText) findViewById(R.id.ip_edittext); EditText ipEntryBox = (EditText) findViewById(R.id.ip_edittext);
ipEntryBox.setOnEditorActionListener(new TextView.OnEditorActionListener() { ipEntryBox.setOnEditorActionListener((v, actionId, event) -> {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEND) {
if (actionId == EditorInfo.IME_ACTION_SEND) { addNewDevice();
addNewDevice(); return true;
return true;
}
return false;
} }
return false;
}); });
} }
boolean dialogAlreadyShown = false; boolean dialogAlreadyShown = false;
private AdapterView.OnItemClickListener onClickListener = new AdapterView.OnItemClickListener() { private AdapterView.OnItemClickListener onClickListener = (parent, view, position, id) -> {
@Override
public void onItemClick(AdapterView<?> parent, View view, final int position, final long id) {
if (dialogAlreadyShown) { if (dialogAlreadyShown) {
return; return;
}
// remove touched item after confirmation
DialogInterface.OnClickListener confirmationListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
ipAddressList.remove(position);
saveList();
break;
case DialogInterface.BUTTON_NEGATIVE:
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(CustomDevicesActivity.this);
builder.setMessage("Delete " + ipAddressList.get(position) + " ?");
builder.setPositiveButton("Yes", confirmationListener);
builder.setNegativeButton("No", confirmationListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { //DismissListener
dialogAlreadyShown = true;
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
dialogAlreadyShown = false;
}
});
}
builder.show();
} }
// remove touched item after confirmation
DialogInterface.OnClickListener confirmationListener = (dialog, which) -> {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
ipAddressList.remove(position);
saveList();
break;
case DialogInterface.BUTTON_NEGATIVE:
break;
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(CustomDevicesActivity.this);
builder.setMessage("Delete " + ipAddressList.get(position) + " ?");
builder.setPositiveButton("Yes", confirmationListener);
builder.setNegativeButton("No", confirmationListener);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { //DismissListener
dialogAlreadyShown = true;
builder.setOnDismissListener(dialog -> dialogAlreadyShown = false);
}
builder.show();
}; };
private void addNewDevice() { private void addNewDevice() {

View File

@ -110,97 +110,64 @@ public class DeviceFragment extends Fragment {
//Log.e("DeviceFragment", "device: " + deviceId); //Log.e("DeviceFragment", "device: " + deviceId);
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(mActivity, service -> {
@Override device = service.getDevice(mDeviceId);
public void onServiceStart(BackgroundService service) { if (device == null) {
device = service.getDevice(mDeviceId); Log.e("DeviceFragment", "Trying to display a device fragment but the device is not present");
if (device == null) { mActivity.onDeviceSelected(null);
Log.e("DeviceFragment", "Trying to display a device fragment but the device is not present"); return;
mActivity.onDeviceSelected(null);
return;
}
mActivity.getSupportActionBar().setTitle(device.getName());
device.addPairingCallback(pairingCallback);
device.addPluginsChangedListener(pluginsChangedListener);
refreshUI();
} }
mActivity.getSupportActionBar().setTitle(device.getName());
device.addPairingCallback(pairingCallback);
device.addPluginsChangedListener(pluginsChangedListener);
refreshUI();
}); });
final Button pairButton = (Button) rootView.findViewById(R.id.pair_button); final Button pairButton = (Button) rootView.findViewById(R.id.pair_button);
pairButton.setOnClickListener(new View.OnClickListener() { pairButton.setOnClickListener(view -> {
@Override pairButton.setVisibility(View.GONE);
public void onClick(View view) { ((TextView) rootView.findViewById(R.id.pair_message)).setText("");
pairButton.setVisibility(View.GONE); rootView.findViewById(R.id.pair_progress).setVisibility(View.VISIBLE);
((TextView) rootView.findViewById(R.id.pair_message)).setText(""); BackgroundService.RunCommand(mActivity, service -> {
rootView.findViewById(R.id.pair_progress).setVisibility(View.VISIBLE); device = service.getDevice(deviceId);
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() { if (device == null) return;
@Override device.requestPairing();
public void onServiceStart(BackgroundService service) { });
device = service.getDevice(deviceId);
if (device == null) return;
device.requestPairing();
}
});
}
}); });
rootView.findViewById(R.id.accept_button).setOnClickListener(new View.OnClickListener() { rootView.findViewById(R.id.accept_button).setOnClickListener(view -> BackgroundService.RunCommand(mActivity, service -> {
@Override if (device != null) {
public void onClick(View view) { device.acceptPairing();
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() { rootView.findViewById(R.id.pairing_buttons).setVisibility(View.GONE);
@Override
public void onServiceStart(BackgroundService service) {
if (device != null) {
device.acceptPairing();
rootView.findViewById(R.id.pairing_buttons).setVisibility(View.GONE);
}
}
});
} }
}); }));
rootView.findViewById(R.id.reject_button).setOnClickListener(new View.OnClickListener() { rootView.findViewById(R.id.reject_button).setOnClickListener(view -> BackgroundService.RunCommand(mActivity, service -> {
@Override if (device != null) {
public void onClick(View view) { //Remove listener so buttons don't show for a while before changing the view
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() { device.removePluginsChangedListener(pluginsChangedListener);
@Override device.removePairingCallback(pairingCallback);
public void onServiceStart(BackgroundService service) { device.rejectPairing();
if (device != null) {
//Remove listener so buttons don't show for a while before changing the view
device.removePluginsChangedListener(pluginsChangedListener);
device.removePairingCallback(pairingCallback);
device.rejectPairing();
}
mActivity.onDeviceSelected(null);
}
});
} }
}); mActivity.onDeviceSelected(null);
}));
return rootView; return rootView;
} }
final Device.PluginsChangedListener pluginsChangedListener = new Device.PluginsChangedListener() { final Device.PluginsChangedListener pluginsChangedListener = device -> refreshUI();
@Override
public void onPluginsChanged(final Device device) {
refreshUI();
}
};
@Override @Override
public void onDestroyView() { public void onDestroyView() {
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(mActivity, service -> {
@Override Device device = service.getDevice(mDeviceId);
public void onServiceStart(BackgroundService service) { if (device == null) return;
Device device = service.getDevice(mDeviceId); device.removePluginsChangedListener(pluginsChangedListener);
if (device == null) return; device.removePairingCallback(pairingCallback);
device.removePluginsChangedListener(pluginsChangedListener);
device.removePairingCallback(pairingCallback);
}
}); });
super.onDestroyView(); super.onDestroyView();
} }
@ -223,63 +190,47 @@ public class DeviceFragment extends Fragment {
if (!p.displayInContextMenu()) { if (!p.displayInContextMenu()) {
continue; continue;
} }
menu.add(p.getActionName()).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { menu.add(p.getActionName()).setOnMenuItemClickListener(item -> {
@Override p.startMainActivity(mActivity);
public boolean onMenuItemClick(MenuItem item) { return true;
p.startMainActivity(mActivity);
return true;
}
}); });
} }
menu.add(R.string.device_menu_plugins).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { menu.add(R.string.device_menu_plugins).setOnMenuItemClickListener(menuItem -> {
@Override Intent intent = new Intent(mActivity, SettingsActivity.class);
public boolean onMenuItemClick(MenuItem menuItem) { intent.putExtra("deviceId", mDeviceId);
Intent intent = new Intent(mActivity, SettingsActivity.class); startActivity(intent);
intent.putExtra("deviceId", mDeviceId); return true;
startActivity(intent);
return true;
}
}); });
if (device.isReachable()) { if (device.isReachable()) {
menu.add(R.string.encryption_info_title).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { menu.add(R.string.encryption_info_title).setOnMenuItemClickListener(menuItem -> {
@Override Context context = mActivity;
public boolean onMenuItemClick(MenuItem menuItem) { AlertDialog.Builder builder = new AlertDialog.Builder(context);
Context context = mActivity; builder.setTitle(context.getResources().getString(R.string.encryption_info_title));
AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setPositiveButton(context.getResources().getString(R.string.ok), (dialog, id) -> dialog.dismiss());
builder.setTitle(context.getResources().getString(R.string.encryption_info_title));
builder.setPositiveButton(context.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
if (device.certificate == null) { if (device.certificate == null) {
builder.setMessage(R.string.encryption_info_msg_no_ssl); builder.setMessage(R.string.encryption_info_msg_no_ssl);
} else { } else {
builder.setMessage(context.getResources().getString(R.string.my_device_fingerprint) + "\n" + SslHelper.getCertificateHash(SslHelper.certificate) + "\n\n" builder.setMessage(context.getResources().getString(R.string.my_device_fingerprint) + "\n" + SslHelper.getCertificateHash(SslHelper.certificate) + "\n\n"
+ context.getResources().getString(R.string.remote_device_fingerprint) + "\n" + SslHelper.getCertificateHash(device.certificate)); + context.getResources().getString(R.string.remote_device_fingerprint) + "\n" + SslHelper.getCertificateHash(device.certificate));
}
builder.create().show();
return true;
} }
builder.create().show();
return true;
}); });
} }
if (device.isPaired()) { if (device.isPaired()) {
menu.add(R.string.device_menu_unpair).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { menu.add(R.string.device_menu_unpair).setOnMenuItemClickListener(menuItem -> {
@Override //Remove listener so buttons don't show for a while before changing the view
public boolean onMenuItemClick(MenuItem menuItem) { device.removePluginsChangedListener(pluginsChangedListener);
//Remove listener so buttons don't show for a while before changing the view device.removePairingCallback(pairingCallback);
device.removePluginsChangedListener(pluginsChangedListener); device.unpair();
device.removePairingCallback(pairingCallback); mActivity.onDeviceSelected(null);
device.unpair(); return true;
mActivity.onDeviceSelected(null);
return true;
}
}); });
} }
@ -291,19 +242,16 @@ public class DeviceFragment extends Fragment {
getView().setFocusableInTouchMode(true); getView().setFocusableInTouchMode(true);
getView().requestFocus(); getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() { getView().setOnKeyListener((v, keyCode, event) -> {
@Override if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
public boolean onKey(View v, int keyCode, KeyEvent event) { boolean fromDeviceList = getArguments().getBoolean(ARG_FROM_DEVICE_LIST, false);
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { // Handle back button so we go to the list of devices in case we came from there
boolean fromDeviceList = getArguments().getBoolean(ARG_FROM_DEVICE_LIST, false); if (fromDeviceList) {
// Handle back button so we go to the list of devices in case we came from there mActivity.onDeviceSelected(null);
if (fromDeviceList) { return true;
mActivity.onDeviceSelected(null);
return true;
}
} }
return false;
} }
return false;
}); });
} }
@ -347,12 +295,7 @@ public class DeviceFragment extends Fragment {
if (!p.hasMainActivity()) continue; if (!p.hasMainActivity()) continue;
if (p.displayInContextMenu()) continue; if (p.displayInContextMenu()) continue;
pluginListItems.add(new PluginItem(p, new View.OnClickListener() { pluginListItems.add(new PluginItem(p, v -> p.startMainActivity(mActivity)));
@Override
public void onClick(View v) {
p.startMainActivity(mActivity);
}
}));
} }
createPluginsList(device.getFailedPlugins(), R.string.plugins_failed_to_load, new PluginClickListener() { createPluginsList(device.getFailedPlugins(), R.string.plugins_failed_to_load, new PluginClickListener() {
@ -408,31 +351,25 @@ public class DeviceFragment extends Fragment {
@Override @Override
public void pairingFailed(final String error) { public void pairingFailed(final String error) {
mActivity.runOnUiThread(new Runnable() { mActivity.runOnUiThread(() -> {
@Override if (rootView == null) return;
public void run() { ((TextView) rootView.findViewById(R.id.pair_message)).setText(error);
if (rootView == null) return; rootView.findViewById(R.id.pair_progress).setVisibility(View.GONE);
((TextView) rootView.findViewById(R.id.pair_message)).setText(error); rootView.findViewById(R.id.pair_button).setVisibility(View.VISIBLE);
rootView.findViewById(R.id.pair_progress).setVisibility(View.GONE); rootView.findViewById(R.id.pair_request).setVisibility(View.GONE);
rootView.findViewById(R.id.pair_button).setVisibility(View.VISIBLE); refreshUI();
rootView.findViewById(R.id.pair_request).setVisibility(View.GONE);
refreshUI();
}
}); });
} }
@Override @Override
public void unpaired() { public void unpaired() {
mActivity.runOnUiThread(new Runnable() { mActivity.runOnUiThread(() -> {
@Override if (rootView == null) return;
public void run() { ((TextView) rootView.findViewById(R.id.pair_message)).setText(R.string.device_not_paired);
if (rootView == null) return; rootView.findViewById(R.id.pair_progress).setVisibility(View.GONE);
((TextView) rootView.findViewById(R.id.pair_message)).setText(R.string.device_not_paired); rootView.findViewById(R.id.pair_button).setVisibility(View.VISIBLE);
rootView.findViewById(R.id.pair_progress).setVisibility(View.GONE); rootView.findViewById(R.id.pair_request).setVisibility(View.GONE);
rootView.findViewById(R.id.pair_button).setVisibility(View.VISIBLE); refreshUI();
rootView.findViewById(R.id.pair_request).setVisibility(View.GONE);
refreshUI();
}
}); });
} }
@ -440,51 +377,47 @@ public class DeviceFragment extends Fragment {
public static void acceptPairing(final String devId, final MainActivity activity) { public static void acceptPairing(final String devId, final MainActivity activity) {
final DeviceFragment frag = new DeviceFragment(devId, activity); final DeviceFragment frag = new DeviceFragment(devId, activity);
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(activity, service -> {
public void onServiceStart(BackgroundService service) { Device dev = service.getDevice(devId);
Device dev = service.getDevice(devId); if (dev == null) {
if (dev == null) { Log.w("rejectPairing", "Device no longer exists: " + devId);
Log.w("rejectPairing", "Device no longer exists: " + devId); return;
return;
}
activity.getSupportActionBar().setTitle(dev.getName());
dev.addPairingCallback(frag.pairingCallback);
dev.addPluginsChangedListener(frag.pluginsChangedListener);
frag.device = dev;
frag.device.acceptPairing();
frag.refreshUI();
} }
activity.getSupportActionBar().setTitle(dev.getName());
dev.addPairingCallback(frag.pairingCallback);
dev.addPluginsChangedListener(frag.pluginsChangedListener);
frag.device = dev;
frag.device.acceptPairing();
frag.refreshUI();
}); });
} }
public static void rejectPairing(final String devId, final MainActivity activity) { public static void rejectPairing(final String devId, final MainActivity activity) {
final DeviceFragment frag = new DeviceFragment(devId, activity); final DeviceFragment frag = new DeviceFragment(devId, activity);
BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(activity, service -> {
public void onServiceStart(BackgroundService service) { Device dev = service.getDevice(devId);
Device dev = service.getDevice(devId); if (dev == null) {
if (dev == null) { Log.w("rejectPairing", "Device no longer exists: " + devId);
Log.w("rejectPairing", "Device no longer exists: " + devId); return;
return;
}
activity.getSupportActionBar().setTitle(dev.getName());
dev.addPairingCallback(frag.pairingCallback);
dev.addPluginsChangedListener(frag.pluginsChangedListener);
frag.device = dev;
//Remove listener so buttons don't show for a while before changing the view
frag.device.removePluginsChangedListener(frag.pluginsChangedListener);
frag.device.removePairingCallback(frag.pairingCallback);
frag.device.rejectPairing();
activity.onDeviceSelected(null);
frag.refreshUI();
} }
activity.getSupportActionBar().setTitle(dev.getName());
dev.addPairingCallback(frag.pairingCallback);
dev.addPluginsChangedListener(frag.pluginsChangedListener);
frag.device = dev;
//Remove listener so buttons don't show for a while before changing the view
frag.device.removePluginsChangedListener(frag.pluginsChangedListener);
frag.device.removePairingCallback(frag.pairingCallback);
frag.device.rejectPairing();
activity.onDeviceSelected(null);
frag.refreshUI();
}); });
} }

View File

@ -74,12 +74,7 @@ public class PairingDeviceItem implements ListAdapter.Item {
v.findViewById(R.id.list_item_entry_summary).setVisibility(View.GONE); v.findViewById(R.id.list_item_entry_summary).setVisibility(View.GONE);
} }
v.setOnClickListener(new View.OnClickListener() { v.setOnClickListener(v1 -> callback.pairingClicked(device));
@Override
public void onClick(View v) {
callback.pairingClicked(device);
}
});
return v; return v;
} }

View File

@ -92,12 +92,7 @@ public class MainActivity extends AppCompatActivity {
TextView nameView = (TextView) mDrawerHeader.findViewById(R.id.device_name); TextView nameView = (TextView) mDrawerHeader.findViewById(R.id.device_name);
nameView.setText(deviceName); nameView.setText(deviceName);
View.OnClickListener renameListener = new View.OnClickListener() { View.OnClickListener renameListener = v -> renameDevice();
@Override
public void onClick(View v) {
renameDevice();
}
};
mDrawerHeader.findViewById(R.id.kdeconnect_label).setOnClickListener(renameListener); mDrawerHeader.findViewById(R.id.kdeconnect_label).setOnClickListener(renameListener);
mDrawerHeader.findViewById(R.id.device_name).setOnClickListener(renameListener); mDrawerHeader.findViewById(R.id.device_name).setOnClickListener(renameListener);
@ -105,17 +100,14 @@ public class MainActivity extends AppCompatActivity {
addDarkModeSwitch((ViewGroup) mDrawerHeader); addDarkModeSwitch((ViewGroup) mDrawerHeader);
} }
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { mNavigationView.setNavigationItemSelectedListener(menuItem -> {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
String deviceId = mMapMenuToDeviceId.get(menuItem); String deviceId = mMapMenuToDeviceId.get(menuItem);
onDeviceSelected(deviceId); onDeviceSelected(deviceId);
mDrawerLayout.closeDrawer(mNavigationView); mDrawerLayout.closeDrawer(mNavigationView);
return true; return true;
}
}); });
preferences = getSharedPreferences(STATE_SELECTED_DEVICE, Context.MODE_PRIVATE); preferences = getSharedPreferences(STATE_SELECTED_DEVICE, Context.MODE_PRIVATE);
@ -150,8 +142,8 @@ public class MainActivity extends AppCompatActivity {
* Adds a {@link SwitchCompat} to the bottom of the navigation header for * Adds a {@link SwitchCompat} to the bottom of the navigation header for
* toggling dark mode on and off. Call from {@link #onCreate(Bundle)}. * toggling dark mode on and off. Call from {@link #onCreate(Bundle)}.
* <p> * <p>
* Only supports android ICS and higher because {@link SwitchCompat} * Only supports android ICS and higher because {@link SwitchCompat}
* requires that. * requires that.
* </p> * </p>
* *
* @param drawerHeader the layout which should contain the switch * @param drawerHeader the layout which should contain the switch
@ -218,33 +210,30 @@ public class MainActivity extends AppCompatActivity {
//Log.e("MainActivity", "UpdateComputerList"); //Log.e("MainActivity", "UpdateComputerList");
BackgroundService.RunCommand(MainActivity.this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(MainActivity.this, service -> {
@Override
public void onServiceStart(final BackgroundService service) {
Menu menu = mNavigationView.getMenu(); Menu menu = mNavigationView.getMenu();
menu.clear(); menu.clear();
mMapMenuToDeviceId.clear(); mMapMenuToDeviceId.clear();
int id = 0; int id = 0;
Collection<Device> devices = service.getDevices().values(); Collection<Device> devices = service.getDevices().values();
for (Device device : devices) { for (Device device : devices) {
if (device.isReachable() && device.isPaired()) { if (device.isReachable() && device.isPaired()) {
MenuItem item = menu.add(0, id++, 0, device.getName()); MenuItem item = menu.add(0, id++, 0, device.getName());
item.setIcon(device.getIcon()); item.setIcon(device.getIcon());
item.setCheckable(true); item.setCheckable(true);
item.setChecked(device.getDeviceId().equals(mCurrentDevice)); item.setChecked(device.getDeviceId().equals(mCurrentDevice));
mMapMenuToDeviceId.put(item, device.getDeviceId()); mMapMenuToDeviceId.put(item, device.getDeviceId());
}
} }
MenuItem item = menu.add(99, id++, 0, R.string.pair_new_device);
item.setIcon(R.drawable.ic_action_content_add_circle_outline);
item.setCheckable(true);
item.setChecked(mCurrentDevice == null);
mMapMenuToDeviceId.put(item, null);
} }
MenuItem item = menu.add(99, id++, 0, R.string.pair_new_device);
item.setIcon(R.drawable.ic_action_content_add_circle_outline);
item.setCheckable(true);
item.setChecked(mCurrentDevice == null);
mMapMenuToDeviceId.put(item, null);
}); });
} }
@ -252,29 +241,14 @@ public class MainActivity extends AppCompatActivity {
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
BackgroundService.addGuiInUseCounter(this, true); BackgroundService.addGuiInUseCounter(this, true);
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> service.addDeviceListChangedCallback("MainActivity", this::updateComputerList));
@Override
public void onServiceStart(BackgroundService service) {
service.addDeviceListChangedCallback("MainActivity", new BackgroundService.DeviceListChangedCallback() {
@Override
public void onDeviceListChanged() {
updateComputerList();
}
});
}
});
updateComputerList(); updateComputerList();
} }
@Override @Override
protected void onStop() { protected void onStop() {
BackgroundService.removeGuiInUseCounter(this); BackgroundService.removeGuiInUseCounter(this);
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> service.removeDeviceListChangedCallback("MainActivity"));
@Override
public void onServiceStart(BackgroundService service) {
service.removeDeviceListChangedCallback("MainActivity");
}
});
super.onStop(); super.onStop();
} }
@ -326,12 +300,9 @@ public class MainActivity extends AppCompatActivity {
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { switch (requestCode) {
case RESULT_NEEDS_RELOAD: case RESULT_NEEDS_RELOAD:
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(mCurrentDevice);
public void onServiceStart(BackgroundService service) { device.reloadPluginsFromSettings();
Device device = service.getDevice(mCurrentDevice);
device.reloadPluginsFromSettings();
}
}); });
break; break;
default: default:
@ -344,12 +315,9 @@ public class MainActivity extends AppCompatActivity {
for (int result : grantResults) { for (int result : grantResults) {
if (result == PackageManager.PERMISSION_GRANTED) { if (result == PackageManager.PERMISSION_GRANTED) {
//New permission granted, reload plugins //New permission granted, reload plugins
BackgroundService.RunCommand(this, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(this, service -> {
@Override Device device = service.getDevice(mCurrentDevice);
public void onServiceStart(BackgroundService service) { device.reloadPluginsFromSettings();
Device device = service.getDevice(mCurrentDevice);
device.reloadPluginsFromSettings();
}
}); });
} }
} }
@ -368,24 +336,13 @@ public class MainActivity extends AppCompatActivity {
); );
new AlertDialog.Builder(MainActivity.this) new AlertDialog.Builder(MainActivity.this)
.setView(deviceNameEdit) .setView(deviceNameEdit)
.setPositiveButton(R.string.device_rename_confirm, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.device_rename_confirm, (dialog, which) -> {
@Override String deviceName1 = deviceNameEdit.getText().toString();
public void onClick(DialogInterface dialog, int which) { DeviceHelper.setDeviceName(MainActivity.this, deviceName1);
String deviceName = deviceNameEdit.getText().toString(); nameView.setText(deviceName1);
DeviceHelper.setDeviceName(MainActivity.this, deviceName); BackgroundService.RunCommand(MainActivity.this, BackgroundService::onNetworkChange);
nameView.setText(deviceName);
BackgroundService.RunCommand(MainActivity.this, new BackgroundService.InstanceCallback() {
@Override
public void onServiceStart(final BackgroundService service) {
service.onNetworkChange();
}
});
}
}) })
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { .setNegativeButton(R.string.cancel, (dialog, which) -> {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}) })
.setTitle(R.string.device_rename_title) .setTitle(R.string.device_rename_title)
.show(); .show();

View File

@ -15,8 +15,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.kde.kdeconnect.UserInterface; package org.kde.kdeconnect.UserInterface;
@ -79,12 +79,7 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
View listRootView = rootView.findViewById(R.id.devices_list); View listRootView = rootView.findViewById(R.id.devices_list);
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_list_layout); mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_list_layout);
mSwipeRefreshLayout.setOnRefreshListener( mSwipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() { this::updateComputerListAction
@Override
public void onRefresh() {
updateComputerListAction();
}
}
); );
headerText = new TextView(inflater.getContext()); headerText = new TextView(inflater.getContext());
headerText.setText(getString(R.string.pairing_description)); headerText.setText(getString(R.string.pairing_description));
@ -102,138 +97,106 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
private void updateComputerListAction() { private void updateComputerListAction() {
updateComputerList(); updateComputerList();
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(mActivity, BackgroundService::onNetworkChange);
@Override
public void onServiceStart(BackgroundService service) {
service.onNetworkChange();
}
});
mSwipeRefreshLayout.setRefreshing(true); mSwipeRefreshLayout.setRefreshing(true);
new Thread(new Runnable() { new Thread(() -> {
@Override try {
public void run() { Thread.sleep(1500);
try { } catch (InterruptedException ignored) {
Thread.sleep(1500);
} catch (InterruptedException ignored) {
}
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
}
});
} }
mActivity.runOnUiThread(() -> mSwipeRefreshLayout.setRefreshing(false));
}).start(); }).start();
} }
private void updateComputerList() { private void updateComputerList() {
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(mActivity, service -> mActivity.runOnUiThread(() -> {
@Override
public void onServiceStart(final BackgroundService service) {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (!isAdded()) {
//Fragment is not attached to an activity. We will crash if we try to do anything here.
return;
}
if (listRefreshCalledThisFrame) {
// This makes sure we don't try to call list.getFirstVisiblePosition()
// twice per frame, because the second time the list hasn't been drawn
// yet and it would always return 0.
return;
}
listRefreshCalledThisFrame = true;
headerText.setText(getString(NetworkHelper.isOnMobileNetwork(getContext()) ? R.string.on_data_message : R.string.pairing_description));
//Disable tap animation
headerText.setOnClickListener(null);
headerText.setOnLongClickListener(null);
try {
Collection<Device> devices = service.getDevices().values();
final ArrayList<ListAdapter.Item> items = new ArrayList<>();
SectionItem connectedSection;
Resources res = getResources();
connectedSection = new SectionItem(res.getString(R.string.category_connected_devices));
items.add(connectedSection);
for (Device device : devices) {
if (device.isReachable() && device.isPaired()) {
items.add(new PairingDeviceItem(device, PairingFragment.this));
connectedSection.isEmpty = false;
}
}
if (connectedSection.isEmpty) {
items.remove(items.size() - 1); //Remove connected devices section if empty
}
SectionItem availableSection = new SectionItem(res.getString(R.string.category_not_paired_devices));
items.add(availableSection);
for (Device device : devices) {
if (device.isReachable() && !device.isPaired()) {
items.add(new PairingDeviceItem(device, PairingFragment.this));
availableSection.isEmpty = false;
}
}
if (availableSection.isEmpty && !connectedSection.isEmpty) {
items.remove(items.size() - 1); //Remove remembered devices section if empty
}
SectionItem rememberedSection = new SectionItem(res.getString(R.string.category_remembered_devices));
items.add(rememberedSection);
for (Device device : devices) {
if (!device.isReachable() && device.isPaired()) {
items.add(new PairingDeviceItem(device, PairingFragment.this));
rememberedSection.isEmpty = false;
}
}
if (rememberedSection.isEmpty) {
items.remove(items.size() - 1); //Remove remembered devices section if empty
}
final ListView list = (ListView) rootView.findViewById(R.id.devices_list);
//Store current scroll
int index = list.getFirstVisiblePosition();
View v = list.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - list.getPaddingTop());
list.setAdapter(new ListAdapter(mActivity, items));
//Restore scroll
list.setSelectionFromTop(index, top);
} catch (IllegalStateException e) {
e.printStackTrace();
//Ignore: The activity was closed while we were trying to update it
} finally {
listRefreshCalledThisFrame = false;
}
}
});
if (!isAdded()) {
//Fragment is not attached to an activity. We will crash if we try to do anything here.
return;
} }
});
}
if (listRefreshCalledThisFrame) {
// This makes sure we don't try to call list.getFirstVisiblePosition()
// twice per frame, because the second time the list hasn't been drawn
// yet and it would always return 0.
return;
}
listRefreshCalledThisFrame = true;
headerText.setText(getString(NetworkHelper.isOnMobileNetwork(getContext()) ? R.string.on_data_message : R.string.pairing_description));
//Disable tap animation
headerText.setOnClickListener(null);
headerText.setOnLongClickListener(null);
try {
Collection<Device> devices = service.getDevices().values();
final ArrayList<ListAdapter.Item> items = new ArrayList<>();
SectionItem connectedSection;
Resources res = getResources();
connectedSection = new SectionItem(res.getString(R.string.category_connected_devices));
items.add(connectedSection);
for (Device device : devices) {
if (device.isReachable() && device.isPaired()) {
items.add(new PairingDeviceItem(device, PairingFragment.this));
connectedSection.isEmpty = false;
}
}
if (connectedSection.isEmpty) {
items.remove(items.size() - 1); //Remove connected devices section if empty
}
SectionItem availableSection = new SectionItem(res.getString(R.string.category_not_paired_devices));
items.add(availableSection);
for (Device device : devices) {
if (device.isReachable() && !device.isPaired()) {
items.add(new PairingDeviceItem(device, PairingFragment.this));
availableSection.isEmpty = false;
}
}
if (availableSection.isEmpty && !connectedSection.isEmpty) {
items.remove(items.size() - 1); //Remove remembered devices section if empty
}
SectionItem rememberedSection = new SectionItem(res.getString(R.string.category_remembered_devices));
items.add(rememberedSection);
for (Device device : devices) {
if (!device.isReachable() && device.isPaired()) {
items.add(new PairingDeviceItem(device, PairingFragment.this));
rememberedSection.isEmpty = false;
}
}
if (rememberedSection.isEmpty) {
items.remove(items.size() - 1); //Remove remembered devices section if empty
}
final ListView list = (ListView) rootView.findViewById(R.id.devices_list);
//Store current scroll
int index = list.getFirstVisiblePosition();
View v = list.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - list.getPaddingTop());
list.setAdapter(new ListAdapter(mActivity, items));
//Restore scroll
list.setSelectionFromTop(index, top);
} catch (IllegalStateException e) {
e.printStackTrace();
//Ignore: The activity was closed while we were trying to update it
} finally {
listRefreshCalledThisFrame = false;
}
}));
}
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(mActivity, service -> service.addDeviceListChangedCallback("PairingFragment", this::updateComputerList));
@Override
public void onServiceStart(BackgroundService service) {
service.addDeviceListChangedCallback("PairingFragment", new BackgroundService.DeviceListChangedCallback() {
@Override
public void onDeviceListChanged() {
updateComputerList();
}
});
}
});
updateComputerList(); updateComputerList();
} }
@ -241,12 +204,7 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
mSwipeRefreshLayout.setEnabled(false); mSwipeRefreshLayout.setEnabled(false);
BackgroundService.RunCommand(mActivity, new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(mActivity, service -> service.removeDeviceListChangedCallback("PairingFragment"));
@Override
public void onServiceStart(BackgroundService service) {
service.removeDeviceListChangedCallback("PairingFragment");
}
});
} }
@Override @Override

View File

@ -29,15 +29,12 @@ public class PluginPreference extends CheckBoxPreference {
Plugin plugin = device.getPlugin(pluginKey, true); Plugin plugin = device.getPlugin(pluginKey, true);
if (info.hasSettings() && plugin != null) { if (info.hasSettings() && plugin != null) {
this.listener = new View.OnClickListener() { this.listener = v -> {
@Override Plugin plugin1 = device.getPlugin(pluginKey, true);
public void onClick(View v) { if (plugin1 != null) {
Plugin plugin = device.getPlugin(pluginKey, true); plugin1.startPreferencesActivity(activity);
if (plugin != null) { } else { //Could happen if the device is not connected anymore
plugin.startPreferencesActivity(activity); activity.finish(); //End this activity so we go to the "device not reachable" screen
} else { //Could happen if the device is not connected anymore
activity.finish(); //End this activity so we go to the "device not reachable" screen
}
} }
}; };
} else { } else {
@ -58,14 +55,11 @@ public class PluginPreference extends CheckBoxPreference {
button.setOnClickListener(listener); button.setOnClickListener(listener);
} }
root.setOnClickListener(new View.OnClickListener() { root.setOnClickListener(v -> {
@Override boolean newState = !device.isPluginEnabled(pluginKey);
public void onClick(View v) { setChecked(newState); //It actually works on API<14
boolean newState = !device.isPluginEnabled(pluginKey); button.setEnabled(newState);
setChecked(newState); //It actually works on API<14 device.setPluginEnabled(pluginKey, newState);
button.setEnabled(newState);
device.setPluginEnabled(pluginKey, newState);
}
}); });
} }

View File

@ -44,24 +44,16 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
deviceId = getIntent().getStringExtra("deviceId"); deviceId = getIntent().getStringExtra("deviceId");
} }
BackgroundService.RunCommand(getApplicationContext(), new BackgroundService.InstanceCallback() { BackgroundService.RunCommand(getApplicationContext(), service -> {
@Override final Device device = service.getDevice(deviceId);
public void onServiceStart(BackgroundService service) { if (device == null) {
final Device device = service.getDevice(deviceId); SettingsActivity.this.runOnUiThread(SettingsActivity.this::finish);
if (device == null) { return;
SettingsActivity.this.runOnUiThread(new Runnable() { }
@Override List<String> plugins = device.getSupportedPlugins();
public void run() { for (final String pluginKey : plugins) {
SettingsActivity.this.finish(); PluginPreference pref = new PluginPreference(SettingsActivity.this, pluginKey, device);
} preferenceScreen.addPreference(pref);
});
return;
}
List<String> plugins = device.getSupportedPlugins();
for (final String pluginKey : plugins) {
PluginPreference pref = new PluginPreference(SettingsActivity.this, pluginKey, device);
preferenceScreen.addPreference(pref);
}
} }
}); });
} }

View File

@ -204,43 +204,27 @@ public class LanLinkTest extends AndroidTestCase {
Mockito.when(sharePacket.getType()).thenReturn("kdeconnect.share"); Mockito.when(sharePacket.getType()).thenReturn("kdeconnect.share");
Mockito.when(sharePacket.hasPayload()).thenReturn(true); Mockito.when(sharePacket.hasPayload()).thenReturn(true);
Mockito.when(sharePacket.hasPayloadTransferInfo()).thenReturn(true); Mockito.when(sharePacket.hasPayloadTransferInfo()).thenReturn(true);
Mockito.doAnswer(new Answer() { Mockito.doAnswer(invocationOnMock -> sharePacketJson.toString()).when(sharePacket).serialize();
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
return sharePacketJson.toString();
}
}).when(sharePacket).serialize();
Mockito.when(sharePacket.getPayload()).thenReturn(new ByteArrayInputStream(data)); Mockito.when(sharePacket.getPayload()).thenReturn(new ByteArrayInputStream(data));
Mockito.when(sharePacket.getPayloadSize()).thenReturn((long) data.length); Mockito.when(sharePacket.getPayloadSize()).thenReturn((long) data.length);
Mockito.doAnswer(new Answer() { Mockito.doAnswer(invocationOnMock -> sharePacketJson.getJSONObject("payloadTransferInfo")).when(sharePacket).getPayloadTransferInfo();
@Override Mockito.doAnswer(invocationOnMock -> {
public Object answer(InvocationOnMock invocationOnMock) throws Throwable { JSONObject object = (JSONObject) invocationOnMock.getArguments()[0];
return sharePacketJson.getJSONObject("payloadTransferInfo");
}
}).when(sharePacket).getPayloadTransferInfo();
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
JSONObject object = (JSONObject) invocationOnMock.getArguments()[0];
sharePacketJson.put("payloadTransferInfo", object); sharePacketJson.put("payloadTransferInfo", object);
return null; return null;
}
}).when(sharePacket).setPayloadTransferInfo(Mockito.any(JSONObject.class)); }).when(sharePacket).setPayloadTransferInfo(Mockito.any(JSONObject.class));
Mockito.doAnswer(new Answer() { Mockito.doAnswer(invocationOnMock -> {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
Log.e("LanLinkTest", "Write to stream"); Log.e("LanLinkTest", "Write to stream");
String stringNetworkPacket = new String((byte[]) invocationOnMock.getArguments()[0]); String stringNetworkPacket = new String((byte[]) invocationOnMock.getArguments()[0]);
final NetworkPacket np = NetworkPacket.unserialize(stringNetworkPacket); final NetworkPacket np = NetworkPacket.unserialize(stringNetworkPacket);
downloader.setNetworkPacket(np); downloader.setNetworkPacket(np);
downloader.start(); downloader.start();
return stringNetworkPacket.length(); return stringNetworkPacket.length();
}
}).when(goodOutputStream).write(Mockito.any(byte[].class)); }).when(goodOutputStream).write(Mockito.any(byte[].class));
goodLanLink.sendPacket(sharePacket, callback); goodLanLink.sendPacket(sharePacket, callback);