在本地通过 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 客户端
我需要在本地发布我设备的 (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 客户端