使用内置 android 传感器的移动方向

Posted

技术标签:

【中文标题】使用内置 android 传感器的移动方向【英文标题】:mobile orientation using in-built android sensors 【发布时间】:2022-01-17 18:41:24 【问题描述】:

我是这个领域的新手。我的目标是制作一个 android 应用程序,当在车辆中时,它用于使用 android 内置传感器测量车辆的速度。我面临的问题是我可以使用 TYPE_LINEAR_ACCELERATION 获得加速。但它显示在 3 轴的 3 个不同值上。我能理解的是对于这个应用程序,我应该看看手机是否处于水平位置,那么我应该考虑 Y 轴,如果手机处于水平位置,那么我应该考虑 X 轴。但是我怎么知道手机是水平的还是垂直的?有人可以帮我吗?

它显示错误,我只是复制了您给定的代码: public void onSensorChanged(SensorEvent sensorEvent)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
            display?.rotation
        else
            windowManager.defaultDisplay.orientation
        

        float x=sensorEvent.values[0];
        float y=sensorEvent.values[1];
        float z=sensorEvent.values[2];

        accelerationCurrentValue=Math.abs((Math.sqrt((x*x)+(y*y)+(z*z))-9.8));
        accelerationCurrentValue=(double)Math.round(accelerationCurrentValue*1000)/1000;

        //update text views
        tv_accel.setText(String.valueOf(accelerationCurrentValue));
    

它显示错误 无法解析符号“显示”、“旋转”、“窗口管理器” 你能告诉我如何解决它们吗?

【问题讨论】:

【参考方案1】:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
        display?.rotation
    else
        windowManager.defaultDisplay.orientation
    

您可以使用它来获取方向

【讨论】:

嗨,我已将您的代码和我的问题添加到问题中。请帮忙。 请在您的活动中添加此代码。您还可以重写 onConfigurationChange 方法以在方向更改发生时获取方向 你好,我有一个代码,我想显示我将发布我的代码的速度。它没有向我显示速度。【参考方案2】:
 package com.example.gpslatlongi;

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

 import android.Manifest;
 import android.content.pm.PackageManager;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.location.Address;
 import android.location.Geocoder;
 import android.location.Location;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.view.View;
 import android.widget.Switch;
 import android.widget.TextView;
 import android.widget.Toast;

 import com.google.android.gms.location.FusedLocationProviderClient;
 import com.google.android.gms.location.LocationCallback;
 import com.google.android.gms.location.LocationRequest;
 import com.google.android.gms.location.LocationResult;
 import com.google.android.gms.location.LocationServices;
 import com.google.android.gms.tasks.OnCompleteListener;
 import com.google.android.gms.tasks.OnSuccessListener;
 import com.google.android.gms.tasks.Task;

 import java.util.Date;
 import java.util.List;
 import java.util.Timer;
 import java.util.TimerTask;

 public class MainActivity extends AppCompatActivity 

public static final int DEFAULT_UPDATE_INTERVAL = 30;
public static final int FAST_UPDATE_INTERVAL = 2;
private static final int PERMISSIONS_FINE_LOCATION = 99;
//reference to the UI elements
TextView tv_lat, tv_lon, tv_altitude, tv_accuracy, tv_speed, tv_sensor, tv_updates, tv_address, tv_accel;

Switch sw_locationupdates, sw_gps;

Handler handler = new Handler();

//define the sensor variables
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private Sensor mGravity;

//variable to remember if we are tracking location or not
boolean updateOn = false;

float appliedAcceleration = 0;
float currentAcceleration = 0;
float velocity = 0;
Date lastUpdate;

//Location request is a config file for all settings related to FusedLocationProviderClient
LocationRequest locationRequest;

LocationCallback locationCallBack;

//Google's API for location services. The majority of the app functions using this class.
FusedLocationProviderClient fusedLocationProviderClient;
private double accelerationCurrentValue;
private SensorEventListener sensorEventListener=new SensorEventListener() 

    double calibration = Double.NaN;

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) 

        double x=sensorEvent.values[0];
        double y=sensorEvent.values[1];
        double z=sensorEvent.values[2];

        accelerationCurrentValue=Math.abs((Math.sqrt((x*x)+(y*y)+(z*z))-9.8));
        tv_accel.setText(String.valueOf(accelerationCurrentValue));

        if (calibration == Double.NaN)
            calibration = accelerationCurrentValue;
        else 
            updateVelocity();
            currentAcceleration = (float)accelerationCurrentValue;
        

    

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) 

    
;

private void updateVelocity() 
    // Calculate how long this acceleration has been applied.
    Date timeNow = new Date(System.currentTimeMillis());
    long timeDelta = timeNow.getTime()-lastUpdate.getTime();
    lastUpdate.setTime(timeNow.getTime());

    // Calculate the change in velocity at the
    // current acceleration since the last update.
    float deltaVelocity = appliedAcceleration * (timeDelta/1000);
    appliedAcceleration = currentAcceleration;

    // Add the velocity change to the current velocity.
    velocity += deltaVelocity;


