Android:StreamProxy不适用于带有Android 5.x的Nexus4/5
下面是我在项目中使用的StreamProxy的源代码Android:StreamProxy不适用于带有Android 5.x的Nexus4/5,android,sockets,streaming,audio-streaming,Android,Sockets,Streaming,Audio Streaming,下面是我在项目中使用的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 Thre
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流代理上运行良好,实际上运行良好。我从MediaExtractor得到的所有错误都与容器有关。对于大多数以m4a格式打包的文件,使用Android SDK的组件无法通过流播放。除了三星、LG和其他一些制造商的一些ROM具有此功能
NuCachedSource2﹕ source returned error -1, 10 retries left
NuCachedSource2﹕ source returned error -1, 9 retries left
...