我正在开发一个应用程序,通过使用加速度计和光传感器数据判断手机的移动和环境来自动设置系统警报。为此,我使用的是IntentService + Alarm Manager。我希望我的服务能够获取传感器数据并进行广播。我在另一个活动中捕获广播并将传感器值写入文件。我使用报警管理器,以便我可以定期获取传感器值。我面临两个问题:
正如我在Logcat上看到的那样,我的intentservice中只有'onCreate'和'onHandleIntent'方法正在执行。 'onSensorChanged'方法未被执行。是因为我在'onHandle'方法中发送广播,并且该服务除此之外不执行任何其他操作。如果是这样,请指导我如何实现在服务中获取传感器数据并将其发送回活动以定期执行进一步处理的用例。 以下是我的代码:
MainActivity.java
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scheduleAlarm();
}
// Setup a recurring alarm every 15 minutes
public void scheduleAlarm() {
Toast.makeText(MainActivity.this, "Scheduling Alarm.", Toast.LENGTH_SHORT).show();
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(this, AlarmReceiver.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 5 seconds
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
// First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
// Interval can be INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_DAY
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
AlarmManager.INTERVAL_FIFTEEN_MINUTES, pIntent);
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
public static final String ACTION = "com.example.tyagi.smartalarm.alarm";
// Triggered by the Alarm periodically (starts the service to run task)
@Override
public void onReceive(Context context, Intent intent) {
Log.d("AlarmReceiver", "Alarm called.");
Intent i = new Intent(context, sensorService.class);
i.putExtra("foo", "bar");
context.startService(i);
}
}
IntentService.java
public class sensorService extends IntentService implements SensorEventListener {
public static final String ACTION = "com.example.tyagi.smartalarm.sensorService";
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;
TextView xCoor; // declare X axis object
TextView yCoor; // declare Y axis object
TextView zCoor; // declare Z axis object
TextView lightVal;
// constructor for the java class. Mandatory, otherwise was showing error.
public sensorService() {
super("sensorService");
}
@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("sensorService","onCreate");
sensorManager=(SensorManager) getSystemService(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.
mAccel = 0.00f;
mAccelCurrent = SensorManager.GRAVITY_EARTH;
mAccelLast = SensorManager.GRAVITY_EARTH;
}
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("sensorService", "onSensorChanged.");
/* check sensor type */
if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
mGravity = event.values.clone();
// assign directions
float x=event.values[0];
float y=event.values[1];
float z=event.values[2];
xCoor.setText("X: "+x);
yCoor.setText("Y: "+y);
zCoor.setText("Z: "+z);
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 > .5)
{
Toast.makeText(sensorService.this, "Movement Detected.", Toast.LENGTH_SHORT).show();
}
}
else if(event.sensor.getType()==Sensor.TYPE_LIGHT)
{
float l = event.values[0];
lightVal.setText(l+"");
}
/* unregister if we just want one result. */
sensorManager.unregisterListener(this);
}
@Override
protected void onHandleIntent(Intent intent) {
// This describes what will happen when service is triggered
// Fetch data passed into the intent on start
String val = intent.getStringExtra("foo");
// Construct an Intent tying it to the ACTION (arbitrary event namespace)
Intent in = new Intent(ACTION);
in.putExtra("resultCode", Activity.RESULT_OK);
in.putExtra("resultValue","My result value. Passed in : " + val);
// Fire the broadcast with intent packaged
LocalBroadcastManager.getInstance(this).sendBroadcast(in);
// or sendBroadcast(in) for a normal broadcast;
Log.d("sensorService", "Service running");
}
}
RegularService:正如@Mike建议我尝试使用常规服务。这次也只是执行了onCreate方法。休息没有任何反应。
public class MyService extends Service implements SensorEventListener{
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;
@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(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.
mAccel = 0.00f;
mAccelCurrent = SensorManager.GRAVITY_EARTH;
mAccelLast = SensorManager.GRAVITY_EARTH;
}
public int onStartCommand(){
Log.d("MyService","onStartCommand");
return START_STICKY;
}
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("sensorService", "onSensorChanged.");
Toast.makeText(MyService.this, "onSensorChanged.", Toast.LENGTH_SHORT).show();
/* check sensor type */
if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
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 > 3)
{
Toast.makeText(MyService.this, "Movement Detected.", Toast.LENGTH_SHORT).show();
}
}
else if(event.sensor.getType()==Sensor.TYPE_LIGHT)
{
float l = event.values[0];
}
/* unregister if we just want one result. */
// sensorManager.unregisterListener(this);
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}