android: why getrotationmatrix return false? - android

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.

Related

How to sync head movement with Google Cardboard in 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];
}
}
}
};

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;
}
}

SensorManager, the if and else of the same condition are executed at the same time

while I was debugging the code posted below, I decided to place a Toast in the body of the ifstatement and in the body of the else statement, so I can see where the error comes from. When I ran the app I found the both Toasts are executed. initially the Toast within the if statement shows and and after few seconds the display switches to the Toast within the else statement and they keep alternating. I do not know how a condition is evaluated to be true and and false at the same time. Please provide logical explanation and suggestions to solve this problem.
JavaCode:
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
accelerometerValues = event.values.clone();
tvAcc_XReading.setText(Float.toString(accelerometerValues[0]));
tvAcc_YReading.setText(Float.toString(accelerometerValues[1]));
tvAcc_ZReading.setText(Float.toString(accelerometerValues[2]));
case Sensor.TYPE_MAGNETIC_FIELD:
magnetometerValues = event.values.clone();
tvMagneto_XReading.setText(Float.toString(magnetometerValues[0]));
tvMagneto_YReading.setText(Float.toString(magnetometerValues[1]));
tvMagneto_ZReading.setText(Float.toString(magnetometerValues[2]));
}
if (accelerometerValues != null && magnetometerValues != null) {
float [] matrixR = new float[9];
float [] matrixI = new float[9];
boolean success = SensorManager.getRotationMatrix(matrixR, matrixI, accelerometerValues,
magnetometerValues);
if (success) {
Toast.makeText(getApplicationContext(), "SUCCESS", Toast.LENGTH_LONG).show();
float [] orientationMatrix = new float[3];
SensorManager.getOrientation(matrixR, orientationMatrix);
tvAzimuthReading.setText(Float.toString(orientationMatrix[0]));
tvPitchReading.setText(Float.toString(orientationMatrix[1]));
tvRollReading.setText(Float.toString(orientationMatrix[2]));
} else {
Toast.makeText(getApplicationContext(), "No Rmatrix", Toast.LENGTH_LONG).show();
}
}
Try adding a break statement to your cases, otherwise it will fall through.
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
accelerometerValues = event.values.clone();
tvAcc_XReading.setText(Float.toString(accelerometerValues[0]));
tvAcc_YReading.setText(Float.toString(accelerometerValues[1]));
tvAcc_ZReading.setText(Float.toString(accelerometerValues[2]));
break;
case Sensor.TYPE_MAGNETIC_FIELD:
magnetometerValues = event.values.clone();
tvMagneto_XReading.setText(Float.toString(magnetometerValues[0]));
tvMagneto_YReading.setText(Float.toString(magnetometerValues[1]));
tvMagneto_ZReading.setText(Float.toString(magnetometerValues[2]));
break;
}

how to implement onTouchListener?

