在本地通过 nodejs 服务器发布 android GPS 位置?

Publishing android GPS location over nodejs server locally?

我需要在本地发布我设备的 (android) GPS 坐标,以供笔记本电脑用于某些处理任务。现在我很高兴了解 Termux 以及通过 android.

设置 Web 服务器的能力

所以我计划在 android 上配置 nodeJS 服务器 (http) > 笔记本电脑通过热点连接到 android > 笔记本电脑上的 c++ 脚本可以请求设备 GPS实时(频率约为 10 - 20 Hz,我知道设备的 GPS 更新最多为 1Hz,但这里我说的是两个设备之间的通信)。

我试过使用

navigator.geolocation.getCurrentPosition

没有意识到它对 HTML 引擎的依赖,并且不可能从 nodeJS 实现。现在我正在寻找替代品 solution/approach 来实现这一目标。

作为最后的手段,我可​​能会创建一个 android app/service 将 GPS 位置发布到服务器并在我的笔记本电脑上获取该信息。我知道这太模糊了,但这就是我目前的理解。

谢谢!

好的,所以我最终为 android 创建了一个小型 GPS 服务器应用程序,它通过 USB 连接到系统。

在网上搜索时,我确实发现了“共享 GPS”应用程序,该应用程序在我的 android 9 上毫无用处。它无法捕获 GPS 测量值并吐出乱码以获得 $GPGGA 或$GPGSV 通过 USB 连接。但这为我的解决方案提供了线索。

我找不到任何合适的基于 c++ 的 gps 包来配合 android 平台的套接字连接。因此,最后一个选择是创建一个 android 应用程序来执行相同的操作。下面是我的实现,以防你遇到我的情况。

清单权限

<uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name = "android.permission.INTERNET"/>
<uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION" />

GPS 追踪器

package com.nfynt.gpsserver;

import android.Manifest;
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;

import androidx.core.app.ActivityCompat;

public class GPSTracker extends Service implements LocationListener {

    private final Context mContext;

    // flag for GPS status
    boolean isGPSEnabled = false;

    // flag for network status
    boolean isNetworkEnabled = false;

    // flag for GPS status
    boolean canGetLocation = false;

    Location location; // location
    double latitude; // latitude
    double longitude; // longitude
    double altitude;    //altitude

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1; // 1 meters

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 1; // 1 second

    // Declaring a Location Manager
    protected LocationManager locationManager;

    public GPSTracker(Context context) {
        this.mContext = context;
        initLocationTracker();
    }

    public Location initLocationTracker() {
        try {
            locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);

            // getting GPS status
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

            // getting network status
            isNetworkEnabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                // no network provider is enabled
            } else {
                this.canGetLocation = true;
                // First get location from Network Provider
                if (isNetworkEnabled) {

                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                            altitude = location.getAltitude();
                        }
                    }
                }

                // if GPS Enabled get lat/long using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);

                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                                altitude = location.getAltitude();
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }

    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app
     * */

    public void stopUsingGPS(){
        if(locationManager != null){
            locationManager.removeUpdates(GPSTracker.this);
        }
    }

    public double getLatitude(){
        if(location != null){
            latitude = location.getLatitude();
        }
        return latitude;
    }

    public double getLongitude(){
        if(location != null){
            longitude = location.getLongitude();
        }
        return longitude;
    }

    public double getAltitude(){
        if(location != null){
            altitude = location.getAltitude();
        }
        return altitude;
    }

    /**
     * Function to check GPS/wifi enabled
     * @return boolean
     * */

    public boolean canGetLocation() {
        return this.canGetLocation;
    }

    public void showSettingsAlert(){
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        // Setting Dialog Title
        alertDialog.setTitle("GPS is settings");

        // Setting Dialog Message
        alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

        // On pressing Settings button
        alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog,int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
            }
        });

        // on pressing cancel button
        alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });

        // Showing Alert Message
        alertDialog.show();
    }

    @Override
    public void onLocationChanged(Location location) {
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}

主要活动

package com.nfynt.gpsserver;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.*;

public class MainActivity extends AppCompatActivity {

    ServerSocket serverSocket;
    boolean serverIsActive;
    Thread Thread1 = null;
    TextView tvIP, tvPort;
    TextView tvStatus;
    TextView tvMessages;
    //EditText etMessage;
    Button btnSend;

