Ответ 1
Вы можете это сделать, настроив широковещательные приемники для ACTION_SCREEN_ON
и ACTION_SCREEN_OFF
.
В Android 2.2 (уровень 7) функция PowerManager.IsScreenOn()
возвращает логическое значение, которое истинно, если экран включен и false, если экран выключен. Я разрабатываю код для Android 1.5 (уровень 3). Как выполнить ту же задачу в более старых версиях Android?
Я не хочу включать и выключать экран в своем коде. Я просто хочу знать, что это такое.
Вы можете это сделать, настроив широковещательные приемники для ACTION_SCREEN_ON
и ACTION_SCREEN_OFF
.
Там лучший способ, чем использование BroadcastReceivers:
// If you use API20 or more:
DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
for (Display display : dm.getDisplays()) {
if (display.getState() != Display.STATE_OFF) {
return true;
}
}
return false;
// If you use less than API20:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
if (powerManager.isScreenOn()){ return true; }
Обратите внимание, что Display.getState()
также может возвращать STATE_DOZE
и STATE_DOZE_SUSPEND
, что означает, что экран включен специальным образом. Подробнее о Display.getState()
и его значениях возврата здесь: http://developer.android.com/reference/android/view/Display.html#getState()
Также обратите внимание, что хотя официальная документация рекомендует использовать isInteractive()
вместо isScreenOn()
, если вы действительно хотите узнать о состоянии экрана, Display.getState()
является лучшим вариантом из-за специальных условий, которые задают экран пока устройство не является интерактивным.
Вот как вы должны это делать:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
boolean result= VERSION.SDK_INT>=VERSION_CODES.KITKAT_WATCH&&powerManager.isInteractive()||VERSION.SDK_INT<VERSION_CODES.KITKAT_WATCH&&powerManager.isScreenOn();
return result;
Я использую следующую функцию:
public boolean isInteractive() {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH
? powerManager.isInteractive()
: powerManager.isScreenOn();
}
Я публикую это, потому что на устройстве HUAWAI Prism II Android 4.1.1 (API 16) игра, над которой я работаю (http://www.playlunapuma.com) имели следующее раздражающее поведение:
Я показываю свое главное меню, которое имеет некоторую анимацию в SurfaceView и время от времени воспроизводит звук.
Устройство переходит в режим ожидания, затемняется, а затем становится темным.
Он вызывает onDestroy
в моей активности, а затем , когда экран выключен снова создает мою активность, называя onCreate
!
Поэтому проблема заключается в том, что мои анимации и звуки воспроизводятся, когда экран выключен. Я действительно хочу, чтобы мой цикл анимации не запускался вообще, если экран выключен. Приемники широковещательной передачи не работают, потому что я не могу сохранить состояние в последний раз, когда экран погас. Я думал о некоторых хаках, связанных с статическими булерами, но это просто похоже на kluge, который может не работать и иметь ужасные случаи. Экран уже выключен, когда моя активность создана снова, поэтому я не получаю событие через приемник вещания, что мой экран выключен.
Я решил это, используя как широковещательный приемник, так и код, указанный выше.
В моем onCreate
я создаю широковещательный приемник. Это будет контролировать мой цикл анимации, когда экран включается и выключается.
if (mScreenReceiver == null) {
mScreenIntentFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
mScreenIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
mScreenReceiver = new ScreenReceiver();
registerReceiver(mScreenReceiver, mScreenIntentFilter);
}
public class ScreenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
controlAnimLoop(false, false, true);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
controlAnimLoop(false, false, false);
}
}
}
В моем controlAnimLoop я проверяю isScreenOn
, который является этим кодом:
private boolean isScreenOn() {
if (android.os.Build.VERSION.SDK_INT >= 20) {
// I'm counting
// STATE_DOZE, STATE_OFF, STATE_DOZE_SUSPENDED
// all as "OFF"
DisplayManager dm = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
for (Display display : dm.getDisplays ()) {
if (display.getState () == Display.STATE_ON ||
display.getState () == Display.STATE_UNKNOWN) {
return true;
}
}
return false;
}
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
return powerManager.isScreenOn();
}
MainActivity.Java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_HEADSET_PLUG);
filter.addAction(Intent.ACTION_POWER_CONNECTED);
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(new MyReceiver(), filter);
}
}
MyReciever.Java
public class MyReceiver extends BroadcastReceiver {
MainActivity mActivity;
@Override
public void onReceive(Context arg0, Intent arg1) {
mActivity = (MainActivity) arg0;
TextView tv = (TextView)mActivity.findViewById(R.id.textView1);
if(arg1.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
tv.setText("Headset Plugin ");
} else if(arg1.getAction().equals(Intent.ACTION_POWER_CONNECTED)) {
tv.setText("Power Connected ");
} else if(arg1.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
tv.setText("Power Disconnected ");
} else if(arg1.getAction().equals(Intent.ACTION_SCREEN_ON)) {
tv.setText("Screen ON ");
} else if(arg1.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
tv.setText("Screen OFF ");
}
}
}