Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android secondary display - persistence across activity invocation

I am using the Android MediaRouter (API 16) and Presentation (API 17) classes to generate & manage a secondary display. I followed the example in ApiDemos to create unique non-mirrored output, and so far it works fine (testing with Nexus 10 connected to HDTV via HDMI cable).

Now, I have a situation where I want the Presentation object created in Activity X to continue running on the secondary display, even if Activity X invokes another Activity Y. In this situation, Activity X is still on the stack, but Activity Y is now on top of it.

The problem is that when Activity Y starts, the physical secondary display reverts to mirroring. When I exit Activity Y, the content of Activity X's Presentation goes back (since I never called dismiss() on it).

So the question is: How can I keep a Presentation attached to a secondary display running on that display, even if a subordinate Activity is running on the local device?

UPDATE: One way I thought of doing this is to instantiate the Presentation object from a background thread; then the subsequent creation of another Activity should not interfere with the content being written by the background thread to its Presentation object. But I'm not sure this will work, as it's generally not allowed to update a UI from a background thread.

Another approach would be to disable the use of secondary displays by the subordinate Activity, if possible, thereby preventing it from reverting the secondary display to mirroring when the new Activity becomes active. But I haven't found a way to do this either. Thanks again for any suggestions.

like image 369
gcl1 Avatar asked Feb 26 '13 14:02

gcl1


Video Answer


1 Answers

I implemented one of the approaches suggested by @CommonsWare (and independently by Mark Allison in answer to my question on his blog). Thanks for your suggestions!

In review, THE PROBLEM was I couldn't keep a second screen presentation running in the background across Activity invocations on a local device. This was because the Presentation class is implemented as a subclass of Dialog, and is therefore tied to an Activity instance. So when a new Activity started up, the second screen went back to mirroring (instead of displaying other content I was specifically generating for it).

THE SOLUTION was to refactor all "subordinate" Activities into Fragments of the original Activity (i.e., the one that launched the second screen). Then, instead of calling startActivity(), I start/stop the new Fragments using FragmentTransactions. The net effect is that the Activity that started the Presentation is still running, so the secondary display is no longer interrupted when a new Activity starts.

My case was further complicated by the fact that the top level Activity (which starts the second screen) was actually a SherlockFragmentActivity that uses a ViewPager and FragmentStatePagerAdapter -- so I had to cram all this into a Fragment. It also required explicit management of ActionBar tabs, menu items, and home icon.

Overall, I think the code is a little less transparent ... but it works!

NOTE: It's good that Google has implemented a secondary screen interface. But I'm not sure why they did it the way they did. Rather than shoe-horning the Presentation class into Dialog, it would have been nice if they provided a more general solution that could easily run in the background, i.e., regardless of foreground Activities on the device. A solution like this would have saved me from a lot of code refactoring, as described above.

like image 157
gcl1 Avatar answered Nov 15 '22 05:11

gcl1