在Android「N」中,Doze已被擴展爲「Doze on the Go」。是否有可能跟蹤應用何時進入「隨時待命」(AKA Doze Light,Doze Extended和Doze 2)?
我正在尋找一種方法來檢測設備何時進入並離開這些新燈打盹IDLE和IDLE_MAINTENANCE狀態。 (基本上是要求定期打盹here相同的問題。)
在Android「N」中,Doze已被擴展爲「Doze on the Go」。是否有可能跟蹤應用何時進入「隨時待命」(AKA Doze Light,Doze Extended和Doze 2)?
我正在尋找一種方法來檢測設備何時進入並離開這些新燈打盹IDLE和IDLE_MAINTENANCE狀態。 (基本上是要求定期打盹here相同的問題。)
TrevorWiley的答案的實現工作,但可以簡化一下。是的,Nougat的PowerManager有isLightDeviceIdleMode()
,它的註釋是@hide
。我們可以使用反射來調用它,它更加簡潔並且獨立於PowerManager的內部實現細節。
public static boolean isLightDeviceIdleMode(final Context context) {
boolean result = false;
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm != null) {
try {
Method isLightDeviceIdleModeMethod = pm.getClass().getDeclaredMethod("isLightDeviceIdleMode");
result = (boolean)isLightDeviceIdleModeMethod.invoke(pm);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
Log.e(TAG, "Reflection failed for isLightDeviceIdleMode: " + e.toString(), e);
}
}
return result;
}
主要與TrevorWiley使用String來註冊廣播同意。與上述方法相同,您可以使用反射來獲取字段ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED
的值並回退到硬編碼字符串"android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED"
。
PowerManager的在線文檔沒有提到它,但最新的源代碼(API 24版本1)有看起來應該是這樣的解決方案問題:
String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED
= "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED"
boolean isLightDeviceIdleMode()
從理論上講,你可以簡單地註冊一些代碼作爲意圖接收器和檢查功能的當前值。一些與dumpsys activity broadcasts
扯皮表明,意圖確實發送時,輕瞌睡狀態的變化。但是,最新的SDK平臺(API 24修訂版2)中沒有這些符號 - 我得到編譯錯誤(並且有一些javap
和jar
表示它們確實不存在)。深入Google,我們被告知這是預期的設計。
有一種解決方法,它是對上述同一個字符串進行硬編碼,然後使用反射來調用在API中調用的相同函數。像這樣:
/**
* Check if the device is currently in the Light IDLE mode.
*
* @param context The application context.
* @return True if the device is in the Light IDLE mode.
*/
public static boolean isLightDeviceIdleMode(final Context context) {
boolean result = false;
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm != null) {
// result = pm.isLightDeviceIdleMode();
try {
Log.d(TAG, "Trying reflection for isLightDeviceIdleMode");
Field pmServiceField = pm.getClass().getDeclaredField("mService");
pmServiceField.setAccessible(true);
Object pmService = pmServiceField.get(pm);
Method isLightDeviceIdleMode = pmService.getClass().getDeclaredMethod("isLightDeviceIdleMode");
isLightDeviceIdleMode.setAccessible(true);
result = (Boolean) isLightDeviceIdleMode.invoke(pmService);
} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
Log.e(TAG, "Reflection failed for isLightDeviceIdleMode: " + e.toString());
} catch (RemoteException re) {
Log.e(TAG, "Remote exception checking isLightDeviceIdleMode: " + e.toString());
}
}
return result;
}
請參閱https://code.google.com/p/android/issues/detail?id=222595瞭解我對缺失API的調查 – TrevorWiley
我們已與Google脫機聯繫,因此我上次評論中提到的問題沒有提及,在這個時候,包含任何官方迴應。 – TrevorWiley
我沒有做任何與Android相關的東西,所以我無法驗證這個作品,但它看起來很合理,所以我將其轉換爲接受的答案。如果有人遇到麻煩,他們總是可以回到我的答案。 – TrevorWiley