2012-02-28 74 views
2

我目前正在開發一款應用程序,該應用程序應該每兩秒收集一次加速度計和麥克風數據。爲此,我啓動了一個服務(在內部運行一個計時器),以便在應用程序在後臺運行時收集數據。到現在爲止還挺好。如何在手機處於空閒狀態時收集加速度計數據

定時器啓動,收集數據並將該數據寫入XML文件。但是在看過生成的XML文件後,我意識到,當手機處於空閒狀態時,加速度計的值始終是相同的。我甚至使用喚醒鎖來每兩秒「喚醒」手機,但即使這樣也行不通。

下面是相關代碼:

@Override 
public void onCreate() { 
    super.onCreate(); 

    Toast.makeText(this, "Background Service Created", Toast.LENGTH_SHORT) 
      .show(); 
    Log.d(TAG, "onCreate Service"); 

    this.startActivities(); 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 

    // Kill timer, sensors and XML file 
    this.stopActivities(); 

    Toast.makeText(this, "Background Service Stopped", Toast.LENGTH_SHORT) 
      .show(); 
    Log.d(TAG, "onDestroy"); 
} 

@Override 
public void onStart(Intent intent, int startid) { 
    Toast.makeText(this, "Background Service Started", Toast.LENGTH_SHORT).show(); 
    Log.d(TAG, "onStart"); 
} 

/** 
* Expanded modification function. 
*/ 
private void startExpandedNotification(){ 
    //Id for the intent of the expanded notification 
    final int myID = 1234; 

    //The intent to launch when the user clicks the expanded notification 
    Intent i = new Intent(this, MainMovement.class); 
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 
    PendingIntent pendIntent = PendingIntent.getActivity(this, 0, i, 0); 

    //This constructor is deprecated. Use Notification.Builder instead if programming for 3.0+ 
    Notification notice = new Notification(R.drawable.ic_launcher, "Movement Sampling Activated", System.currentTimeMillis()); 

    //This method is deprecated. Use Notification.Builder instead if programming for 3.0+ 
    notice.setLatestEventInfo(this, "Movement Sampling", "Sensors activated", pendIntent); 

    notice.flags |= Notification.FLAG_NO_CLEAR; 
    startForeground(myID, notice); 
} 

/** 
* Stop Expanded Notification 
*/ 
private void stopExpandedNotification(){ 
    stopForeground(true); 
} 

/** 
* Starts everything that the service needs to collect the sensors data 
* (timer, xml file, sensors, expanded notification) 
*/ 
private void startActivities() { 
    // Define output file path 
    OUTPUT_FILE = Environment.getExternalStorageDirectory() 
      .getAbsolutePath() + "/Ze";// also added ""/Ze here 
    OUTPUT_FILE += "/audiorecordtest.3gp"; 

    timer = new Timer(); // If I take this line out, it will lead to an 
          // exception. But if I do so, the acc values are 
          // measured while the phone is in the idle state (works only on samsung spika) 
    timer.scheduleAtFixedRate(new mainTask(), 0, _refreshRate); 

    xml = new DataStore(); 

    this.startRecordingMic(); 
    this.startRecordingAcc(); 

    startExpandedNotification(); 

    _sampling = true; 
} 

/** 
* Stops everything that the service needs to collect the sensors data 
* (timer, xml file, sensors, expanded notification) 
*/ 
private void stopActivities() { 
    timer.cancel(); 
    //Log.e(TAG, "timer: CANCELLED"); 

    // close xml file 
    xml.closeFile(); 
    //Log.e(TAG, "XML: CLOSED"); 

    // unregister sensor 
    _sensorManager.unregisterListener(accelerationListener); 
    //Log.e(TAG, "Sensors: UNREGISTERED"); 

    // stop recording 
    if (_recorder != null) { 
     _recorder.stop(); 
     _recorder.release(); 
     _recorder = null; 
    } 

    stopExpandedNotification(); 

    _sampling = false; 
} 

/** 
* Responsible for collecting the sensors data every two seconds 
*/ 
private class mainTask extends TimerTask { 
    /** 
    * Collects the sensor data every 2 seconds 
    */ 
    @Override 
    public void run() { 
     MovementService.this.collectData(); 
    } 
} 

/** 
* Initiates the microphone in order to collect the amplitude value 
*/ 
private void startRecordingMic() { 
    _recorder = new MediaRecorder(); 
    _recorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
    _recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
    _recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
    _recorder.setOutputFile(OUTPUT_FILE); 

    try { 
     _recorder.prepare(); 
    } catch (final IllegalStateException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (final IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    _recorder.start(); 
} 

/** 
* Initiates the acceleromenter sensor in order to collect movement data 
*/ 
private void startRecordingAcc() { 
    // ACCELEROMETER 
    _sensorManager = (SensorManager) this 
      .getSystemService(Context.SENSOR_SERVICE); 
    _accelerometer = _sensorManager 
      .getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
    _sensorManager.registerListener(accelerationListener, _accelerometer, 
      SensorManager.SENSOR_DELAY_FASTEST); 
} 

private final SensorEventListener accelerationListener = new SensorEventListener() { 

    public void onAccuracyChanged(Sensor sensor, int acc) { 
    } 


    public void onSensorChanged(SensorEvent event) { 

     // sampling values per axis 
     _x = event.values[0]; 
     _y = event.values[1]; 
     _z = event.values[2]; 

     //Log.e(TAG , "x: " + _x + " y: " + _y + " z:" + _z); 
    } 
}; 

/** 
* Send data (amplitude and decibel) to the xml file 
*/ 
public void collectData() { 
    //The power lock ensures that the service will indeed collect the accelerometer data 
    PowerManager pm = (PowerManager) MovementService.this.getSystemService(Context.POWER_SERVICE); 
    PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "YOUR TAG"); 
    wl.acquire(); 
    Log.v(TAG, "lock aquired"); 

    if (xml != null) xml.writeOnFile(this.getAmplitude(), this.getAccelaration(), this.getTotalAccelaration()); 

    wl.release(); 
    Log.v(TAG, "lock released"); 
} 

有你們任何建議,爲了解決這個問題呢?這真讓我抓狂。

Ps:我使用的是三星spika,android版本2.1。

回答

0

AFAIK當設備空閒時,加速計不能被採樣。你需要設置一個PARTIAL_WAKE_LOCK來保持CPU的運行。它仍然允許屏幕熄滅,但當然,電池的運行速度會比平時更快。

http://developer.android.com/reference/android/os/PowerManager.html#PARTIAL_WAKE_LOCK

代碼:

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag"); 
wl.acquire(); 
// ..screen will stay on during this section.. 
wl.release(); 

您還必須包括在清單此權限條目:

<uses-permission android:name="android.permission.WAKE_LOCK" /> 

有在這一點上一個問題: How to sample accelerometer data in the background or on the sleep mode

相關問題