@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    lastUpdate = new Date(System.currentTimeMillis());

    //give each UI variable a value
    tv_lat = findViewById(R.id.tv_lat);
    tv_lon = findViewById(R.id.tv_lon);
    tv_altitude = findViewById(R.id.tv_altitude);
    tv_accuracy = findViewById(R.id.tv_accuracy);
    tv_speed = findViewById(R.id.tv_speed);
    tv_sensor = findViewById(R.id.tv_sensor);
    tv_updates = findViewById(R.id.tv_updates);
    tv_address = findViewById(R.id.tv_address);
    tv_accel = findViewById(R.id.tv_accel);

    sw_locationupdates = findViewById(R.id.sw_locationsupdates);
    sw_gps = findViewById(R.id.sw_gps);

    //initialize sensor objects
    mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
    mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

    Timer updateTimer = new Timer("velocityUpdate");
    updateTimer.scheduleAtFixedRate(new TimerTask() 
        public void run() 
            updateGUI();
        
    , 0, 1000);


    //set all properties of LocationRequest
    locationRequest = new LocationRequest();

    //how often does the default location check occur?
    locationRequest.setInterval(1000 * DEFAULT_UPDATE_INTERVAL);

    //how often does the default location check occur when set to the most frequent update?
    locationRequest.setFastestInterval(1000 * FAST_UPDATE_INTERVAL);

    locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

    //event that is triggered whenever the update interval is met.
    locationCallBack = new LocationCallback() 

        @Override
        public void onLocationResult(LocationResult locationResult) 
            super.onLocationResult(locationResult);

            //save the location
            Location location = locationResult.getLastLocation();
            updateUIValues(location);
        
    ;

    sw_gps.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            if (sw_gps.isChecked()) 
                //most accurate - use GPS
                locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
                tv_sensor.setText("Using GPS sensors");
             else 
                locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
                tv_sensor.setText("Using Towers + WiFi");
            
        
    );

    sw_locationupdates.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            if (sw_locationupdates.isChecked()) 
                //turn on location tracking
                startLocationUpdates();
             else 
                //turn off tracking
                stopLocationUpdates();
            
        
    );

    updateGPS();

//end onCreate() method

private void updateGUI() 
    // Convert from meters per second to miles per hour.
    final double mph = (Math.round(100*velocity / 1.6 * 3.6))/100;

    // Update the GUI
    handler.post(new Runnable() 
        public void run() 
            tv_speed.setText(String.valueOf(mph) + "mph");
        
    );


private void stopLocationUpdates() 
    tv_updates.setText("Location is not being tracked");
    tv_speed.setText("Not tracking location");
    tv_lat.setText("Not tracking location");
    tv_lon.setText("Not tracking location");
    tv_accuracy.setText("Not tracking location");
    tv_altitude.setText("Not tracking location");
    tv_address.setText("Not tracking location");
    tv_sensor.setText("Not tracking location");

    fusedLocationProviderClient.removeLocationUpdates(locationCallBack);


private void startLocationUpdates() 
    tv_updates.setText("Location is being tracked");
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    
    fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallBack, null);
    updateGPS();


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    switch (requestCode)
        case PERMISSIONS_FINE_LOCATION:
            if(grantResults[0] == PackageManager.PERMISSION_GRANTED)
                updateGPS();
            
            else
                Toast.makeText(this, "This app requires permission to be granted in order to work properly.", Toast.LENGTH_SHORT).show();
                finish();
            
            break;
    


private void updateGPS()
    //get permission from the user to track GPS
    //get the current location from fused client
    //update the UI - i.e. set all properties in their associated text view items.

    fusedLocationProviderClient= LocationServices.getFusedLocationProviderClient(MainActivity.this);
    if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED)
        //user provided the permission
        fusedLocationProviderClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() 
            @Override
            public void onSuccess(Location location) 
                if(location!=null) 
                    //we got permissions
                    updateUIValues(location);
                
            
        );
    else
        //permissions not granted yet
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            requestPermissions(new String[] Manifest.permission.ACCESS_FINE_LOCATION, PERMISSIONS_FINE_LOCATION);
        
    


protected void onResume() 
    super.onResume();
    mSensorManager.registerListener(sensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);


protected void onPause() 
    super.onPause();
    mSensorManager.unregisterListener(sensorEventListener);



private void updateUIValues(Location location) 

    //update all the text view objects with a new location.
    tv_lat.setText(String.valueOf(location.getLatitude()));
    tv_lon.setText(String.valueOf(location.getLongitude()));
    tv_accuracy.setText(String.valueOf(location.getAccuracy()));

    if(location.hasAltitude())
        tv_altitude.setText(String.valueOf(location.getAltitude()));
    
    else
        tv_altitude.setText("Not available.");
    

    Geocoder geocoder=new Geocoder(MainActivity.this);

    try
        List<Address> addresses=geocoder.getFromLocation(location.getLatitude(),location.getLongitude(),1);
        tv_address.setText(addresses.get(0).getAddressLine(0));
    catch(Exception e)
        tv_address.setText("Unable to get street address");
    

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于使用内置 android 传感器的移动方向的主要内容,如果未能解决你的问题,请参考以下文章

如何在android的驱动程序中对加速度传感器的数据进行方向和坐标的转

在没有 GPS 的情况下获取设备移动方向

Android开发之Sensors与摇一摇

Android Sensor Development

Android开发之方向传感器的使用? (2011-10-13 20:56:05)转载▼

从陀螺仪android传感器获取旋转度