I just started out on android and java yesterday, and i'm having a problem. I'm trying to output a sensor's values to some TextViews. The text updates, but with the values set at definition. onSensorChanged should update these values right?
import [...]
public class MainActivity extends Activity implements SensorEventListener {
public float[] gravity = {0,0,0};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView gravxTxtView = (TextView) findViewById(R.id.gravxTxtView);
final TextView gravyTxtView = (TextView) findViewById(R.id.gravyTxtView);
final TextView gravzTxtview = (TextView) findViewById(R.id.gravzTxtView);
final Handler handler = new Handler();
handler.postDelayed(
new Runnable() {
#Override
public void run() {
gravxTxtView.setText("Gravity x: " + Float.toString((gravity[0])));
gravyTxtView.setText("Gravity y: " + Float.toString((gravity[1])));
gravzTxtview.setText("Gravity z: " + Float.toString((gravity[2])));
}
}, 500);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event) {
if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
gravity[0] = event.values[0];
gravity[1] = event.values[1];
gravity[2] = event.values[2];
}
}
}
There are some serious steps you are missing
1. Get the instance of sensor manager
SensorManager sensorManager=(SensorManager)getSystemService(SENSOR_SERVICE);
2. Get the instance of the sensor
Sensor accel=sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
3. Register sensor to the lister class which implements SensorEventListener in your case you have implemented on the MainActivity so it will be this
sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_NORMAL);
now when certain change will happen it will call the onSensorChanged method ,please let me know its working or not
Related
I am trying to use accelerometer to press a button in android studio for my dice app. Does anyone know how to hook it up to a button, so that when I shake my phone the dice will roll? I've tried to use SensorEventListener but couldn't get it to work. Thanks for any feedback/suggestion.
PS. I'm a noob.
Here is my java code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button rollButton;
rollButton = findViewById(R.id.rollButton);
final ImageView leftDice = findViewById(R.id.diceLeft);
final ImageView rightDice = findViewById(R.id.diceRight);
final ImageView topDice = findViewById(R.id.diceTop);
final int [] diceArray = {
R.drawable.perspective_dice_one,
R.drawable.perspective_dice_two,
R.drawable.perspective_dice_three,
R.drawable.perspective_dice_four,
R.drawable.perspective_dice_five,
R.drawable.perspective_dice_six,
};
rollButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Dice", "You pressed the button!");
Random randomNumberGenerator = new Random();
int number = randomNumberGenerator.nextInt(6);
Log.d("Dice", "The random number is: " + number);
leftDice.setImageResource(diceArray[number]);
number = randomNumberGenerator.nextInt(6);
rightDice.setImageResource(diceArray[number]);
number = randomNumberGenerator.nextInt(6);
topDice.setImageResource(diceArray[number]);
}
});
}
}
I created a simple app to learn how to use sensor heart beat with one button and label here is my code:
public class MainActivity extends AppCompatActivity implements SensorEventListener {
Button show;
TextView showHeartRate;
SensorManager sensorMgr;
Sensor heartRate;
String heartRateValue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = (Button) findViewById(R.id.button);
show.setOnClickListener(displayHeartRate);
showHeartRate = (TextView) findViewById(R.id.showHeartRate);
sensorMgr = (SensorManager)this.getSystemService(SENSOR_SERVICE);
heartRate = sensorMgr.getDefaultSensor(Sensor.TYPE_HEART_RATE);
}
View.OnClickListener displayHeartRate = new View.OnClickListener() {
#Override
public void onClick(View view) {
showHeartRate.setText(heartRateValue);
}
};
#Override
protected void onResume() {
super.onResume();
sensorMgr.registerListener(this,heartRate,SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause() {
super.onPause();
sensorMgr.unregisterListener(this);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
heartRateValue = Integer.toString(sensorEvent.sensor.getType());
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
I add to the manifest:
<uses-permission android:name="android.permission.BODY_SENSORS"/>
the problem is that the onSensorChanged() is not called.
i check a lot of solutions here but i did not find anything
First, why would you expect it to ask permissions to use your camera if its heartrate sensor that you are trying to use?
Second, I think by the time you click 'display heartrate', you just don't have any data from the sensor yet (heartRateValue is empty), and when data finally comes you don't really update UI, you only update your state. What I suggest is to update your UI state on every sensor change, for example:
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
heartRateValue = Integer.toString(sensorEvent.sensor.getType());
showHeartRate.setText(heartRateValue);
}
or you can avoid code duplication (even thought its only one line), create a setter and and call it from both click handler and sensor handler:
private void setHeartrate(String rate) {
showHeartRate.setText(rate);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
heartRateValue = Integer.toString(sensorEvent.sensor.getType());
setHeartrate(heartRateValue);
}
View.OnClickListener displayHeartRate = new View.OnClickListener() {
#Override
public void onClick(View view) {
setHeartrate(heartRateValue);
}
};
Third, you are not using data from your sensor, look at SensorEvent, data comes in values array and you are only trying to displat sensor type, why? Try this:
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
heartRateValue = Integer.toString(sensorEvent.values.length > 0 ? sensorEvent.values[0] : 0.0f);
showHeartRate.setText(heartRateValue);
}
I have a problem with code. I have two classes: MainActivity where i checking if sensor (in this case light sensor) is available and if yes - i try to get date from sensor from another class LightSensor, but result is always null. I think that i'm doing something wrong with listener but i don't know what.. and i'm sitting on this couple of hours and still nothing.. If you have any idea, please write and help me.
MainActivity class:
`public class MainActivity extends Activity implements EventListener {
SensorManager mSensorManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView wyswietl = (TextView)findViewById(R.id.res);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
LightSensor mLightSensor = new LightSensor(getBaseContext());
if (mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) != null){
//mLightSensor.register();
String newLux = mLightSensor.getLux();
wyswietl.setText("Light level: " + newLux);
}
else{
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}`
and in MainActivioty class i don't know it argument in constructor :
LightSensor mLightSensor = new LightSensor(getBaseContext()); is good...
LightSensor class:
`public class LightSensor implements SensorEventListener {
public SensorManager mSensorManagerx;
public Sensor lightManager;
public String lux;
Context context;
public LightSensor(Context context){
//public void onCreateLight(Context context){
this.context = context;
mSensorManagerx = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
lightManager = mSensorManagerx.getDefaultSensor(Sensor.TYPE_LIGHT);
}
public void register(){
mSensorManagerx.registerListener(this, lightManager, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
lux = Float.toString(event.values[0]);
}
public String getLux(){
return lux;
}
public void unregister(){
mSensorManagerx.unregisterListener(this);
}
}`
You should not use a getter for this purpose, because the value your getting will be initialized after a unknown time. So it could still be null when you're calling the getLux method.
What you should do is use a listener pattern. I have changed your code a bit to give you an example implementation.
LightSensor:
public class LightSensor implements SensorEventListener {
public static interface LightSensorListener {
abstract void onLightSensorChanged(String lux);
}
private LightSensorListener listener;
private SensorManager mSensorManagerx;
private Sensor lightManager;
public LightSensor(Context context) {
mSensorManagerx = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
lightManager = mSensorManagerx.getDefaultSensor(Sensor.TYPE_LIGHT);
}
public void setListener(LightSensorListener listener) {
this.listener = listener;
}
public boolean register() {
return mSensorManagerx.registerListener(this, lightManager, SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event) {
if (listener != null) {
listener.onLightSensorChanged(Float.toString(event.values[0]));
}
}
public void unregister() {
mSensorManagerx.unregisterListener(this);
}
}
Activity:
public class ActivityLightSensor extends Activity implements LightSensorListener {
private TextView text;
private LightSensor mLightSensor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.test);
mLightSensor = new LightSensor(getBaseContext());
mLightSensor.setListener(this);
}
#Override
public void onLightSensorChanged(String lux){
text.setText("Light level: " + lux);
}
#Override
protected void onResume() {
super.onStart();
if(!mLightSensor.register()){
Toast.makeText(this, "Light sensor not supported!", Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onPause() {
super.onStop();
mLightSensor.unregister();
}
}
onSensorChanged event is not called just after you created listener. It is called after something will change sensot value, then it will be called. So you should implement some callback, or, as for me, better would be to implement SensorEventListener in your activity, then just in onSensorChanged event method call
wyswietl.setText("Light level: " + newLux);
been working on a prject for a while, now I want it so that when the user touches the screen it changes the color of the textView(DigitalClock). I'm a bit of a noob when it comes to java so I really need a fully working example if possible? Here's my code so far:
public class MainActivity extends Activity {
private static final Random RANDOM = new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
Handler handler = new RandomMoveHandler((TextView) findViewById(R.id.digitalClock1));
handler.sendEmptyMessage(0);
}
private static class RandomMoveHandler extends Handler {
private final WeakReference<TextView> textViewWeakReference;
private RandomMoveHandler(TextView textView) {
this.textViewWeakReference = new WeakReference<TextView>(textView);
}
#Override
public void handleMessage(Message msg) {
TextView textView = textViewWeakReference.get();
if (textView == null) {
Log.i(TAG, "WeakReference is gone so giving up.");
return;
}
int x = RANDOM.nextInt(670 - 100);
int y = RANDOM.nextInt(1230 - 100);
Log.i(TAG, String.format("Moving text view to (%d, %d)", x, y));
textView.setX(x);
textView.setY(y);
//change the text position here
this.sendEmptyMessageDelayed(0, 30000);
}
}
textView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// use any of your own colors here...
textView.setTextColor(android.R.color.holo_purple);
return true;
}
});
See also https://developer.android.com/reference/android/widget/TextView.html#setTextColor(int)
I'm trying to detect the y-axis rotation angle (forward-backward tilt when holding in landscape) but I'm obviously doing thins wrong as the onSensorChanged event never gets triggered
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
...
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
mSensorManager.registerListener(this.mSensorEventListener, mSensor, SensorManager.SENSOR_DELAY_GAME);
}
...
private SensorEventListener mSensorEventListener = new SensorEventListener() {
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
float aX = event.values[1];
float aY = event.values[2];
double angle = aY * (Math.PI / 180);
btnStop.setText(Double.toString(angle));
};
Your device probably does not have Sensor.TYPE_ROTATION_VECTOR