Netflix app for Android (Official and Kindle Fire) has a feature to pause the video playback when the status bar is expanded. Different apps including non-media apps would like to know as to when the status bar is expanded or collapsed. One approach is to constantly poll for this but being notified is the best possible approach. Unfortunately, Android SDK doesn't offer any API to register a callback for status bar event updates. So how is Netflix notified of status bar updates?
One possibility is for the application to listen for window focus events. In Android world, each and every Activity has a corresponding window. This is why Activity has a callback, onWindowFocusChanged. The callback is passed a boolean to indicate focus gain or loss. Netflix most likely is listening for this event on the window corresponding to the playback.
The status bar and its contents are hosted in its own window and when user expands the status bar, window manager gives that window the active focus. This in turn causes a focus loss for the foreground application's window (Netflix in this case). This is the case when the status bar is collapsed causing a focus loss for Status bar window and focus gain for the application's window. This is called irrespective of the source causing the focus gain/loss. A dialog displayed by the activity would cause a focus loss as dialogs are hosted in their own window. This is true for Popup menu too. In case of Netflix, it kind of makes sense that the playback has to be paused the moment any kind of window is shown on top the playback activity. But this is only a possibility, could there be a hidden API or any other trick to find if the Status Bar is expanded or not?
I tested with an application starting a service. The service has a logic to display a window few seconds after launch. This is good enough to resume Netflix app and start a playback. As suspected, the playback is paused the moment the service initiated window is shown on top of Netflix application. This rules out any kind of Status Bar specific APIs.
One possibility is for the application to listen for window focus events. In Android world, each and every Activity has a corresponding window. This is why Activity has a callback, onWindowFocusChanged. The callback is passed a boolean to indicate focus gain or loss. Netflix most likely is listening for this event on the window corresponding to the playback.
public void onWindowFocusChanged(boolean hasFocus) {
if( hasFocus ) {
resumePlayback();
}
else {
pausePlayback();
}
}
The status bar and its contents are hosted in its own window and when user expands the status bar, window manager gives that window the active focus. This in turn causes a focus loss for the foreground application's window (Netflix in this case). This is the case when the status bar is collapsed causing a focus loss for Status bar window and focus gain for the application's window. This is called irrespective of the source causing the focus gain/loss. A dialog displayed by the activity would cause a focus loss as dialogs are hosted in their own window. This is true for Popup menu too. In case of Netflix, it kind of makes sense that the playback has to be paused the moment any kind of window is shown on top the playback activity. But this is only a possibility, could there be a hidden API or any other trick to find if the Status Bar is expanded or not?
I tested with an application starting a service. The service has a logic to display a window few seconds after launch. This is good enough to resume Netflix app and start a playback. As suspected, the playback is paused the moment the service initiated window is shown on top of Netflix application. This rules out any kind of Status Bar specific APIs.
public int onStartCommand(Intent intent, int flags, int startId) {
new android.os.Handler().postDelayed(new Runnable() {
public void run() {
launchTranslucentDialog();
}
}, 20000);
return super.onStartCommand(intent, flags, startId);
}
private void launchTranslucentDialog()
{
TextView textView = new TextView( getApplicationContext() );
textView.setText("TextView in a translucent window");
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.type = WindowManager.LayoutParams.TYPE_PHONE;
params.format = PixelFormat.TRANSLUCENT;
params.flags = 0x40020;
final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
wm.addView(textView, params);
}
No comments:
Post a Comment