I have created a simple activity-service android app in which I call the service periodically using alarmmanager
. In the service, I capture values from accelerometer
sensor and light sensor
, put them in a broadcast and broadcast the intent. In my MainActivity
, I receive the broadcast and try to show the sensor values. But I keep getting a NUll Obect Reference Error
. I LOGCAT
the sensor values in the service to check if the sensor values are being captured and I get a output. Is is only when I try to access them via a returned intent in the main activity I get the error. I have tried to debug it a lot but really can't fathom where my logic is going wrong. Following are the relevant code samples :
MainActivity.java
// Define the callback for what to do when data is received
private BroadcastReceiver testReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG,"onReceive");
// int resultCode = intent.getIntExtra("resultCode", RESULT_CANCELED);
Intent returnIntent = getIntent();
Bundle results = returnIntent.getExtras();
float accelValue = results.getFloat("accelVal");
float lightValue = results.getFloat("lightVal");
Toast.makeText(MainActivity.this, accelValue + " " + lightValue, Toast.LENGTH_SHORT).show();
// if (resultCode == RESULT_OK) {
// String accelValue = results.getString("accelVal");
// String lightValue = results.getString("lightVal");
// Toast.makeText(MainActivity.this, accelValue + " " + lightValue, Toast.LENGTH_SHORT).show();
// }
}
};
Service.java
public class MyService extends Service implements SensorEventListener{
private static final String LOG_TAG = "MyService::";
public static final String ACTION = "com.example.tyagi.smartalarm.MyService";
int count=0;
public MyService() {
}
private SensorManager sensorManager; // this instance of SensorManager class will be used to get a reference to the sensor service.
private Sensor mSensor,lSensor; // this instance of Sensor class is used to get the sensor we want to use.
private float[] mGravity;
private float mAccel;
private float mAccelCurrent;
private float mAccelLast;
float l;
Intent in = new Intent(ACTION); // create an intent to broadcast.
Bundle bundle = new Bundle();
public void onAccuracyChanged(Sensor sensor,int accuracy){
}
// // if sensor value is changes, change the values in the respective textview.
public void onSensorChanged(SensorEvent event){
Log.d(LOG_TAG, "onSensorChanged.");
// in.putExtra("resultCode",Activity.RESULT_OK);
/* check sensor type */
if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
Log.d(LOG_TAG, "onSensorChanged,accelerometer");
count+=1;
Log.d(LOG_TAG,"count :"+count);
mGravity = event.values.clone();
// assign directions
float x=event.values[0];
float y=event.values[1];
float z=event.values[2];
float x1=event.values[0];
float y1=event.values[1];
float z1=event.values[2];
mAccelLast = mAccelCurrent;
mAccelCurrent = (float)Math.sqrt(x*x + y*y + z*z); // we calculate the length of the event because these values are independent of the co-ordinate system.
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel*0.9f + delta;
if(mAccel >= 0)
{
bundle.putFloat("accelVal", mAccel);
// in.putExtra("accelVal",Float.toString(mAccel));
}
}
if(event.sensor.getType()==Sensor.TYPE_LIGHT)
{
l = event.values[0];
bundle.putFloat("lightVal", l);
// in.putExtra("lightVal",Float.toString(l));
}
in.putExtras(bundle);
Log.d(LOG_TAG, "mAccel : " + Float.toString(mAccel));
Log.d(LOG_TAG,"lightsensr : "+Float.toString(l));
if(count ==2) {
LocalBroadcastManager.getInstance(this).sendBroadcast(in);
stopSelf();
}
}
@Override
public void onCreate() {
super.onCreate(); // if you override onCreate(), make sure to call super().
// If a Context object is needed, call getApplicationContext() here.
Log.d("MyService", "onCreate");
sensorManager=(SensorManager) getSystemService(Context.SENSOR_SERVICE); // get an instance of the SensorManager class, lets us access sensors.
mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); // get Accelerometer sensor from the list of sensors.
lSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); // get light sensor from the list of sensors.
sensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, lSensor, SensorManager.SENSOR_DELAY_NORMAL);
mAccel = 0.00f;
mAccelCurrent = SensorManager.GRAVITY_EARTH;
mAccelLast = SensorManager.GRAVITY_EARTH;
}
public int onStartCommand(Intent intent, int flags, int startId){
Log.d("MyService", "onStartCommand");
return START_STICKY;
}
@Override
public void onDestroy() {
Log.d( LOG_TAG, "onDestroy" );
sensorManager.unregisterListener(this);
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
The count
variable used in the Service.java is just so that the sensor runs twice before broadcasting the values.
Any help is appreciated.
You should be checking the Intent
passed into onReceive()
for your extras, not the Intent
returned by getIntent()
.
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG,"onReceive");
//Intent returnIntent = getIntent();
Bundle results = intent.getExtras();
...
}
The getIntent()
method is a member of the Activity
class, and normally returns the Intent
used to start the current Activity
. (Your anonymous BroadcastReceiver
class is in the Activity
's scope, and therefore has access to that method.)
The Intent
passed into the onReceive()
method is the one that you broadcast with all your extras.