I have a toggleButton that I wish to set an onTouchListener on. I am getting some errors however so I don't think I'm doing this right.
I have declared my button.
private ToggleButton pushBtn;
I have set my activity to implement View.onTouchListener.
public class InCallActivity extends SherlockFragmentActivity implements View.OnTouchListener {
In onCreate I have written:
pushBtn = (ToggleButton) findViewById(R.id.PTT_button3);
pushBtn.setOnTouchListener(this);
Then I have tried to use the listener in the class::
pushBtn.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event)
{
// if more than one call, change this code
int callId = 0;
for (SipCallSession callInfo : callsInfo)
{
callId = callInfo.getCallId();
Log.e(TAG, "" + callInfo.getCallId());
}
final int id = callId;
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
// press
pushBtn.setBackgroundResource(R.drawable.btn_blue_glossy);
pushBtn.setChecked(true);
OnDtmf(id, 17, 10);
OnDtmf(id, 16, 9);
return true;
}
case MotionEvent.ACTION_UP:
{
// release
pushBtn.setBackgroundResource(R.drawable.btn_lightblue_glossy);
pushBtn.setChecked(false);
OnDtmf(id, 18, 11);
OnDtmf(id, 18, 11);
return true;
}
default:
return false;
}
}
});
I have multiple errors, it says onTouch is not implemented, but I have done so?
Also I placed the listener in the class and it now complains about the method before it saying:
Syntax error on token "}", delete this token
But That was fine until I added the listener, does a listener have to be in a method or something?
At the end of my listener I get the error:
Syntax error, insert "}" to complete MethodBody
But I do now know why.
EDIT UPDATE
Here is my onCreate, I get a nullpointerexception:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//handler.setActivityInstance(this);
Log.d(THIS_FILE, "Create in call");
setContentView(R.layout.in_call_main);
SipCallSession initialSession = getIntent().getParcelableExtra(SipManager.EXTRA_CALL_INFO);
synchronized (callMutex) {
callsInfo = new SipCallSession[1];
callsInfo[0] = initialSession;
}
bindService(new Intent(this, SipService.class), connection, Context.BIND_AUTO_CREATE);
prefsWrapper = new PreferencesProviderWrapper(this);
// Log.d(THIS_FILE, "Creating call handler for " +
// callInfo.getCallId()+" state "+callInfo.getRemoteContact());
powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
| PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE,
"com.csipsimple.onIncomingCall");
wakeLock.setReferenceCounted(false);
takeKeyEvents(true);
// Cache findViews
mainFrame = (ViewGroup) findViewById(R.id.mainFrame);
inCallControls = (InCallControls) findViewById(R.id.inCallControls);
inCallAnswerControls = (InCallAnswerControls) findViewById(R.id.inCallAnswerControls);
activeCallsGrid = (InCallInfoGrid) findViewById(R.id.activeCallsGrid);
heldCallsGrid = (InCallInfoGrid) findViewById(R.id.heldCallsGrid);
pushBtn = (ToggleButton) findViewById(R.id.PTT_button3);
//pushBtn.setOnTouchListener((OnTouchListener) this);
attachVideoPreview();
inCallControls.setOnTriggerListener(this);
inCallAnswerControls.setOnTriggerListener(this);
if(activeCallsAdapter == null) {
activeCallsAdapter = new CallsAdapter(true);
}
activeCallsGrid.setAdapter(activeCallsAdapter);
if(heldCallsAdapter == null) {
heldCallsAdapter = new CallsAdapter(false);
}
heldCallsGrid.setAdapter(heldCallsAdapter);
ScreenLocker lockOverlay = (ScreenLocker) findViewById(R.id.lockerOverlay);
lockOverlay.setActivity(this);
lockOverlay.setOnLeftRightListener(this);
/*
middleAddCall = (Button) findViewById(R.id.add_call_button);
middleAddCall.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
onTrigger(ADD_CALL, null);
}
});
if (!prefsWrapper.getPreferenceBooleanValue(SipConfigManager.SUPPORT_MULTIPLE_CALLS)) {
middleAddCall.setEnabled(false);
middleAddCall.setText(R.string.not_configured_multiple_calls);
}
*/
// Listen to media & sip events to update the UI
registerReceiver(callStateReceiver, new IntentFilter(SipManager.ACTION_SIP_CALL_CHANGED));
registerReceiver(callStateReceiver, new IntentFilter(SipManager.ACTION_SIP_MEDIA_CHANGED));
registerReceiver(callStateReceiver, new IntentFilter(SipManager.ACTION_ZRTP_SHOW_SAS));
proximityManager = new CallProximityManager(this, this, lockOverlay);
keyguardManager = KeyguardWrapper.getKeyguardManager(this);
dialFeedback = new DialingFeedback(this, true);
if (prefsWrapper.getPreferenceBooleanValue(SipConfigManager.PREVENT_SCREEN_ROTATION)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
if (quitTimer == null) {
quitTimer = new Timer("Quit-timer");
}
useAutoDetectSpeaker = prefsWrapper.getPreferenceBooleanValue(SipConfigManager.AUTO_DETECT_SPEAKER);
applyTheme();
proximityManager.startTracking();
inCallControls.setCallState(initialSession);
inCallAnswerControls.setCallState(initialSession);
pushBtn.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
//if more than one call, change this code
int callId = 0;
for (SipCallSession callInfo : callsInfo) {
callId = callInfo.getCallId();
Log.e(TAG, ""+callInfo.getCallId());
}
final int id= callId;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
//press
pushBtn.setBackgroundResource(R.drawable.btn_blue_glossy);
pushBtn.setChecked(true);
OnDtmf(id, 17, 10);
OnDtmf(id, 16, 9);
return true;
}
case MotionEvent.ACTION_UP: {
//release
pushBtn.setBackgroundResource(R.drawable.btn_lightblue_glossy);
pushBtn.setChecked(false);
OnDtmf(id, 18, 11);
OnDtmf(id, 18, 11);
return true;
}
default:
return false;
}
}
});
}
The line with the nullpointer 250 is pushBtn.setOnTouchListener(new OnTouchListener() {
You should add '}' on closing touch method.
Eclipse sometimes makes some mistakes by itself.
You're code seems right, try to cut all of your code and then paste it again in the same position.
Also try to remove all of the import at the beginning of the class and then reimporting everything by pressing
ctrl + SHIFT + o (cmd+shift+o on a mac)
another solution is to put a
return false;
at the very end of the onTouch method

Categories

Resources