以下是我用于项目的StreamProxy的来源
public class StreamProxy implements Runnable {
private static final String LOG_TAG = "Stream proxy: %s";
private int port = 0;
private boolean isRunning = true;
private ServerSocket socket;
private Thread thread;
public StreamProxy() {
init();
start();
}
public int getPort() {
return port;
}
public String getProxyUrl(String uri, String tag) {
return String.format("http://127.0.0.1:%d/%s", getPort(), uri);
}
private void init() {
try {
socket = new ServerSocket(port, 0, InetAddress.getByAddress(new byte[]{127, 0, 0, 1}));
socket.setSoTimeout(5000);
port = socket.getLocalPort();
Timber.d(LOG_TAG, "port " + port + " obtained");
} catch (IOException e) {
Timber.e(e, "Error initializing server");
}
}
private void start() {
if (socket == null) {
throw new IllegalStateException("Cannot start proxy; it has not been initialized.");
}
thread = new Thread(this);
thread.start();
}
public void stop() {
isRunning = false;
if (thread == null) {
throw new IllegalStateException("Cannot stop proxy; it has not been started.");
}
thread.interrupt();
try {
thread.join(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
Timber.d(LOG_TAG, "running");
while (isRunning) {
try {
Socket client = socket.accept();
if (client == null) {
continue;
}
Timber.d(LOG_TAG, "client connected");
client.setKeepAlive(false);
readRequest(client);
} catch (SocketTimeoutException e) {
} catch (IOException e) {
Timber.e(e, "Error connecting to client");
}
}
Timber.d(LOG_TAG, "Proxy interrupted. Shutting down.");
}
@Nullable
private void readRequest(Socket client) throws IOException {
InputStream is;
String firstLine;
try {
is = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
firstLine = reader.readLine();
} catch (IOException e) {
Timber.e(LOG_TAG, "Error parsing request", e);
return;
}
if (firstLine == null) {
Timber.i(LOG_TAG, "Proxy client closed connection without a request.");
return;
}
StringTokenizer st = new StringTokenizer(firstLine);
st.nextToken();
String uri = st.nextToken().substring(1);
Timber.d(LOG_TAG, uri);
processRequest(client, uri, "");
}
@Nullable
private HttpURLConnection download(String path) throws IOException {
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException("Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage());
}
return connection;
}
private void processRequest(Socket client, String url, String tag)
throws IllegalStateException, IOException {
Timber.d(LOG_TAG, "processing");
HttpURLConnection realResponse = download(url);
if (realResponse == null) {
return;
}
InputStream data = realResponse.getInputStream();
socketWriter.setClient(client);
try {
int readBytes;
Timber.d(LOG_TAG, "writing data to client");
// Start streaming content.
byte[] buff = new byte[1024 * 8];
while (isRunning && (readBytes = data.read(buff)) != -1) {
client.getOutputStream().write(buff, 0, readBytes)
}
Timber.d(LOG_TAG, "end writing data");
} catch (IOException e) {
Timber.e(e, "Error data transfer to client");
} finally {
Timber.d(LOG_TAG, "finally block");
if (data != null) {
data.close();
}
}
}
}
它完全适用于Android< 5.0但在Android 5.0上。+我在使用MediaExtractor(http://developer.android.com/reference/android/media/MediaExtractor.html)时出现以下错误
NuCachedSource2﹕ source returned error -1, 10 retries left
NuCachedSource2﹕ source returned error -1, 9 retries left
...
使用Mediaplayer时没有任何错误消息,只需几次静音重试。
对于Android 5,还有另一种带缓存的音频流方式吗?