How to sync head movement with Google Cardboard in Android - android

I need to get head movements and according to that head turns (rotations). I need to do some work there. This is in case of inserting device in google cardboard.
I have searched the internet but I found no proper information. Please help me out here.
Thanks in advance.

Use Sensor class for this as shown below..
SensorEventListener mSensorListener = new SensorEventListener() {
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
}
#Override
public void onSensorChanged(SensorEvent event) {
Sensor sensor = event.sensor;
if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
if (event.values != null && event.values.length > 1) {
accelDataOld = rawAccelData;
rawAccelData = event.values[1];
tweenStep = (rawAccelData - accelData) / TWEEN_TIMING;
}
} else if (sensor.getType() == Sensor.TYPE_GYROSCOPE) {
if (event.values != null && event.values.length > 1) {
rawGyroData += event.values[0];
}
}
}
};

Related

Not getting sensor reading from fragment class

I am trying to get sensor gyroscope reading from a fragment
I implemented the SensorEventListener
public class Fragment1 extends Fragment implements View.OnClickListener, SensorEventListener
private SensorManager mSensorManager;
private Sensor mSensorGyro;
float [] history = new float[2];
public void onCreate(Bundle savedInstanceState) {
getActivity().getSystemService(Context.SENSOR_SERVICE);
mSensorGyro = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
}
Here's how I handled on incoming sensor readings.
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
Log.d(TAG, "onSensorChanged: ");
switch (sensorEvent.sensor.getType()) {
case Sensor.TYPE_GYROSCOPE:
float xChange = history[0] - sensorEvent.values[0];
float yChange = history[1] - sensorEvent.values[1];
history[0] = sensorEvent.values[0];
history[1] = sensorEvent.values[1];
if (xChange > 2) {
//clockwise
Log.d(TAG, "onSensorChanged: Clockwise");
} else if (xChange < -2) {
//anticlockwise
Log.d(TAG, "onSensorChanged: Anti-Clockwise");
}
if (yChange > 2) {
//forward
Log.d(TAG, "onSensorChanged: Forward");
}
}
}
When I run it on my android device, I am not getting any reading back, judging from the missing log on android logcat.
What could be the issue?
Missing listener register
mSensorManager.registerListener(this, mSensorGyro, SensorManager.SENSOR_DELAY_NORMAL);

Azimuth coming back as 0

I am trying to get the azimuth of the users phone when they take a picture. However, when I put the azimuth to the screen just for debugging purposes currently, it always comes back at 0.0. I am new to using Sensors so I am trying to figure this out. My code is
private void dispatchTakePictureIntent() {
double latitude, longitude;
if (mGpsLocationTracker.canGetLocation()) {
latitude = mGpsLocationTracker.getLatitude();
longitude = mGpsLocationTracker.getLongitude();
} else {
latitude = 0;
longitude = 0;
}
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
Toast.makeText(this, "" + latitude + ", " + longitude, Toast.LENGTH_SHORT).show();
getDirection ();
Toast.makeText(this, Float.toString(degree), Toast.LENGTH_SHORT).show();
}
public void getDirection() {
SensorManager mySensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
List<Sensor> mySensors = mySensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
if(mySensors.size() > 0){
mySensorManager.registerListener(mySensorEventListener, mySensors.get(0), SensorManager.SENSOR_DELAY_UI);
}
}
/*
DOES NOT WORK. NEED TO FIX
*/
private SensorEventListener mySensorEventListener = new SensorEventListener(){
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
float radianValue = Math.round(event.values[0]);
degree = (float) Math.toDegrees(radianValue);
if (degree < 0.0f) {
degree += 360.0f;
}
}
};
public void takePicture (View view) {
dispatchTakePictureIntent();
}
Can anyone help me with what I'm doing wrong
Doesn't the orientation sensor return the angle in degrees? You're assuming radians and converting to degrees. Given that though, it still should't give you 0.
TYPE_ORIENTATION is depreciated and does not give the correct result
if the device is not flat. You need to use TYPE_ACCELEROMETER and TYPE_MAGNETIC_FIELD to obtain the rotation matrix and then call remapCoordinateSystem before calling getOrientation.

Bluetooth connection fails when try to send command via bluetooth

