2012-04-02 60 views
62

我正在爲計算機科學的最終論文開發一個應用程序,而且我需要收集並記錄加速計數據。我需要購買一整天,因此存在嚴重的電池限制(例如,我無法離開屏幕)。另外,這不是一個針對市場的應用程序,因此如果需要,進行一些嚴重的黑客攻擊,即使是低級的C/C++編碼也是可以接受的。當屏幕關閉時Android加速度計不工作

衆所周知,在許多設備上,加速計事件監聽器在屏幕熄滅時停止生成事件(有關此問題的一些鏈接:http://code.google.com/p/android/issues/detail?id=3708,Accelerometer stops delivering samples when the screen is off on Droid/Nexus One even with a WakeLock)。我徹底搜索了一些替代品,其中一些替代品包括不適用於我的設備(LG P990,庫存ROM)的解決方法。

因此會發生什麼: 當您在服務中爲android加速度計傳感器註冊事件偵聽器時,它會正常工作,直到屏幕關閉。我已經嘗試在IntentService上的服務上註冊eventListener,試圖獲取WakeLocks。關於wakelocks,我可以驗證服務仍在運行看LOGcat輸出,但似乎加速度計進入睡眠模式。一個在某些環節提出的解決方法是註銷並重新註冊事件監聽器定期使用IntentService的線程想在這個代碼片段波紋管

synchronized private static PowerManager.WakeLock getLock(Context context) { 
    if (lockStatic==null) { 
     PowerManager mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE); 

     lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,NAME); 
     lockStatic.setReferenceCounted(true); 
    } 

    return(lockStatic); 
} 

@Override 
protected void onHandleIntent(Intent intent) { 

    sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE); 
    sensorManager.unregisterListener(this); 
    sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); 


    synchronized (this) { 
     boolean run = true; 
     while (run){ 
      try { 
       wait(1000); 
       getLock(AccelerometerService.this).acquire(); 
       sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE); 
       sensorManager.unregisterListener(this); 
       sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); 
       Log.d("Accelerometer service", "tick!"); 

      } catch (Exception e) { 
       run = false; 
       Log.d("Accelerometer service", "interrupted; cause: " + e.getMessage()); 


      } 
     } 
    }  
} 


@Override 
public void onSensorChanged(SensorEvent event) { 
    Log.d("accelerometer event received", "xyz: "+ event.values[0] + "," + event.values[1] + "," + event.values[2]); 
} 

這的確使得onSensorChange叫我們每次取消註冊/註冊偵聽器。問題是收到的事件總是包含相同的值,無論我搖晃設備。

所以,基本上我的問題是:(多多包涵,我即將結束:P)

  1. 是有可能有低級別的訪問(C/C++的方法)來加速計硬件,而不註冊到事件監聽器?

  2. 有沒有其他的解決方法或破解?

  3. 任何人都可以使用更新的手機進行測試,如果問題仍然存在於固件3.0或更高版本中?

[更新]

不幸的是,這似乎是與一些手機的bug。更多細節在我的答案中。

+1

