0

I'm writing a wrapper around ExoPlayer as a custom view. The goal is to create a very simple abstraction for our streams and ad logic so that we can distribute a JAR file to clients and they can drag-and-drop a "BFPlayer" into their custom apps, hand it an ID referencing one of our broadcasts, and everything will play like magic.

As ExoPlayer needs to be released whenever an activity is paused or stopped, if possible I would like to do this automatically. I would like to detect when the parent activity is paused, release ExoPlayer, then detect when it's unpaused and spin up a new ExoPlayer silently and resume the previous state.

I found this StackOverflow post, describing how to get the hosting Activity from a View, however once I have the activity I don't know of a way to register a function to run automatically when the activity is paused.

stevendesu
  • 15,753
  • 22
  • 105
  • 182

2 Answers2

1

In your activity you can implement a method to allow views to subscribe to lifecycle events like so:

Make a listener for events

interface LifeCycleListener {
    fun onPause()
    fun onResume()
}

Allow views to subscribe to events

private var mListener: LifeCycleListener? = null
fun subscribeToLifecycleEvents(listener: LifeCycleListener) {
    mListener = listener
}

In activities methods call the listener

    override protected final fun onPause() {
        mListener?.onPause()

        super.onPause()
    }

    override protected final fun onResume() {
        super.onResume();

        mListener?.onResume()
    }

And then make your view implement the LifeCycleListener and call the subscribe function after you get your activity

Quinn
  • 7,072
  • 7
  • 39
  • 61
  • So the only way is to have the consumer of my library modify their activity to act as a publisher in a pub-sub model? If that's the case, I may be better-served just providing `release()` and `restore()` methods and asking that they call them within `onPause` and `onResume` -- add two lines of code instead of 10. – stevendesu May 10 '19 at 16:41
  • @stevendesu yeah, sorry i misunderstood your intent. As far as i know there are no built in ways to listen to those events without control of the activity. Your best bet is likely to just make them call `release()` and `restore()` appropriatly – Quinn May 10 '19 at 17:34
  • @stevendesu another thing to consider, you could maybe make a fragment instead of a custom view, and the fragment will have access to the lifecycle events – Quinn May 10 '19 at 19:51
  • if I create a fragment as part of an Android Library, would it be available in the layout designer for someone to drag and drop into their app? My goal was to distribute this player as an easy-to-use media player for our clients to build their own apps to play videos hosted on our service – stevendesu May 10 '19 at 20:03
  • @stevendesu i never use layout designer but i believe you can include it in the xml fairly easily – Quinn May 11 '19 at 00:10
  • I've found a new solution to this that I think is a bit more elegant. I posted it as an answer. – stevendesu May 30 '19 at 18:41
1

Just wanted to add another solution I discovered for this that might be a bit cleaner. You can have your View implement the LifecycleListener interface then call getLifecycle().addListener(view) within the activity:

Activity.java:

public class MyActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        MyView myView = findViewById(R.id.myView);
        getLifecycle().addObserver(myView);
    }
}

View.java:

public class MyView extends View implements LifecycleListener {
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause() {
        Log.i("LIFECYCLE EVENT", "Activity was paused");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() {
        Log.i("LIFECYCLE EVENT", "Activity was resumed");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onStop() {
        Log.i("LIFECYCLE EVENT", "Activity was stopped");
    }
}

I like this solution because it minimizes the amount of code that must be added to the activity - reducing the cost to implement a library to a single additional line that must be pasted in rather than having to declare multiple lifecycle methods and delegate to the view manually.

stevendesu
  • 15,753
  • 22
  • 105
  • 182