From dd020b0b6de595352e5968ad1d0b863e29488a48 Mon Sep 17 00:00:00 2001 From: badaix Date: Sun, 17 Jan 2016 14:16:18 +0100 Subject: [PATCH] undo delete client --- .../de/badaix/snapcast/ClientInfoItem.java | 5 +- .../java/de/badaix/snapcast/MainActivity.java | 82 +++++++++++------ .../de/badaix/snapcast/SnapclientService.java | 91 ++++++++++--------- .../badaix/snapcast/control/ClientInfo.java | 17 ++++ .../snapcast/control/RemoteControl.java | 2 +- .../badaix/snapcast/control/ServerInfo.java | 2 +- .../src/main/res/layout/activity_main.xml | 17 ++-- .../Snapcast/src/main/res/values/strings.xml | 2 + 8 files changed, 133 insertions(+), 85 deletions(-) diff --git a/android/Snapcast/src/main/java/de/badaix/snapcast/ClientInfoItem.java b/android/Snapcast/src/main/java/de/badaix/snapcast/ClientInfoItem.java index 676147e9..f2a22e5c 100644 --- a/android/Snapcast/src/main/java/de/badaix/snapcast/ClientInfoItem.java +++ b/android/Snapcast/src/main/java/de/badaix/snapcast/ClientInfoItem.java @@ -41,10 +41,7 @@ public class ClientInfoItem extends LinearLayout implements SeekBar.OnSeekBarCha } private void update() { - if (!clientInfo.getName().isEmpty()) - title.setText(clientInfo.getName()); - else - title.setText(clientInfo.getHost()); + title.setText(clientInfo.getVisibleName()); title.setEnabled(clientInfo.isConnected()); volumeSeekBar.setProgress(clientInfo.getVolume().getPercent()); if (clientInfo.getVolume().isMuted()) diff --git a/android/Snapcast/src/main/java/de/badaix/snapcast/MainActivity.java b/android/Snapcast/src/main/java/de/badaix/snapcast/MainActivity.java index 0e3b985d..5314a205 100644 --- a/android/Snapcast/src/main/java/de/badaix/snapcast/MainActivity.java +++ b/android/Snapcast/src/main/java/de/badaix/snapcast/MainActivity.java @@ -5,8 +5,6 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; import android.media.AudioManager; import android.net.Uri; import android.net.nsd.NsdManager; @@ -14,6 +12,9 @@ import android.net.nsd.NsdServiceInfo; import android.os.Build; import android.os.Bundle; import android.os.IBinder; +import android.support.design.widget.Snackbar; +import android.support.design.widget.Snackbar.Callback; +import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.Menu; @@ -26,7 +27,6 @@ import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ListView; import android.widget.TextView; -import android.widget.Toast; import com.google.android.gms.appindexing.Action; import com.google.android.gms.appindexing.AppIndex; @@ -40,9 +40,6 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl private static final String TAG = "Main"; boolean bound = false; - private TextView tvInfo; - private CheckBox cbScreenWakelock; - private ListView lvClient; private MenuItem miStartStop = null; private NsdManager.DiscoveryListener mDiscoveryListener; private NsdManager mNsdManager = null; @@ -82,8 +79,8 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - tvInfo = (TextView) findViewById(R.id.tvInfo); - cbScreenWakelock = (CheckBox) findViewById(R.id.cbScreenWakelock); + TextView tvInfo = (TextView) findViewById(R.id.tvInfo); + CheckBox cbScreenWakelock = (CheckBox) findViewById(R.id.cbScreenWakelock); cbScreenWakelock.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { @@ -94,8 +91,6 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl } }); - lvClient = (ListView) findViewById(R.id.lvClient); - AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { String rate = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); @@ -104,6 +99,7 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl } clientInfoAdapter = new ClientInfoAdapter(this, this); + ListView lvClient = (ListView) findViewById(R.id.lvClient); lvClient.setAdapter(clientInfoAdapter); getSupportActionBar().setSubtitle("Host: no Snapserver found"); @@ -175,6 +171,7 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); i.putExtra(SnapclientService.EXTRA_HOST, host); i.putExtra(SnapclientService.EXTRA_PORT, port); + i.setAction(SnapclientService.ACTION_START); startService(i); } @@ -209,7 +206,9 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { - getSupportActionBar().setSubtitle(text); + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) + actionBar.setSubtitle(text); } }); } @@ -361,9 +360,31 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl } @Override - public void onDeleteClicked(ClientInfoItem clientInfoItem) { - remoteControl.delete(clientInfoItem.getClientInfo()); - clientInfoAdapter.removeClient(clientInfoItem.getClientInfo()); + public void onDeleteClicked(final ClientInfoItem clientInfoItem) { + final ClientInfo clientInfo = clientInfoItem.getClientInfo(); + clientInfo.setDeleted(true); + clientInfoAdapter.update(); + Snackbar mySnackbar = Snackbar.make(findViewById(R.id.myCoordinatorLayout), + getString(R.string.client_deleted, clientInfo.getVisibleName()), + Snackbar.LENGTH_SHORT); + mySnackbar.setAction(R.string.undo_string, new View.OnClickListener() { + @Override + public void onClick(View v) { + clientInfo.setDeleted(false); + clientInfoAdapter.update(); + } + }); + mySnackbar.setCallback(new Callback() { + @Override + public void onDismissed(Snackbar snackbar, int event) { + super.onDismissed(snackbar, event); + if (event != DISMISS_EVENT_ACTION) { + remoteControl.delete(clientInfo); + clientInfoAdapter.removeClient(clientInfo); + } + } + }); + mySnackbar.show(); } @Override @@ -409,7 +430,7 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl @Override public void onServerInfo(RemoteControl remoteControl, ServerInfo serverInfo) { - clientInfoAdapter.update(serverInfo); + clientInfoAdapter.updateServer(serverInfo); } private class ClientInfoAdapter extends ArrayAdapter { @@ -440,29 +461,36 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl return clientInfoItem; } - public void updateClient(final ClientInfo clientInfo) { - if (serverInfo.addClient(clientInfo)) - update(null); - } - public void removeClient(final ClientInfo clientInfo) { - Log.d(TAG, "removeClient: " + clientInfo.getMac()); - if (serverInfo.removeClient(clientInfo)) { + if ((clientInfo != null) && serverInfo.removeClient(clientInfo)) { Log.d(TAG, "removeClient 1: " + clientInfo.getMac()); - update(null); + update(); } } - public void update(final ServerInfo serverInfo) { - if (serverInfo != null) + public void updateClient(final ClientInfo clientInfo) { + Log.d(TAG, "updateClient: " + clientInfo.getHost() + " " + clientInfo.isDeleted()); + if (serverInfo.updateClient(clientInfo)) { + update(); + } + } + + public void updateServer(final ServerInfo serverInfo) { + if (serverInfo != null) { ClientInfoAdapter.this.serverInfo = serverInfo; + update(); + } + } + + + public void update() { MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { clear(); for (ClientInfo clientInfo : ClientInfoAdapter.this.serverInfo.getClientInfos()) { - if ((clientInfo != null) && (!hideOffline || clientInfo.isConnected())) + if ((clientInfo != null) && (!hideOffline || clientInfo.isConnected()) && !clientInfo.isDeleted()) add(clientInfo); } notifyDataSetChanged(); @@ -478,7 +506,7 @@ public class MainActivity extends AppCompatActivity implements ClientInfoItem.Cl if (this.hideOffline == hideOffline) return; this.hideOffline = hideOffline; - update(null); + update(); } } } diff --git a/android/Snapcast/src/main/java/de/badaix/snapcast/SnapclientService.java b/android/Snapcast/src/main/java/de/badaix/snapcast/SnapclientService.java index 6641b1f5..491ab668 100644 --- a/android/Snapcast/src/main/java/de/badaix/snapcast/SnapclientService.java +++ b/android/Snapcast/src/main/java/de/badaix/snapcast/SnapclientService.java @@ -15,7 +15,6 @@ import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.support.v4.app.NotificationCompat; -import android.widget.Toast; import java.io.BufferedReader; import java.io.File; @@ -32,6 +31,8 @@ public class SnapclientService extends Service { public static final String EXTRA_HOST = "EXTRA_HOST"; public static final String EXTRA_PORT = "EXTRA_PORT"; + public static final String ACTION_START = "ACTION_START"; + public static final String ACTION_STOP = "ACTION_STOP"; private final IBinder mBinder = new LocalBinder(); private java.lang.Process process = null; private PowerManager.WakeLock wakeLock = null; @@ -50,57 +51,57 @@ public class SnapclientService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { - if (intent.getAction() == "ACTION_STOP") { + if (intent == null) + return START_NOT_STICKY; + + if (intent.getAction() == ACTION_STOP) { stopService(); return START_NOT_STICKY; - } - Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); + } else if (intent.getAction() == ACTION_START) { + Intent stopIntent = new Intent(this, SnapclientService.class); + stopIntent.setAction(ACTION_STOP); + PendingIntent piStop = PendingIntent.getService(this, 0, stopIntent, 0); - Intent stopIntent = new Intent(this, SnapclientService.class); - stopIntent.setAction("ACTION_STOP"); - PendingIntent piStop = PendingIntent.getService(this, 0, stopIntent, 0); + NotificationCompat.Builder builder = + new NotificationCompat.Builder(this) + .setSmallIcon(R.drawable.ic_media_play) + .setTicker(getText(R.string.ticker_text)) + .setContentTitle(getText(R.string.notification_title)) + .setContentText(getText(R.string.notification_text)) + .setContentInfo(getText(R.string.notification_info)) + .setStyle(new NotificationCompat.BigTextStyle().bigText(getText(R.string.notification_text))) + .addAction(R.drawable.ic_media_stop, getString(R.string.stop), piStop); - NotificationCompat.Builder builder = - new NotificationCompat.Builder(this) - .setSmallIcon(R.drawable.ic_media_play) - .setTicker(getText(R.string.ticker_text)) - .setContentTitle(getText(R.string.notification_title)) - .setContentText(getText(R.string.notification_text)) - .setContentInfo(getText(R.string.notification_info)) - .setStyle(new NotificationCompat.BigTextStyle().bigText(getText(R.string.notification_text))) - .addAction(R.drawable.ic_media_stop, getString(R.string.stop), piStop); + Intent resultIntent = new Intent(this, MainActivity.class); - Intent resultIntent = new Intent(this, MainActivity.class); - - // The stack builder object will contain an artificial back stack for the - // started Activity. - // This ensures that navigating backward from the Activity leads out of - // your application to the Home screen. - TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); - // Adds the back stack for the Intent (but not the Intent itself) - stackBuilder.addParentStack(MainActivity.class); - // Adds the Intent that starts the Activity to the top of the stack - stackBuilder.addNextIntent(resultIntent); - PendingIntent resultPendingIntent = - stackBuilder.getPendingIntent( - 0, - PendingIntent.FLAG_UPDATE_CURRENT - ); - builder.setContentIntent(resultPendingIntent); - NotificationManager mNotificationManager = - (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - // mId allows you to update the notification later on. - final Notification notification = builder.build(); + // The stack builder object will contain an artificial back stack for the + // started Activity. + // This ensures that navigating backward from the Activity leads out of + // your application to the Home screen. + TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); + // Adds the back stack for the Intent (but not the Intent itself) + stackBuilder.addParentStack(MainActivity.class); + // Adds the Intent that starts the Activity to the top of the stack + stackBuilder.addNextIntent(resultIntent); + PendingIntent resultPendingIntent = + stackBuilder.getPendingIntent( + 0, + PendingIntent.FLAG_UPDATE_CURRENT + ); + builder.setContentIntent(resultPendingIntent); + NotificationManager mNotificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + // mId allows you to update the notification later on. + final Notification notification = builder.build(); // mNotificationManager.notify(123, notification); - startForeground(123, notification); + startForeground(123, notification); - - String host = intent.getStringExtra(EXTRA_HOST); - int port = intent.getIntExtra(EXTRA_PORT, 1704); - start(host, port); - - // If we get killed, after returning from here, restart - return START_STICKY; + String host = intent.getStringExtra(EXTRA_HOST); + int port = intent.getIntExtra(EXTRA_PORT, 1704); + start(host, port); + return START_STICKY; + } + return START_NOT_STICKY; } @Override diff --git a/android/Snapcast/src/main/java/de/badaix/snapcast/control/ClientInfo.java b/android/Snapcast/src/main/java/de/badaix/snapcast/control/ClientInfo.java index 05b349dd..ea330d2e 100644 --- a/android/Snapcast/src/main/java/de/badaix/snapcast/control/ClientInfo.java +++ b/android/Snapcast/src/main/java/de/badaix/snapcast/control/ClientInfo.java @@ -29,6 +29,7 @@ public class ClientInfo implements JsonSerialisable { private Time_t lastSeen; private boolean connected; private int latency = 0; + private boolean deleted = false; public ClientInfo(JSONObject json) { fromJson(json); @@ -114,6 +115,12 @@ public class ClientInfo implements JsonSerialisable { return name; } + public String getVisibleName() { + if ((name != null) && !name.isEmpty()) + return name; + return getHost(); + } + public void setName(String name) { this.name = name; } @@ -134,6 +141,14 @@ public class ClientInfo implements JsonSerialisable { this.connected = connected; } + public boolean isDeleted() { + return deleted; + } + + public void setDeleted(boolean deleted) { + this.deleted = deleted; + } + @Override public String toString() { return "ClientInfo{" + @@ -157,6 +172,7 @@ public class ClientInfo implements JsonSerialisable { ClientInfo that = (ClientInfo) o; if (connected != that.connected) return false; + if (deleted != that.deleted) return false; if (latency != that.latency) return false; if (mac != null ? !mac.equals(that.mac) : that.mac != null) return false; if (ip != null ? !ip.equals(that.ip) : that.ip != null) return false; @@ -176,6 +192,7 @@ public class ClientInfo implements JsonSerialisable { result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (volume != null ? volume.hashCode() : 0); result = 31 * result + (connected ? 1 : 0); + result = 31 * result + (deleted ? 1 : 0); result = 31 * result + latency; return result; } diff --git a/android/Snapcast/src/main/java/de/badaix/snapcast/control/RemoteControl.java b/android/Snapcast/src/main/java/de/badaix/snapcast/control/RemoteControl.java index cabc93fe..3087e63d 100644 --- a/android/Snapcast/src/main/java/de/badaix/snapcast/control/RemoteControl.java +++ b/android/Snapcast/src/main/java/de/badaix/snapcast/control/RemoteControl.java @@ -76,7 +76,7 @@ public class RemoteControl implements TcpClient.TcpClientListener { JSONArray clients = json.getJSONObject("result").getJSONArray("clients"); for (int i = 0; i < clients.length(); i++) { final ClientInfo clientInfo = new ClientInfo(clients.getJSONObject(i)); - serverInfo.addClient(clientInfo); + serverInfo.updateClient(clientInfo); } if (listener != null) listener.onServerInfo(this, serverInfo); diff --git a/android/Snapcast/src/main/java/de/badaix/snapcast/control/ServerInfo.java b/android/Snapcast/src/main/java/de/badaix/snapcast/control/ServerInfo.java index 65c6c034..629aab21 100644 --- a/android/Snapcast/src/main/java/de/badaix/snapcast/control/ServerInfo.java +++ b/android/Snapcast/src/main/java/de/badaix/snapcast/control/ServerInfo.java @@ -26,7 +26,7 @@ public class ServerInfo { return false; } - public boolean addClient(ClientInfo client) { + public boolean updateClient(ClientInfo client) { if (client == null) return false; diff --git a/android/Snapcast/src/main/res/layout/activity_main.xml b/android/Snapcast/src/main/res/layout/activity_main.xml index 276bb009..92f06273 100644 --- a/android/Snapcast/src/main/res/layout/activity_main.xml +++ b/android/Snapcast/src/main/res/layout/activity_main.xml @@ -1,12 +1,10 @@ - + android:layout_centerHorizontal="true" + android:paddingBottom="@dimen/activity_vertical_margin" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin"> - + + diff --git a/android/Snapcast/src/main/res/values/strings.xml b/android/Snapcast/src/main/res/values/strings.xml index e0577b26..87989b3b 100644 --- a/android/Snapcast/src/main/res/values/strings.xml +++ b/android/Snapcast/src/main/res/values/strings.xml @@ -26,5 +26,7 @@ Latency online Play/Stop + Client %1$s deleted + undo