diff --git a/api/net/sf/briar/api/transport/TransportCallback.java b/api/net/sf/briar/api/transport/TransportCallback.java
new file mode 100644
index 0000000000000000000000000000000000000000..b74e2eabed09cd514af9b792368550ff9f7a5df9
--- /dev/null
+++ b/api/net/sf/briar/api/transport/TransportCallback.java
@@ -0,0 +1,16 @@
+package net.sf.briar.api.transport;
+
+import java.util.Map;
+
+public interface TransportCallback {
+
+	void setLocalTransports(Map<String, String> transports);
+
+	void setConfig(Map<String, String> config);
+
+	void showMessage(String message);
+
+	boolean showConfirmationMessage(String message);
+
+	int showChoice(String message, String[] choices);
+}
diff --git a/api/net/sf/briar/api/transport/batch/BatchTransportCallback.java b/api/net/sf/briar/api/transport/batch/BatchTransportCallback.java
index 79ef714be1e24627784a02208007ddf27fd7f6e0..8ad8b4221060af085a876ec403e8ddb73ff7c90b 100644
--- a/api/net/sf/briar/api/transport/batch/BatchTransportCallback.java
+++ b/api/net/sf/briar/api/transport/batch/BatchTransportCallback.java
@@ -1,18 +1,14 @@
 package net.sf.briar.api.transport.batch;
 
-import java.util.Map;
+import net.sf.briar.api.transport.TransportCallback;
 
 /**
  * An interface for receiving readers and writers created by a batch-mode
  * transport plugin.
  */
-public interface BatchTransportCallback {
+public interface BatchTransportCallback extends TransportCallback {
 
 	void readerCreated(BatchTransportReader r);
 
 	void writerCreated(BatchTransportWriter w);
-
-	void setLocalTransports(Map<String, String> transports);
-
-	void setConfig(Map<String, String> config);
 }
diff --git a/api/net/sf/briar/api/transport/batch/BatchTransportWriter.java b/api/net/sf/briar/api/transport/batch/BatchTransportWriter.java
index c485b6b235cb665b3a1d57d515a499d2450ca188..4ea8763306272cee210317752179da3936889843 100644
--- a/api/net/sf/briar/api/transport/batch/BatchTransportWriter.java
+++ b/api/net/sf/briar/api/transport/batch/BatchTransportWriter.java
@@ -16,9 +16,14 @@ public interface BatchTransportWriter {
 	OutputStream getOutputStream();
 
 	/**
-	 * Closes the writer and disposes of any associated state. This method must
-	 * be called even if the writer is not used, or if an exception is thrown
-	 * while using the writer.
+	 * Finishes writing to the transport. This method should be called after
+	 * flushing and closing the output stream.
+	 */
+	void finish() throws IOException;
+
+	/**
+	 * Disposes of any associated state. This method must be called even if the
+	 * writer is not used, or if an exception is thrown while using the writer.
 	 */
 	void dispose() throws IOException;
 }
diff --git a/api/net/sf/briar/api/transport/stream/StreamTransportCallback.java b/api/net/sf/briar/api/transport/stream/StreamTransportCallback.java
index 3a84fc5eb84e5c26952fbd9a965daf4241a5c4c3..d58d0ecbc5cb9b577ae4197b4ec77fa4b4b6284f 100644
--- a/api/net/sf/briar/api/transport/stream/StreamTransportCallback.java
+++ b/api/net/sf/briar/api/transport/stream/StreamTransportCallback.java
@@ -1,16 +1,12 @@
 package net.sf.briar.api.transport.stream;
 
-import java.util.Map;
+import net.sf.briar.api.transport.TransportCallback;
 
 /**
  * An interface for receiving connections created by a stream-mode transport
  * plugin.
  */
-public interface StreamTransportCallback {
+public interface StreamTransportCallback extends TransportCallback {
 
 	void connectionCreated(StreamTransportConnection c);
-
-	void setLocalTransports(Map<String, String> transports);
-
-	void setConfig(Map<String, String> config);
 }
diff --git a/test/net/sf/briar/transport/batch/TestBatchTransportWriter.java b/test/net/sf/briar/transport/batch/TestBatchTransportWriter.java
index bd2a3520861d71bfcaa5aecf9fdc701914edf81e..eb9f78167ca360c6ac99041a0cb74de4c606ae82 100644
--- a/test/net/sf/briar/transport/batch/TestBatchTransportWriter.java
+++ b/test/net/sf/briar/transport/batch/TestBatchTransportWriter.java
@@ -23,6 +23,10 @@ class TestBatchTransportWriter implements BatchTransportWriter {
 		return out;
 	}
 
+	public void finish() throws IOException {
+		// Nothing to do
+	}
+
 	public void dispose() throws IOException {
 		// The output stream may have been left open
 		out.close();