I'm working on my first Android app. It's designed to be immersive, and hides the NavigationBar on all activites, while providing its own internal navigation through the ActionBar.
I am committed to using the default MediaController view for this app. I'm using android.widget.MediaController
as a MediaController for a fullscreen video activity via android.widget.VideoView
. I'm also using an extension of android.widget.MediaController
which implements MediaController.MediaPlayerControl
for a non-full screen audio activity via android.media.MediaPlayer
.
After investigating the android.widget.MediaController
source, it displays itself as a FrameLayout in a new window, on top of the current activity. Whenever the MediaController is to be shown, it adds itself to the window with a specific set of layout parameters through a call to mWindowManager.addView(mDecor, mDecorLayoutParams);
below.
public void show(int timeout) {
if (!mShowing && mAnchor != null) {
setProgress();
if (mPauseButton != null) {
mPauseButton.requestFocus();
}
disableUnsupportedButtons();
updateFloatingWindowLayout();
mWindowManager.addView(mDecor, mDecorLayoutParams);
mShowing = true;
}
updatePausePlay();
// cause the progress bar to be updated even if mShowing
// was already true. This happens, for example, if we're
// paused with the progress bar showing the user hits play.
post(mShowProgress);
if (timeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
removeCallbacks(mFadeOut);
postDelayed(mFadeOut, timeout);
}
}
The result of this call is that the SystemUiVisibility is reset for this window, and the app comes out of immersive mode, showing the NavigationBar.
The problem I have is that every variable of this class is private, as are most methods. There are zero getters or setters for any of the private variables. So, I can't change the show method's interaction with its variables.
While extending the MediaController class, I can only override the show method to immediately call hideNavigation. However, the NavigationBar still briefly appears on screen each time the controller is shown! This isn't a solution I am comfortable with.
// MediaController implementation
@Override
public void show(int timeout) {
super.show(timeout);
// hide navigation
hideNavigation();
}
// hide navigation
public void hideNavigation() {
// get root view
View rootView = this.getRootView();
// options
final int options =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
;
// set visibility options
rootView.setSystemUiVisibility(options);
}
So, given that I can't extend the class properly, due to its private design, I would like to entirely replace it with my own, using most of the code from the original, just with protected variables and methods instead of private ones.
The problem with this approach is that I can't add import com.android.internal.policy.PhoneWindow;
to my Android Studio project. How can I include this package in my Gradle build?
compile 'com.android.internal.policy:phonewindow:1.0'
What do I need to change to make this work? Or, is it just not possible?
Additionally, I can see that a call to the getInstance(Context context)
method of android.view.accessibility.AccessibilityManager
is not recognized, so that will also prevent me from replicating this class.
Why is this method not available?
If there's some other way to forcibly prevent windows from changing their SystemUiVisibility options, or some other way to extend the show method without reproducing the entire class, that would be preferable!
Any guidance would be appreciated.