Reworked cast button handling

This commit is contained in:
ByteHamster 2020-03-25 17:00:48 +01:00
parent a989db586a
commit 9e84a06260
8 changed files with 165 additions and 202 deletions

View File

@ -2,6 +2,8 @@ package de.danoeh.antennapod.activity;
import androidx.appcompat.app.AppCompatActivity;
import android.view.Menu;
/**
* Activity that allows for showing the MediaRouter button whenever there's a cast device in the
* network.
@ -9,7 +11,7 @@ import androidx.appcompat.app.AppCompatActivity;
public abstract class CastEnabledActivity extends AppCompatActivity {
public static final String TAG = "CastEnabledActivity";
public final void requestCastButton(int showAsAction) {
public final void requestCastButton(Menu menu) {
// no-op
}
}

View File

@ -324,30 +324,6 @@ public class MainActivity extends CastEnabledActivity {
Glide.get(this).clearMemory();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean retVal = super.onCreateOptionsMenu(menu);
if (Flavors.FLAVOR == Flavors.PLAY) {
switch (NavDrawerFragment.getLastNavFragment(this)) {
case QueueFragment.TAG:
case EpisodesFragment.TAG:
case AudioPlayerFragment.TAG:
requestCastButton(MenuItem.SHOW_AS_ACTION_IF_ROOM);
return retVal;
case DownloadsFragment.TAG:
case PlaybackHistoryFragment.TAG:
case AddFeedFragment.TAG:
case SubscriptionFragment.TAG:
return retVal;
default:
requestCastButton(MenuItem.SHOW_AS_ACTION_NEVER);
return retVal;
}
} else {
return retVal;
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (drawerToggle.onOptionsItemSelected(item)) {

View File

@ -295,9 +295,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
if (Flavors.FLAVOR == Flavors.PLAY) {
requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
requestCastButton(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mediaplayer, menu);
return true;

View File

@ -22,6 +22,7 @@ import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.CastEnabledActivity;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
@ -423,7 +424,6 @@ public class AudioPlayerFragment extends Fragment implements
public void setupOptionsMenu() {
if (toolbar.getMenu().size() == 0) {
//toolbar.inflateMenu(R.menu.cast_enabled);
toolbar.inflateMenu(R.menu.mediaplayer);
}
if (controller == null) {
@ -439,17 +439,7 @@ public class AudioPlayerFragment extends Fragment implements
toolbar.getMenu().findItem(R.id.set_sleeptimer_item).setVisible(!controller.sleepTimerActive());
toolbar.getMenu().findItem(R.id.disable_sleeptimer_item).setVisible(controller.sleepTimerActive());
/*MenuItem mediaRouteButton = toolbar.getMenu().findItem(R.id.media_route_menu_item);
SwitchableMediaRouteActionProvider mediaRouteActionProvider =
CastManager.getInstance().addMediaRouterButton(mediaRouteButton);
CastEnabledActivity.CastButtonVisibilityManager castButtonVisibilityManager =
new CastEnabledActivity.CastButtonVisibilityManager(CastManager.getInstance());
castButtonVisibilityManager.setMenu(toolbar.getMenu());
castButtonVisibilityManager.setPrefEnabled(UserPreferences.isCastEnabled());
castButtonVisibilityManager.mediaRouteActionProvider = mediaRouteActionProvider;
castButtonVisibilityManager.setResumed(true);
castButtonVisibilityManager.requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable());*/
((CastEnabledActivity) getActivity()).requestCastButton(toolbar.getMenu());
}
@Override

View File

