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:
parent
7536eb7427
commit
e712c69e15
@ -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 {
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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());
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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++) {
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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() {
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user