Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

Bringing this question back from the dead willing to help someone with the same problem somewhere in time,

I've recently came into a far deeper, but similar, problem: I had to display a presentation anywhere on the system (I work with embedded android) and in the main screen any app could be used.

I first thought of creating a Service that managed the display of the presentation and was initialized at the startup of the application. But the problem was that I couldn't show the presentation because, as you mention, it inherits from a Dialog and the same problem that happens when you call getApplicationContext() when building a dialog, occurred.

My solution was: There is a WindowManager.LayoutParam called TYPE_SYSTEM_ALERT that is used to display alerts like the Low Battery alert Dialog. Using this property you can create a Dialog from a service and display it properly and as the Presentation class is a children of the Dialog, simply setting this property made it work.

The magic happens here:

 WindowManager.LayoutParams l = mPresentation.getWindow()
                    .getAttributes();
 l.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
 mPresentation.show();

Just reminding that in order to achieve that your, application XML should have the SYSTEM_ALERT_WINDOW permission.

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

I think that this should solve your issue as well, but it is a little bit delicated and you need a proper treatment to stop the presentation as soon as you needed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top