【发布时间】:2015-11-30 20:35:07
【问题描述】:
应用程序概述:一个更简单的服务器在端口上侦听连接。向连接到该端口的每个客户端发送 GPS NMEA 字符串,因为它们从 GPS 芯片中出来。
因此 onCreate 会启动一个新线程来侦听端口。对于每个连接,此侦听器线程都会衍生出另一个新线程。这些线程中的每一个当前只是每两秒吐出一条“仍然连接”的消息。这部分一切正常,我可以设置几个 telnet 会话并连接,一切都按预期进行。所有位置信息也在这段代码中工作;它会使用正确且不断变化的 GPS 信息正确更新屏幕。
我想注册一个 Nmealistener,然后让它将该字符串分派给每个服务于连接的线程。但是,socketListenerThread.MasterDispatchNmeaMessage(nmea) 不会在 addNmeaListener 中解析。 (它也不会在它之外解决。) addNmeaListener 似乎没有问题,如果我有它只是通过 Log.d 转储消息,它会很乐意这样做。
在 socketListenerThread 类中,方法 MasterDispatchNmeaMessage 也被标记为“从不调用”。
那么是什么阻止了 MasterDispatchNmeaMessage 得到解决?
对于那些不熟悉的人,示例 NMEA 字符串如下所示:
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
在我正在测试的三星 S4 上,它们以突发形式出现,可能平均每秒 5 到 10 行。
附加说明:我的目标是 API 22。除此之外,位置类还需要更多的权限检查。因此,我希望在添加新的权限检查以使其与最新的库兼容之前,让所有这些工作真正发挥作用。
public class ActivityMain extends AppCompatActivity implements LocationListener {
static final String TAG = "GPSOverWiFi";
static final int LISTENING_PORT = 8085;
private TextView latitudeField;
private TextView longitudeField;
private LocationManager locationManager;
private String provider;
Thread socketListenerThread;
TextView info, infoip;
ServerSocket serverSocket;
int gConnectionCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
latitudeField = (TextView) findViewById(R.id.liveLatitude);
longitudeField = (TextView) findViewById(R.id.liveLongitude);
infoip = (TextView) findViewById(R.id.infoip);
info = (TextView) findViewById(R.id.info);
// Get the GPS location manager
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
// Initialize the location fields
if (location != null) {
System.out.println("Provider " + provider + " has been selected.");
onLocationChanged(location);
} else {
latitudeField.setText("Location not available");
longitudeField.setText("Location not available");
}
infoip.setText("IP Addresss: " + getIpAddress() + ":" + LISTENING_PORT);
socketListenerThread = new SocketListenerThread();
socketListenerThread.start();
//for giggles, it doesn't resolve here either, but this it needs to resolve a few lines down...
//socketListenerThread.MasterDispatchNmeaMessage("asdf");
locationManager.addNmeaListener(new GpsStatus.NmeaListener() {
public void onNmeaReceived(long timestamp, String nmea) {
// ////////////////////////////////////////////////////////////
// socketListenerThread.MasterDispatchNmeaMessage errors here with 'can't resolve
// ////////////////////////////////////////////////////////////
socketListenerThread.MasterDispatchNmeaMessage(nmea);
Log.d(TAG, "NMEA: " + nmea);
}
});
}
public class SocketListenerThread extends Thread {
Socket socket;
ArrayList<EachConnectionThread> connectionThreads = new ArrayList<EachConnectionThread>();
public void run() {
try {
serverSocket = new ServerSocket(LISTENING_PORT);
while (!isInterrupted()) { //You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app.
socket = serverSocket.accept();
gConnectionCount++;
EachConnectionThread thread = new EachConnectionThread(socket);
connectionThreads.add(thread);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void MasterDispatchNmeaMessage(String nmeaMessage) {
for (EachConnectionThread serverThread : connectionThreads)
serverThread.dispatchNmeaMessage(nmeaMessage);
}
}
public class EachConnectionThread extends Thread {
private Socket hostThreadSocket;
EachConnectionThread(Socket socket) {
hostThreadSocket = socket;
}
PrintStream printStream;
@Override
public void run() {
try {
OutputStream outputStream;
outputStream = hostThreadSocket.getOutputStream();
printStream = new PrintStream(outputStream);
printStream.print("Connected\r\n");
while(!printStream.checkError()) {
SystemClock.sleep(2000);
printStream.print("Still connected\r\n");
}
printStream.close();
outputStream.close();
hostThreadSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
gConnectionCount--;
}
public void dispatchNmeaMessage(String nmeaString){
printStream.print(nmeaString);
}
}
【问题讨论】:
-
Thread socketListenerThread;Thread没有那个方法。方法解析是针对声明的类型 (Thread),而不是定义的类型SocketListenerThread -
您是否考虑过使用服务而不是活动,它们都有上下文并且可以访问 gps 和其他通信功能,将所有这些逻辑绑定到活动并不是很好
-
我没有考虑过服务。是时候接受更多的教育了。 ;)
标签: java android multithreading sockets serversocket