@ -146,9 +146,6 @@ public class ItemPagerFragment extends Fragment {
return;
}
super.onCreateOptionsMenu(menu, inflater);
if (Flavors.FLAVOR == Flavors.PLAY) {
((CastEnabledActivity) getActivity()).requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
inflater.inflate(R.menu.feeditem_options, menu);
if (item.hasMedia()) {
FeedItemMenuHandler.onPrepareMenu(menu, item);

View File

@ -136,8 +136,8 @@
<ProgressBar
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="@dimen/audioplayer_playercontrols_length_big"
android:layout_height="@dimen/audioplayer_playercontrols_length_big"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:id="@+id/progLoading"

View File

@ -4,8 +4,6 @@ import android.content.SharedPreferences;
import android.media.AudioManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import androidx.annotation.CallSuper;
import androidx.core.view.MenuItemCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
@ -14,6 +12,7 @@ import android.view.MenuItem;
import com.google.android.gms.cast.ApplicationMetadata;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.cast.CastButtonVisibilityManager;
import de.danoeh.antennapod.core.cast.CastConsumer;
import de.danoeh.antennapod.core.cast.CastManager;
import de.danoeh.antennapod.core.cast.DefaultCastConsumer;
@ -21,6 +20,9 @@ import de.danoeh.antennapod.core.cast.SwitchableMediaRouteActionProvider;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import java.util.ArrayList;
import java.util.List;
/**
* Activity that allows for showing the MediaRouter button whenever there's a cast device in the
* network.
@ -31,8 +33,7 @@ public abstract class CastEnabledActivity extends AppCompatActivity
private CastConsumer castConsumer;
private CastManager castManager;
private SwitchableMediaRouteActionProvider mediaRouteActionProvider;
private CastButtonVisibilityManager castButtonVisibilityManager;
private final List<CastButtonVisibilityManager> castButtons = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -58,9 +59,10 @@ public abstract class CastEnabledActivity extends AppCompatActivity
};
castManager = CastManager.getInstance();
castManager.addCastConsumer(castConsumer);
castButtonVisibilityManager = new CastButtonVisibilityManager(castManager);
CastButtonVisibilityManager castButtonVisibilityManager = new CastButtonVisibilityManager(castManager);
castButtonVisibilityManager.setPrefEnabled(UserPreferences.isCastEnabled());
onCastConnectionChanged(castManager.isConnected());
castButtons.add(castButtonVisibilityManager);
}
@Override
@ -75,47 +77,15 @@ public abstract class CastEnabledActivity extends AppCompatActivity
super.onDestroy();
}
@Override
@CallSuper
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
if (!CastManager.isInitialized()) {
return true;
}
getMenuInflater().inflate(R.menu.cast_enabled, menu);
castButtonVisibilityManager.setMenu(menu);
return true;
}
@Override
@CallSuper
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (!CastManager.isInitialized()) {
return true;
}
MenuItem mediaRouteButton = menu.findItem(R.id.media_route_menu_item);
if (mediaRouteButton == null) {
Log.wtf(TAG, "MediaRoute item could not be found on the menu!", new Exception());
mediaRouteActionProvider = null;
return true;
}
mediaRouteActionProvider = castManager.addMediaRouterButton(mediaRouteButton);
if (mediaRouteActionProvider != null) {
castButtonVisibilityManager.mediaRouteActionProvider = mediaRouteActionProvider;
mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable());
}
return true;
}
@Override
protected void onResume() {
super.onResume();
if (!CastManager.isInitialized()) {
return;
}
castButtonVisibilityManager.setResumed(true);
for (CastButtonVisibilityManager castButton : castButtons) {
castButton.setResumed(true);
}
}
@Override
@ -124,7 +94,9 @@ public abstract class CastEnabledActivity extends AppCompatActivity
if (!CastManager.isInitialized()) {
return;
}
castButtonVisibilityManager.setResumed(false);
for (CastButtonVisibilityManager castButton : castButtons) {
castButton.setResumed(false);
}
}
@ -133,7 +105,9 @@ public abstract class CastEnabledActivity extends AppCompatActivity
if (UserPreferences.PREF_CAST_ENABLED.equals(key)) {
boolean newValue = UserPreferences.isCastEnabled();
Log.d(TAG, "onSharedPreferenceChanged(), isCastEnabled set to " + newValue);
castButtonVisibilityManager.setPrefEnabled(newValue);
for (CastButtonVisibilityManager castButton : castButtons) {
castButton.setPrefEnabled(newValue);
}
// PlaybackService has its own listener, so if it's active we don't have to take action here.
if (!newValue && !PlaybackService.isRunning) {
CastManager.getInstance().disconnect();
@ -143,135 +117,41 @@ public abstract class CastEnabledActivity extends AppCompatActivity
private void onCastConnectionChanged(boolean connected) {
if (connected) {
castButtonVisibilityManager.onConnected();
for (CastButtonVisibilityManager castButton : castButtons) {
castButton.onConnected();
}
setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
} else {
castButtonVisibilityManager.onDisconnected();
for (CastButtonVisibilityManager castButton : castButtons) {
castButton.onDisconnected();
}
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
}
/**
* Should be called by any activity or fragment for which the cast button should be shown.
*
* @param showAsAction refer to {@link MenuItem#setShowAsAction(int)}
*/
public final void requestCastButton(int showAsAction) {
public final void requestCastButton(Menu menu) {
if (!CastManager.isInitialized()) {
return;
}
castButtonVisibilityManager.requestCastButton(showAsAction);
}
public static class CastButtonVisibilityManager {
private final CastManager castManager;
private volatile boolean prefEnabled = false;
private volatile boolean viewRequested = false;
private volatile boolean resumed = false;
private volatile boolean connected = false;
private volatile int showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
private Menu menu;
public SwitchableMediaRouteActionProvider mediaRouteActionProvider;
public CastButtonVisibilityManager(CastManager castManager) {
this.castManager = castManager;
MenuItem mediaRouteButton = menu.findItem(R.id.media_route_menu_item);
if (mediaRouteButton == null) {
getMenuInflater().inflate(R.menu.cast_enabled, menu);
mediaRouteButton = menu.findItem(R.id.media_route_menu_item);
}
public synchronized void setPrefEnabled(boolean newValue) {
if (prefEnabled != newValue && resumed && (viewRequested || connected)) {
if (newValue) {
castManager.incrementUiCounter();
} else {
castManager.decrementUiCounter();
}
}
prefEnabled = newValue;
if (mediaRouteActionProvider != null) {
mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
}
}
public synchronized void setResumed(boolean newValue) {
if (resumed == newValue) {
Log.e(TAG, "resumed should never change to the same value");
return;
}
resumed = newValue;
if (prefEnabled && (viewRequested || connected)) {
if (resumed) {
castManager.incrementUiCounter();
} else {
castManager.decrementUiCounter();
}
}
}
public synchronized void setViewRequested(boolean newValue) {
if (viewRequested != newValue && resumed && prefEnabled && !connected) {
if (newValue) {
castManager.incrementUiCounter();
} else {
castManager.decrementUiCounter();
}
}
viewRequested = newValue;
if (mediaRouteActionProvider != null) {
mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
}
}
public synchronized void setConnected(boolean newValue) {
if (connected != newValue && resumed && prefEnabled && !prefEnabled) {
if (newValue) {
castManager.incrementUiCounter();
} else {
castManager.decrementUiCounter();
}
}
connected = newValue;
if (mediaRouteActionProvider != null) {
mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
}
}
public synchronized boolean shouldEnable() {
return prefEnabled && viewRequested;
}
public void setMenu(Menu menu) {
setViewRequested(false);
showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
this.menu = menu;
setShowAsAction();
}
public void requestCastButton(int showAsAction) {
setViewRequested(true);
this.showAsAction = showAsAction;
setShowAsAction();
}
public void onConnected() {
setConnected(true);
setShowAsAction();
}
public void onDisconnected() {
setConnected(false);
setShowAsAction();
}
private void setShowAsAction() {
if (menu == null) {
Log.d(TAG, "setShowAsAction() without a menu");
return;
}
MenuItem item = menu.findItem(R.id.media_route_menu_item);
if (item == null) {
Log.e(TAG, "setShowAsAction(), but cast button not inflated");
return;
}
MenuItemCompat.setShowAsAction(item, connected? MenuItem.SHOW_AS_ACTION_ALWAYS : showAsAction);
}
SwitchableMediaRouteActionProvider mediaRouteActionProvider =
CastManager.getInstance().addMediaRouterButton(mediaRouteButton);
CastButtonVisibilityManager castButtonVisibilityManager =
new CastButtonVisibilityManager(CastManager.getInstance());
castButtonVisibilityManager.setMenu(menu);
castButtonVisibilityManager.setPrefEnabled(UserPreferences.isCastEnabled());
castButtonVisibilityManager.mediaRouteActionProvider = mediaRouteActionProvider;
castButtonVisibilityManager.setResumed(true);
castButtonVisibilityManager.requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable());
}
}

View File

@ -0,0 +1,120 @@
package de.danoeh.antennapod.core.cast;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import androidx.core.view.MenuItemCompat;
import de.danoeh.antennapod.core.R;
public class CastButtonVisibilityManager {
private static final String TAG = "CastBtnVisibilityMgr";
private final CastManager castManager;
private volatile boolean prefEnabled = false;
private volatile boolean viewRequested = false;
private volatile boolean resumed = false;
private volatile boolean connected = false;
private volatile int showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
private Menu menu;
public SwitchableMediaRouteActionProvider mediaRouteActionProvider;
public CastButtonVisibilityManager(CastManager castManager) {
this.castManager = castManager;
}
public synchronized void setPrefEnabled(boolean newValue) {
if (prefEnabled != newValue && resumed && (viewRequested || connected)) {
if (newValue) {
castManager.incrementUiCounter();
} else {
castManager.decrementUiCounter();
}
}
prefEnabled = newValue;
if (mediaRouteActionProvider != null) {
mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
}
}
public synchronized void setResumed(boolean newValue) {
if (resumed == newValue) {
Log.e(TAG, "resumed should never change to the same value");
return;
}
resumed = newValue;
if (prefEnabled && (viewRequested || connected)) {
if (resumed) {
castManager.incrementUiCounter();
} else {
castManager.decrementUiCounter();
}
}
}
public synchronized void setViewRequested(boolean newValue) {
if (viewRequested != newValue && resumed && prefEnabled && !connected) {
if (newValue) {
castManager.incrementUiCounter();
} else {
castManager.decrementUiCounter();
}
}
viewRequested = newValue;
if (mediaRouteActionProvider != null) {
mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
}
}
public synchronized void setConnected(boolean newValue) {
if (connected != newValue && resumed && prefEnabled && !prefEnabled) {
if (newValue) {
castManager.incrementUiCounter();
} else {
castManager.decrementUiCounter();
}
}
connected = newValue;
if (mediaRouteActionProvider != null) {
mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
}
}
public synchronized boolean shouldEnable() {
return prefEnabled && viewRequested;
}
public void setMenu(Menu menu) {
setViewRequested(false);
showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
this.menu = menu;
setShowAsAction();
}
public void requestCastButton(int showAsAction) {
setViewRequested(true);
this.showAsAction = showAsAction;
setShowAsAction();
}
public void onConnected() {
setConnected(true);
setShowAsAction();
}
public void onDisconnected() {
setConnected(false);
setShowAsAction();
}
private void setShowAsAction() {
if (menu == null) {
Log.d(TAG, "setShowAsAction() without a menu");
return;
}
MenuItem item = menu.findItem(R.id.media_route_menu_item);
if (item == null) {
Log.e(TAG, "setShowAsAction(), but cast button not inflated");
return;
}
MenuItemCompat.setShowAsAction(item, connected ? MenuItem.SHOW_AS_ACTION_ALWAYS : showAsAction);
}
}