从 android 中的服务接收广播时出现 NULL 对象引用错误
NULL object reference error on receiving broadcast from a service in android
我创建了一个简单的 activity-服务 android 应用程序,我在其中使用 alarmmanager
定期调用该服务。在服务中,我从 accelerometer
传感器和 light sensor
捕获值,将它们放入广播中并广播意图。在我的 MainActivity
中,我收到广播并尝试显示传感器值。但我一直收到 NUll Obect Reference Error
。我 LOGCAT
服务中的传感器值,以检查是否正在捕获传感器值并获得输出。仅当我尝试通过主 activity 中返回的意图访问它们时才收到错误。我试过很多次调试,但真的无法理解我的逻辑哪里出了问题。以下是相关代码示例:
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");
}
}
Service.java 中使用的 count
变量只是为了让传感器在广播值之前运行两次。
感谢您的帮助。
您应该检查传递给 onReceive()
的 Intent
是否有额外内容,而不是 getIntent()
返回的 Intent
。
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG,"onReceive");
//Intent returnIntent = getIntent();
Bundle results = intent.getExtras();
...
}
getIntent()
方法是Activity
class的成员,通常returnsIntent
用来启动当前Activity
. (您的匿名 BroadcastReceiver
class 在 Activity
的范围内,因此可以访问该方法。)
传递给 onReceive()
方法的 Intent
是您与所有额外内容一起广播的方法。
我创建了一个简单的 activity-服务 android 应用程序,我在其中使用 alarmmanager
定期调用该服务。在服务中,我从 accelerometer
传感器和 light sensor
捕获值,将它们放入广播中并广播意图。在我的 MainActivity
中,我收到广播并尝试显示传感器值。但我一直收到 NUll Obect Reference Error
。我 LOGCAT
服务中的传感器值,以检查是否正在捕获传感器值并获得输出。仅当我尝试通过主 activity 中返回的意图访问它们时才收到错误。我试过很多次调试,但真的无法理解我的逻辑哪里出了问题。以下是相关代码示例:
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");
}
}
Service.java 中使用的 count
变量只是为了让传感器在广播值之前运行两次。
感谢您的帮助。
您应该检查传递给 onReceive()
的 Intent
是否有额外内容,而不是 getIntent()
返回的 Intent
。
public void onReceive(Context context, Intent intent) {
Log.d(LOG_TAG,"onReceive");
//Intent returnIntent = getIntent();
Bundle results = intent.getExtras();
...
}
getIntent()
方法是Activity
class的成员,通常returnsIntent
用来启动当前Activity
. (您的匿名 BroadcastReceiver
class 在 Activity
的范围内,因此可以访问该方法。)
传递给 onReceive()
方法的 Intent
是您与所有额外内容一起广播的方法。