    public static String SERVER_IP = "";
    public static final int SERVER_PORT = 50000;

    String message;

    String mPermission = Manifest.permission.ACCESS_FINE_LOCATION;
    private static final int REQUEST_CODE_PERMISSION = 2;
    // GPSTracker class
    GPSTracker gps;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvIP = findViewById(R.id.tvIP);
        tvPort = findViewById(R.id.tvPort);
        tvStatus = findViewById(R.id.tvConnectionStatus);
        tvMessages = findViewById(R.id.tvMessages);
        //etMessage = findViewById(R.id.etMessage);
        btnSend = findViewById(R.id.btnSend);

        try {
            if (ActivityCompat.checkSelfPermission(this, mPermission) != PackageManager.PERMISSION_GRANTED) {
                // if the permission is not granted
                ActivityCompat.requestPermissions(this, new String[]{mPermission},
                        REQUEST_CODE_PERMISSION);
            }
        } catch (Exception e) {
            e.printStackTrace();
            tvMessages.append(e.getMessage());
        }
        gps = new GPSTracker(MainActivity.this);

        try {
            SERVER_IP = getLocalIpAddress();
            tvStatus.setText("Offline");
            tvIP.setText("IP: " + SERVER_IP);
            tvPort.setText("Port: " + String.valueOf(SERVER_PORT));
        } catch (UnknownHostException e) {
            e.printStackTrace();
            tvMessages.append(e.getMessage());
        }


        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               // message = etMessage.getText().toString().trim();
                if(serverIsActive)
                    btnSend.setText("Start");
                else
                    btnSend.setText("Stop");
                ToggleServerState();
            }
        });
    }

    private void ToggleServerState()
    {
        serverIsActive=!serverIsActive;
        if(serverIsActive) {
            tvStatus.setText("Online");
            gps.initLocationTracker();
            Thread1 = new Thread(new Thread1());
            Thread1.start();
        }else{
            tvStatus.setText("Offline");
            gps.stopUsingGPS();
        }
        //new Thread(new Thread3(message)).start();
    }
    private String getLocalIpAddress() throws UnknownHostException {
        WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
        assert wifiManager != null;
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        int ipInt = wifiInfo.getIpAddress();
        return InetAddress.getByAddress(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ipInt).array()).getHostAddress();
    }

    private PrintWriter output;
    private BufferedReader input;

    class Thread1 implements Runnable {
        @Override
        public void run() {
            Socket socket;
            try {
                double latitude=0;
                double longitude=0;
                double altitude=0;
                Timestamp time = new Timestamp(System.currentTimeMillis());
                String t_stamp;
                serverSocket = new ServerSocket(SERVER_PORT);
                socket = serverSocket.accept();
                input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                output = new PrintWriter(socket.getOutputStream());

                while (true) {
                    if(!serverIsActive) break;

                    // check if GPS enabled
                    if(gps.canGetLocation()){
                        latitude = gps.getLatitude();
                        longitude = gps.getLongitude();
                        altitude = gps.getAltitude();

                        //Toast.makeText(getApplicationContext(), "Your Location is - \nLat: "
                        //+ latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
                    }else{
                        // Ask user to enable GPS/network in settings
                        gps.showSettingsAlert();
                    }
                    time = new Timestamp(System.currentTimeMillis());
                    //return number of milliseconds since January 1, 1970, 00:00:00 GMT
                    t_stamp = String.valueOf(time.getTime());
                    message = "$<time,lat,lon,alt>: ("+t_stamp+"," + String.valueOf(latitude) + ","+String.valueOf(longitude)+","+String.valueOf(altitude)+")";

                    output.write(message);
                    output.flush();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tvMessages.setText(message);
                        }
                    });
                    Thread.sleep(1000);
                }
                output.flush();
                serverSocket.close();
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

您可以从以下位置找到完整的项目:https://github.com/nfynt/GPS_Server 当前的实现非常粗糙,但符合我的目的。请根据您的要求随意使用或更新。

我正在使用 C++ 通过套接字连接来获取数据,但您也可以使用 netcat。

干杯!

截图:

Android

上的 GPS 服务器

PC 上的 GPS 客户端