我正在尝试实现一个 Android 应用程序来连接到开源软件 Motion。目标是能够检查应用程序的状态并获取最后捕获的图像。
我不太会用 Java 编程,我的背景主要是 C 和 Python。我在理解 Android 的 UI 部分方面没有遇到任何真正的问题,但我发现使用任何类型的字节缓冲区都非常痛苦。Motion 软件有一个非常简单的 HTTP API。在 Java 中打开 URL 连接很容易。默认页面的响应如下所示
Motion 3.2.12 Running [4] Threads
0
1
2
3
出于我的目的,应用程序需要做的第一件事就是解析线程数。在某些时候,我还可以从第一行检索版本号,但这目前并不重要。
这是我的代码
package com.hydrogen18.motionsurveillanceviewer;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
public class MotionHttpApi {
String host;
int port = 80;
boolean secure = false;
int numberOfThreads = -1;
String getBaseUrl()
{
StringBuilder sb = new StringBuilder();
sb.append(secure ? "https://" : "http://");
sb.append(host);
sb.append(':');
sb.append(port);
return sb.toString();
}
public int getNumberOfCameras() throws IOException
{
if(numberOfThreads == -1)
{
retrieveSplash();
}
if(numberOfThreads == 1)
{
return 1;
}
return numberOfThreads - 1;
}
void retrieveSplash () throws IOException
{
URL url = new URL(getBaseUrl());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
if(conn.getResponseCode()!=HttpURLConnection.HTTP_OK)
{
throw new IOException("Got response code" + conn.getResponseCode());
}
try{
Byte[] buffer = new Byte[512];
byte[] sbuf = new byte[128];
int offset = 0;
InputStream in = new BufferedInputStream(conn.getInputStream());
boolean foundInfoString= false;
while( ! foundInfoString)
{
//Check to make sure we have not run out of space
if(offset == buffer.length)
{
throw new IOException("Response too large");
}
//Read into the smaller buffer since InputStream
//can't write to a Byte[]
final int result = in.read(sbuf,0,sbuf.length);
//Copy the data into the larger buffer
for(int i = 0; i < result;++i)
{
buffer[offset+i] = sbuf[i];
}
//Add to the offset
offset+=result;
//Wrap the array as a list
List<Byte> list = java.util.Arrays.asList(buffer);
//Find newline character
final int index = list.indexOf((byte) '\n');
//If the newline is present, extract the number of threads
if (index != -1)
{
//Find the number of threads
//Thread number is in the first lin like "[X]"
final int start = list.indexOf((byte)'[');
final int end = list.indexOf((byte)']');
//Sanity check the bounds
if(! (end > start))
{
throw new IOException("Couldn't locate number of threads");
}
//Create a string from the Byte[] array subset
StringBuilder sb = new StringBuilder();
for(int i = start+1; i != end; ++i)
{
final char c = (char) buffer[i].byteValue();
sb.append(c);
}
String numThreadsStr = sb.toString();
//Try and parse the string into a number
try
{
this.numberOfThreads = Integer.valueOf(numThreadsStr);
}catch(NumberFormatException e)
{
throw new IOException("Number of threads is NaN",e);
}
//No more values to extract
foundInfoString = true;
}
//If the InputStream got EOF and the into string has not been found
//Then an error has occurred.
if(result == -1 && ! foundInfoString )
{
throw new IOException("Never got info string");
}
}
}finally
{
//Close the connection
conn.disconnect();
}
}
public MotionHttpApi(String host,int port)
{
this.host = host;
this.port = port;
}
}
当您调用getNumberOfCameras()
. 但是我想我一定不是真的了解java方面的东西,因为retrieveSplash方法太复杂了。我可以用大约 10 行 C 或 1 行 Python 来做同样的事情。当然必须有一种更明智的方式来操作 java 中的字节?
我认为存在一些样式问题,例如当整数无法解析时,我可能不应该抛出 IOException 。但这是一个单独的问题。