Android "N"에서 Doze가 "Doze on the Go"으로 확장되었습니다.앱이 "Doze on the Go"(AKA Doze Light, Doze Extended 및 Doze 2)로 언제 들어가는 지 추적 할 수 있습니까?
장치가 들어갔을 때이를 감지하여 IDLE 및 IDLE_MAINTENANCE 상태로 전환하는 방법을 찾고 있습니다. (기본적으로 Doze here에 대한 질문과 동일한 질문입니다.)
Android "N"에서 Doze가 "Doze on the Go"으로 확장되었습니다.앱이 "Doze on the Go"(AKA Doze Light, Doze Extended 및 Doze 2)로 언제 들어가는 지 추적 할 수 있습니까?
장치가 들어갔을 때이를 감지하여 IDLE 및 IDLE_MAINTENANCE 상태로 전환하는 방법을 찾고 있습니다. (기본적으로 Doze 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의 브로드 캐스트 등록을위한 문자열 사용에 동의합니다. 위의 방법과 마찬가지로 리플렉션을 사용하여 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
으로 주위를 파고 들자면 light doze 상태가 변경 될 때 실제로 의도가 전송되었음을 알 수 있습니다.
그러나 최신 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;
}
누락 된 API에 대한 조사를 위해 https://code.google.com/p/android/issues/detail?id=222595를 참조하십시오. – TrevorWiley
Google에 연락하여 마지막으로 언급 한 문제가 오프라인 상태가 아니므로, 이때 공식 응답을 포함해야합니다. – TrevorWiley
나는 더 이상 안드로이드 관련 작업을 수행하지 않으므로이 작업을 검증 할 수는 없지만 합리적인 것처럼 보였습니다. 그래서 이것을 받아 들인 대답으로 바꾸고 있습니다. 누군가가 문제가 생기면 항상 내 대답으로 돌아갈 수 있습니다. – TrevorWiley