I am trying to control a RC car using accelerometer via my own android studio app.
I managed to get the app to work through buttons by calling functions when a button is pressed.
I am trying to do the same with accelerometer by saying id the valus of x is less then this do this and call the function. but I cant connect to bluetooth the second i include my go foward function or andy functions to send the bluetooth command inside the if statement.
If connection is not success "Connection Failed. Is it a SPP Bluetooth? Try again". I keep getting this message
This is the part of the accelerometer code i have if statements.
#Override
public void onSensorChanged(SensorEvent event) {
// clean current values
displayCleanValues();
// display the current x,y,z accelerometer values
displayCurrentValues();
// display the max x,y,z accelerometer values
displayMaxValues();
// get the change of the x,y,z values of the accelerometer
deltaX =(lastX - event.values[0]);
deltaY = (lastY - event.values[1]);
deltaZ = (lastZ - event.values[2]);
// if the change is below 2, it is just plain noise
if (deltaX < 2)
DownArrow.setVisibility(View.VISIBLE);
else
DownArrow.setVisibility(View.INVISIBLE);
if ((deltaZ > vibrateThreshold) || (deltaY > vibrateThreshold) || (deltaZ > vibrateThreshold)) {
v.vibrate(50);
}
if (deltaX > -4) {
UpArrow.setVisibility(View.VISIBLE);
goForward();
}
if (deltaX < -4)
UpArrow.setVisibility(View.INVISIBLE);
if (deltaX < -7)
DownArrow.setVisibility(View.VISIBLE);
goBackward();
if (deltaX > -7)
DownArrow.setVisibility(View.INVISIBLE);
}
This is the functions I call which sends the bluetooth command.
private void goForward()
{
if (btSocket!=null)
{
try
{
btSocket.getOutputStream().write("F".toString().getBytes());
}
catch (IOException e)
{
msg("Error");
}
}
}
private void goBackward()
{
if (btSocket!=null)
{
try
{
btSocket.getOutputStream().write("B".toString().getBytes());
}
catch (IOException e)
{
msg("Error");
}
}
}
This is the Bluetooth code
#Override
protected void onPostExecute(Void result) //after the doInBackground, it checks if everything went fine
{
super.onPostExecute(result);
if (!ConnectSuccess)
{
msg("Connection Failed. Is it a SPP Bluetooth? Try again.");
finish();
}
else
{
msg("Connected.");
isBtConnected = true;
}
progress.dismiss();
}
I am doing the same in my button view and it works fine.
btnUp.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
btnUp.setBackgroundResource(R.drawable.button_arrow_green_up_select);
goForward();
return true;
}
if (event.getAction() == MotionEvent.ACTION_UP) {
btnUp.setBackgroundResource(R.drawable.button_arrow_green_up);
Stop();
}
return false;
}
});
Why it keeps failing?
I did a project for fun, Turn on led when any one shake the android mobile. I used arduino and HC-05 in order to communicate android with LED. I think the problem is you are sending "F" and "8" values through bluetooth in UI thread. so create other thread for sending values through bluetooth.
I am sharing part of my code, I think this would be use full.
mmOutputstream=socket.getOutputStream();
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
mGravity = event.values.clone();
// Shake detection
float x = mGravity[0];
float y = mGravity[1];
float z = mGravity[2];
int check=0;
mAccelLast = mAccelCurrent;
mAccelCurrent = FloatMath.sqrt(x*x + y*y + z*z);
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel * 0.9f + delta;
Log.d("TAG",data);
// Make this higher or lower according to how much
// motion you want to detect
if(connection){
if(mAccel<-2.0f)
{
check=10;
}
if(mAccel>-2.4f){
check=0;
}
new arduinosend().execute(check);
}
}
}
class arduinosend extends AsyncTask<Integer, Integer, String>
{
#Override
protected String doInBackground(Integer... params) {
// TODO Auto-generated method stub
try {
mmOutputstream.write(params[0]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}

Chromecast SDK (Android) - is there a way to check whether the media playing on the cast device has finished playing?

Is there an onFinished listener of some sort? Or do we have to compare the current stream position against the duration of the track?
It's not pretty but you can make this call:
if (mRemoteMediaPlayer.getMediaStatus().getPlayerState() == MediaStatus.PLAYER_STATE_IDLE
&& mRemoteMediaPlayer.getMediaStatus().getIdleReason() == MediaStatus.IDLE_REASON_FINISHED) {
...
}
Prem,
There is currently no callback to register for such event. One alternative (and-not-so-pretty) approach is the following: on the receiver, listen for "ended" event of the media element and send an event back to the sender through a private channel. Another approach is what you suggested: check position against duration. When SDK graduates to general availability, better and cleaner approaches will be available to accomplish what you want.
Here is solution:
You just need to take one more variable mIdleReason.
1) Initialize mIdleReason as
public int mIdleReason=MediaStatus.IDLE_REASON_NONE;
2) Update value at method loadMedia
public void loadMedia(String url, MediaMetadata movieMetadata, CastSession castSession, boolean autoPlay, long position) {
if (castSession == null || !castSession.isConnected()) {
return;
}
MediaInfo mediaInfo = new MediaInfo.Builder(url)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("videos/m3u8")
.setMetadata(movieMetadata)
.build();
mRemoteMediaClient = castSession.getRemoteMediaClient();
mRemoteMediaClient.addListener(mRemoteMediaClientListener);
mRemoteMediaClient.load(mediaInfo, autoPlay, position);
mIdleReason = MediaStatus.IDLE_REASON_NONE;
}
3) Update value at onStatusUpdate:
private RemoteMediaClient.Listener mRemoteMediaClientListener = new RemoteMediaClient.Listener() {
#Override
public void onStatusUpdated() {
if (mRemoteMediaClient == null || mediaPlayerListener == null) {
return;
}
MediaStatus mediaStatus = mRemoteMediaClient.getMediaStatus();
if (mediaStatus != null) {
int playerStatus = mediaStatus.getPlayerState();
Log.d("PlayerState", "onStatusUpdated() called, progress= "+mSeekBar.getProgress() +", stream duration= "+ mRemoteMediaClient.getStreamDuration()+" mSeekBar.getProgress() == mRemoteMediaClient.getStreamDuration()="+(mSeekBar.getProgress() == mRemoteMediaClient.getStreamDuration()));
Log.d("PlayerState", "onStatusUpdated() called playerStatus="+playerStatus+", idleReason="+mediaStatus.getIdleReason());
if (playerStatus == MediaStatus.PLAYER_STATE_PLAYING) {
mediaPlayerListener.playing();
mIdleReason = MediaStatus.IDLE_REASON_FINISHED;
} else if (playerStatus == MediaStatus.PLAYER_STATE_BUFFERING) {
mediaPlayerListener.buffering();
mIdleReason = MediaStatus.IDLE_REASON_FINISHED;
} else if (playerStatus == MediaStatus.PLAYER_STATE_PAUSED) {
mediaPlayerListener.paused();
} else if (playerStatus == MediaStatus.IDLE_REASON_INTERRUPTED) {
mediaPlayerListener.error();
} else if (playerStatus == MediaStatus.IDLE_REASON_ERROR) {
mediaPlayerListener.error();
}else if(playerStatus == MediaStatus.PLAYER_STATE_IDLE && mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_FINISHED&& mIdleReason == MediaStatus.IDLE_REASON_FINISHED){
mediaPlayerListener.played();
}
}
}
#Override
public void onMetadataUpdated() {
Log.d("", "onMetadataUpdated: ");
}
#Override
public void onQueueStatusUpdated() {
Log.d("", "onQueueStatusUpdated: ");
}
#Override
public void onPreloadStatusUpdated() {
Log.d("", "onPreloadStatusUpdated: ");
}
#Override
public void onSendingRemoteMediaRequest() {
Log.d("", "onSendingRemoteMediaRequest: ");
}
#Override
public void onAdBreakStatusUpdated() {
Log.d("", "onAdBreakStatusUpdated: ");
}
};