嗨。我剛剛用我的HTC Sensation(ICS)測試了這個問題。加速度計和磁場傳感器都在屏幕關閉的情況下保持報告值。另外,您是否檢查了評論[46](http://code.google.com/p/android/issues/detail?id=3708)中描述的解決方法? – Renard 2012-04-02 20:10:07

+0

謝謝你的反饋Renard。 關於評論46,我也試過了,它和運行定期取消註冊/註冊事件監聽器的線程幾乎是一樣的。但是對於我的設備,每次關閉顯示器時我只能獲得加速度計的固定值.. 也感謝您在ICS上進行測試...它很高興知道它適用於它應該,可悲的是沒有ICS的LG P990了呢=/ – martin 2012-04-03 01:47:50

+1

可能會有用嘗試解決問題從另一方 - 獲取屏幕鎖定,但同時將屏幕亮度降至零以節省電池電量?當然,使用電源按鈕關閉屏幕時不起作用,但在這種情況下,您可以嘗試喚醒設備以防止屏幕鎖定。 – 2012-04-25 20:21:33

回答

61

基本上,這是我的手機有問題。其他用戶也報道過這種情況也會發生在他們的手機上,這些手機來自不同的品牌,但Android版本相同其他人完全沒有問題 - 強烈表明這不是Android的股票版本的問題,而是來自於每個公司的硬件驅動程序的實現。

我需要不斷的加速計數據傳輸,不能有一個加密狗測量這個數據,我 - 我有藍牙和加速度計一個Arduino,所以我可以實現這個解決方案。所以我決定爲我的手機設置臨時解決方案,讓屏幕亮起(變暗)並忽略電池消耗。稍後,我將使用另一個與屏幕關閉的Android手機進行電池使用測試。關於此bug

更多信息

我已經研究多一些,發現從其他Android用戶的報告,我想,也許我明白髮生了什麼。具有手機傳感器驅動程序的庫libsensors.so不是由Google開發的,而是由每個手機供應商開發的 - 當然,因爲每個手機都有自己的特定硬件。谷歌只提供一個C頭文件,以便開發人員知道他們必須實現什麼。在這些驅動程序的一些實現中,開發人員只需在屏幕關閉時關閉加速度計,從而防止傳感器事件偵聽器接收新事件。

我也用CyanogenMod RC7.2測試過這個,但它也沒有工作,因爲加速度計驅動程序是LG原創。

電子郵件與LG

的人力資源管理部門交換我發了一封郵件到LG P990的開發商終於得到了一些具體的答案!對於像我這樣遇到Android這些問題的人來說,這可能會有很大的幫助。我寫了下面的問題

你好!我正在開發我的計算機科學論文,目前我正在從加速計硬件中提取數據。到目前爲止,我發現 加速度計在屏幕關閉時不發送事件,所以即使當我從一個程序中抓取一個喚醒鎖時,我也可以通過 驗證我的程序是否仍在運行(通過LOGcat輸出)但沒有 加速度計事件出來。我必須調暗我的屏幕(我無法承受,電池消耗太快),以再次開始接收 加速度計事件。我也嘗試通過本地C 代碼訪問它,註冊加速度計事件,但結果是 相同,加速度計沒有拋出任何值,即使我旋轉我的設備是 。所以我想知道是否可以用硬件直接訪問 ,使用本地代碼,而不必註冊到 監聽器。這可能嗎?如果是這樣,你能否提供一些進一步的建議?我非常感謝任何幫助!馬丁

對於我收到此迴應:

親愛的馬丁,我們從開發得到的回答。球隊。他們表示,當您的手機屏幕關閉時,您無法獲取加速計事件 。因爲 HAL層沒有實現sysfs路徑來獲得H/W事件,例如 加速計,並且沒有公共API來獲取事件。謝謝。最好的 關心。 (肖恩金)

然後我發了一封郵件退回,除其他外說,我收購喚醒鎖時,認爲這是一個錯誤,因爲人都應該有所有的硬件訪問:

[...]我問這個問題,因爲我有一些朋友也有 Android手機使用相同的薑餅版本,但是從其他 手機品牌,其中一些報告說,他們收到來自 加速度計的事件,當屏幕被關閉。我讀了一些 論壇,這個錯誤 - 我認爲這是一個錯誤,因爲當我獲得 激活鎖定我希望有一些處理事情 - 取決於 傳感器驅動程序的供應商實現了自己的手機。 有沒有可能更新這些驅動程序,或者這個 錯誤在某些時候會被糾正?這將幫助我極大我 正在進行的工作[...]

然後,我收到這樣的回答:

在從開發我的知識。團隊,這不是bug。這是因爲H/W架構,這款手機的無限 。我們需要重新設計HAL 架構和設備驅動程序以支持您的請求。但是,由於缺乏資源,你知道這太難了。我們正在努力幫助您盡我們所能,但我們無法支持您的要求,因爲我提到了 。 (肖恩金)

所以他們顯然知道這一點,但並不試圖糾正這一點,因爲他們要麼不認爲這是一個錯誤 - 我仍然堅信是一個合乎邏輯的缺陷 - 或者他們不這樣做有時間/資源來糾正它。

底線 如果您的手機沒有在關閉屏幕的情況下發送加速計事件,請嘗試更新您的固件。如果這不能解決,並且你確實想要做一些嚴重的黑客攻擊,那就重新實現你的硬件層 - 提示:這可能與libsensors.so有關。

+2

感謝martin提供了非常完整的信息。我們真正需要的是一個列表,說明哪些手機在屏幕上支持加速計事件,因爲人們在購買之前可能需要這些信息(像我 - 我需要這樣)。也許一個維基,人們可以測試他們的手機並更新列表。有沒有像這樣的任何列表? – Fletch 2012-06-01 09:21:01

+8

好的,我做了一個清單:http://www.saltwebsites.com/2012/android-accelerometers-screen-off – Fletch 2012-06-26 10:35:37

+2

令人驚歎的,真正全面的答案。會給出不止一個大拇指:)在某種程度上,您可以通過偵聽SCREEN_OFF和SCREEN_ON事件來解決問題,獲取新的喚醒鎖並重新啓動加速度計服務。但是,它只能在一些手機上使用。 – LambergaR 2012-07-16 22:40:55

