为什么线程中的 public 方法在 onCreate 中没有解析?

Why does a public method in a thread not resolve in onCreate?

应用程序概述:一个更简单的服务器侦听端口的连接。对于连接到该端口的每个客户端,它会在它们从 GPS 芯片出来时发送 GPS NMEA 字符串。

因此 onCreate 启动了一个在端口上侦听的新线程。对于每个连接,此侦听器线程都会派生出另一个新线程。这些线程中的每一个目前只是每两秒吐出一条 "still connected" 消息。这部分一切正常,我可以设置几个 telnet 会话并连接,一切都按预期进行。所有位置的东西也在这段代码中工作;它使用正确和不断变化的 GPS 信息正确更新屏幕。

我想注册一个 Nmealilistener,然后让它将该字符串分派给每个为连接服务的线程。但是,socketListenerThread.MasterDispatchNmeaMessage(nmea) 不会在 addNmeaListener 内部解析。 (它也不会在它之外解决。)addNmeaListener 似乎没有问题,如果我有它只是通过 Log.d 转储消息,它会很乐意这样做。

在 socketListenerThread class 中,方法 MasterDispatchNmeaMessage 也被标记为 "never called"。

那么是什么阻止了 MasterDispatchNmeaMessage 被解析?

对于那些不熟悉的人,示例 NMEA 字符串如下所示:

$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47

它们突然出现,在我测试的三星 S4 上可能平均每秒五到十行。

补充说明:我的目标是 API 22。在此之后,将对位置 classes 进行更多的权限检查。所以我想在添加新的权限检查以使其与最新的库兼容之前让所有这些实际工作。

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;

SocketListenerThread socketListenerThread;

因此您可以通过 socketListenerThread 实例访问 SocketListenerThread 方法。