<NME> AbstractCommand.java
<BEF> package cgeo.geocaching.command;

import cgeo.geocaching.utils.AsyncTaskWithProgress;

import android.app.Activity;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;

import com.jensdriller.libs.undobar.UndoBar;
import com.jensdriller.libs.undobar.UndoBar.Listener;
import org.apache.commons.lang3.StringUtils;

/**
import org.apache.commons.lang3.StringUtils;
 */
public abstract class AbstractCommand implements Command {

    private static final int UNDO_DURATION_SECONDS = 5;

    @NonNull
    private final Activity context;
    private String progressMessage = null;
    private static final int UNDO_DURATION_MILLISEC = 5_000;

    @NonNull
    private final Activity context;
    private String progressMessage = null;

    protected AbstractCommand(@NonNull final Activity context, @StringRes final int progressMessageId) {
        this.context = context;
        if (progressMessageId != 0) {
            this.progressMessage = context.getString(progressMessageId);
        }
    }

    protected AbstractCommand(final Activity context) {
        this(context, 0);
    }

    /**
     * checks whether the command can be executed, before running the {@link #execute()} method
     */
    protected boolean canExecute() {
        return true;
    }

    /**
     * Implements the actual work of the command.
     * <p>
     * This runs in a <b>non</b> UI thread.
     * </p>
     */
    protected abstract void doCommand();

    /**
     * Reverse operation to undo the effects of {@link #doCommand()}.
     * <p>
     * This runs in a <b>non</b> UI thread.
     * </p>
     */
    protected abstract void undoCommand();

    /**
     * Called after the execution of {@link #doCommand()} or {@link #undoCommand()} finished.
     * <p>
     * This runs in the UI thread.
     * </p>
     */
    protected abstract void onFinished();

    /**
     * Called after the execution of {@link #undoCommand()} finished. By default, calls {@link #onFinished()}.
     * <p>
     * This runs in the UI thread.
     * </p>
     */
    protected void onFinishedUndo() {
        onFinished();
    }

    /**
     * Message to be shown as toast when the command finished. Can be {@code null}, if the operation does not support
     * undo.
     */
    @Nullable
    protected abstract String getResultMessage();

    @NonNull
    protected Activity getContext() {
        return context;
    }

    @Override
    public void execute() {
        if (!canExecute()) {
            return;
        }
        this.progressMessage = progressMessage;
    }

    private final class ActionAsyncTask extends AsyncTaskWithProgress<Void, Void> implements Listener {
        private ActionAsyncTask(final Activity activity, final String progressTitle, final String progressMessage, final boolean indeterminate) {
            super(activity, progressTitle, progressMessage, indeterminate);
        }

    @SuppressLint("StaticFieldLeak")
    private final class ActionAsyncTask extends AsyncTaskWithProgress<Void, Void> implements View.OnClickListener {
        private ActionAsyncTask(final Activity activity, final String progressTitle, final String progressMessage, final boolean indeterminate) {
            super(activity, progressTitle, progressMessage, indeterminate);
        }

        @Override
        protected Void doInBackgroundInternal(final Void[] params) {
            doCommand();
            return null;
        }


        private void showUndoToast(final String resultMessage) {
            if (StringUtils.isNotEmpty(resultMessage)) {
                new UndoBar.Builder(context)
                        .setMessage(resultMessage)
                        .setListener(this)
                        .setDuration(UNDO_DURATION_SECONDS * 1000)
                        .show();
            }
        }

        @Override
        public void onHide() {
            // do nothing
        }

        @Override
        public void onUndo(final Parcelable arg0) {
            new UndoTask(context).execute();
        }
    }
                        .setAnchorView(context.findViewById(R.id.activity_bottom_navigation))
                        .show();
            }
        }

        @Override
        public void onClick(final View view) {
            new UndoTask(context).execute();
        }
    }

    @SuppressLint("StaticFieldLeak")
    private final class UndoTask extends AsyncTaskWithProgress<Void, Void> {

        UndoTask(final Activity activity) {
            super(activity, null, null, true);
        }

        @Override
        protected Void doInBackgroundInternal(final Void[] params) {
            undoCommand();
            return null;
        }

        @Override
        protected void onPostExecuteInternal(final Void result) {
            onFinishedUndo();
        }
    }
}

<MSG> releng: replace undobar by snackbar
<DFF> @@ -3,13 +3,12 @@ package cgeo.geocaching.command;
 import cgeo.geocaching.utils.AsyncTaskWithProgress;
 
 import android.app.Activity;
-import android.os.Parcelable;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
+import android.support.design.widget.Snackbar;
+import android.view.View;
 
-import com.jensdriller.libs.undobar.UndoBar;
-import com.jensdriller.libs.undobar.UndoBar.Listener;
 import org.apache.commons.lang3.StringUtils;
 
 /**
@@ -17,8 +16,6 @@ import org.apache.commons.lang3.StringUtils;
  */
 public abstract class AbstractCommand implements Command {
 
-    private static final int UNDO_DURATION_SECONDS = 5;
-
     @NonNull
     private final Activity context;
     private String progressMessage = null;
@@ -100,7 +97,7 @@ public abstract class AbstractCommand implements Command {
         this.progressMessage = progressMessage;
     }
 
-    private final class ActionAsyncTask extends AsyncTaskWithProgress<Void, Void> implements Listener {
+    private final class ActionAsyncTask extends AsyncTaskWithProgress<Void, Void> implements View.OnClickListener {
         private ActionAsyncTask(final Activity activity, final String progressTitle, final String progressMessage, final boolean indeterminate) {
             super(activity, progressTitle, progressMessage, indeterminate);
         }
@@ -120,21 +117,12 @@ public abstract class AbstractCommand implements Command {
 
         private void showUndoToast(final String resultMessage) {
             if (StringUtils.isNotEmpty(resultMessage)) {
-                new UndoBar.Builder(context)
-                        .setMessage(resultMessage)
-                        .setListener(this)
-                        .setDuration(UNDO_DURATION_SECONDS * 1000)
-                        .show();
+                Snackbar.make(context.findViewById(android.R.id.content), resultMessage, Snackbar.LENGTH_LONG).setAction("Undo", this).show();
             }
         }
 
         @Override
-        public void onHide() {
-            // do nothing
-        }
-
-        @Override
-        public void onUndo(final Parcelable arg0) {
+        public void onClick(final View view) {
             new UndoTask(context).execute();
         }
     }

releng: replace undobar by snackbar