0

我不想讓你失望,但是有些設備在睡眠模式下不會讓加速度計繼續工作。有些是,其他則不是。你可以檢查商店裏的任何計步器減肥應用程序,大多數應用程序明確聲明這不適用於某些設備。

2

我碰到與三星Nexus採用其它系統的服務,停止/暫停,而屏幕是關閉的,即使一個PARTIAL_WAKE_LOCK獲取運行的Android 4.0.2類似的問題。我的解決辦法是使用一個SCREEN_DIM_WAKE_LOCK爲:

lockStatic = mgr.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,NAME); 

這將是更好的選擇有屏幕完全關閉,但至少該解決方案的工作,儘管它會更好,如果我能限制使用SCREEN_DIM_WAKE_LOCK只那些需要它的設備/操作系統。

6

我不知道這是否會真正幫助你,但我發現周圍的工作(不知道怎麼好,如果將有助於節電雖然)。

使用bash我有一個while循環捕獲/sys/devices/virtual/accelerometer/accelerometer/acc_file,當我通過電源按鈕關閉屏幕輸出繼續,但被凍結。 (我的sshd運行在chroot因此能看到它。)

然而,在呼應0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness。屏幕關閉,輸出持續。

這是對SGH-T589W,運行Android 2.3.6版本。

+0

你在代碼中完成了這個嗎? – baash05 2013-07-10 12:02:24

+0

唉!很好玩,不要想到bash腳本。我想我會盡量在後面嘗試,儘管我很久以前就已經完成了這項工作.. 感謝您的輸入! – martin 2013-07-15 16:53:25

0

如果局部喚醒鎖選項不可用您的手機就意味着對傳感器的驅動程序有early_suspend啓用。

有兩種選擇。

1:禁用EARLY_SUSPEND在駕駛員

2:添加一個運行時間標誌,在驅動程序級別可以enable/disable early_suspend功能。

ex。 cat/sys/module/earlysuspend/sensor 1/0

IMO第二個選項應該從那開始。

2

我應用了PARTIAL_WAKE_LOCK,它對我來說就像魅力一樣。在OS 5.0上測試,6.0 & 7.0。這是我的代碼來獲取和釋放喚醒鎖。小心它增加了電池排水量,因此可以智能地獲取並釋放它。

public void acquireWakeLock() { 
    final PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 
    releaseWakeLock(); 
    //Acquire new wake lock 
    mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK"); 
    mWakeLock.acquire(); 
} 

public void releaseWakeLock() { 
    if (mWakeLock != null && mWakeLock.isHeld()) { 
     mWakeLock.release(); 
     mWakeLock = null; 
    } 
} 

編號:https://developer.android.com/training/scheduling/wakelock.html#cpu

我工作的一個預測SDK,誰使用設備傳感器(加速度計/陀螺儀)數據和預測用戶的事件。我遇到了同樣的問題。