android: why getrotationmatrix return false?

I want to get the orientation of my phone and I have using this code that I find lot of people using it. this is the code
public void onSensorChanged(SensorEvent event) {
//if the data sensor is unreliabel
if(event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
return;
//gets the value
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
gravity = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
geomag = event.values.clone();
break;
}
getOrientation();
}
private void getOrientation(){
//if gravity n geomag have value, find the rotation matrix
if(gravity != null && geomag != null){
//check the rotation matrix found
boolean success = SensorManager.getRotationMatrix(inR, I, gravity, geomag);
if(success){
SensorManager.getOrientation(inR, orientVals);
azimuth = Math.toDegrees(orientVals[0]);
TextView azi = (TextView) findViewById(R.id.textAzi);
azi.setText("azi : " + azimuth);
}
TextView cek = (TextView) findViewById(R.id.cek);
cek.setText("rotation: "+success);
}
but why the getrotationmatrix always return to false?
where is the problem?
I've try again and get the solution
but I change the code to become like below
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
for(int i=0; i<3; i++){
accelValues[i] = event.values[i];
}
if(compassValues[0] != 0)
ready = true;
break;
case Sensor.TYPE_MAGNETIC_FIELD:
for(int i=0; i<3; i++){
compassValues[i] = event.values[i];
}
if(accelValues[2] != 0)
ready = true;
break;
}
if(!ready)
return;
boolean cek = SensorManager.getRotationMatrix(inR, inclineMatrix, accelValues, compassValues);
if(cek){
SensorManager.getOrientation(inR, prefValues);
mInclination = SensorManager.getInclination(inclineMatrix);
//display every 30th values
if(counter++ % 30 == 0){
//do your code, what you want to do to the result
counter = 1;
}
}
and everything work well
Make sure that you have registered your listeners to listen to the accelerometer, magmetic field and gyro (optional). You do this in the onResume method. If you forget to do this you will get "false" return value when calling getRotationMatrix.
I hope this helps!
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
// do more staff here..
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(
this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL );
mSensorManager.registerListener(
this,
mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_NORMAL );
mSensorManager.registerListener(
this,
mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
SensorManager.SENSOR_DELAY_NORMAL );
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
The problem is with this part of code:
if(event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
return;
For accelerometer event.accuracy return SensorManager.SENSOR_STATUS_UNRELIABLE that is why gravity is always null.

Categories

Resources