Dual Video Android* Apps Using Intel® WiDi Technology Whitepaper

Download

Download DualVideoWidi Code Samples [ZIP 112KB]

This sample demonstrates how to use the Presentation class to display video content on an external display using Intel® WiDi technology. It also shows how to use a service to play the content on the external display, thus allowing the video content to continue playing when another app is launched on the device’s primary display. Finally, it shows how to set up the audio on Intel® processor-based Android devices to allow dual audio streams for dual video playback and/or video playback combined with any other app that plays audio content.

Presentation with Video

The Presentation class is used for creating a dialog to display content on an external display. In this example, we’ll show you how to display video content with it. When using the Presentation API to display content on an external display via Intel WiDi technology, you need to select the correct display to present the content to. You can use the getSystemService function to get a pointer to a DisplayManager object. Using this object, you can get an array of all external displays that can be used with the Presentation class with the getDisplays function and the DISPLAY_CATEGORY_PRESENTATION constant. Once you have a pointer to the Display you want to present to, you can create an instance of the RemoteVideoPresentation class and use its show function to begin rendering content on the external display.

private DisplayManager mDisplayManager; 
mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);

//Select Display
Display[] displays = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
for (Display display : displays) 
{
	//Set up Presentation class and show
	presentation = new RemoteVideoPresentation(this, display, video);
	presentation.show();
}

Our RemoteVideoPresentation class extends Google’s Presentation class and overrides three functions: onCreate, onStart, and onStop. OnCreate is called much like Activity’s OnCreate function. This is where we set up the layout that contains our VideoView and get a handle to the AudioManager.

@Override
protected void onCreate(Bundle savedInstanceState) 
{
	super.onCreate(savedInstanceState);

	mAudManager = (AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE);
	getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
	setContentView(R.layout.activity_remote_video);
	mVideoView = (VideoView) findViewById(R.id.remoteVideoView);
}

The onStart method is invoked after the creator of the object calls its show function. This is where we begin playing our video whose URI was passed in to the constructor on the external display that was also passed in to the constructor. We set up the audio, set the VideoView’s video URI, and then call its start function.

@Override
protected void onStart() 
{
	super.onStart();
	playVideo();
}

public void playVideo()
{
	if (mVideoView != null)
	{
		mVideoView.setVideoURI(mVideoUri);
		int result = mAudManager.requestAudioFocus(afChangeListener,
				// Use the music stream.
				AudioManager.STREAM_MUSIC,
				// Request permanent focus.
				AudioManager.AUDIOFOCUS_GAIN);
		if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED)
		{
			//Error
		}
		mAudManager.setParameters("bgm_state=true");

		mVideoView.start();
	}
}

Managing Presentation with a Service

A Presentation dialog doesn’t need to be managed by a service, but if it’s not, then the dialog will stop when the application is stopped. To allow video playback to continue on the external display while swapping applications on the local display, the Presentation class used to play the video must be created and managed by a service. This also helps with playing back two distinct video streams on the external display and the local display. By creating the service as a class that extends the Service class, we can launch the service as an Intent and stop it in the same manner. RemoteVideoService is the service we’ve extended from the base service class.

public void OnClickPlayRemoteVideo(View view) 
{
	Intent serviceIntent = new Intent(this, RemoteVideoService.class);
	serviceIntent.putExtra(RemoteVideoService.URI, mRemoteVideoUri);
	startService(serviceIntent);
	mRemoteStopButton.setVisibility(View.VISIBLE);
	mRemoteStopButton.setClickable(true);
}

public void OnClickStopRemoteVideo(View view) 
{
	Intent serviceIntent = new Intent(this, RemoteVideoService.class);
	stopService(serviceIntent);

	mRemoteStopButton.setVisibility(View.INVISIBLE);
	mRemoteStopButton.setClickable(false);
}

In the service, we need to override four functions: onBind, onCreate, onDestroy, and onStartCommand. In the onBind function, we only need to return a new Binder object.

@Override
public IBinder onBind(Intent intent) 
{
	return new Binder();
}

onCreate is similar to other onCreate functions we’ve managed in Activities. However, there is no layout setup necessary here since it is all handled in the Presentation class. Here, we just set up the DisplayManager since it will need to be used to select the external display to set up the Presentation on.

@Override
public void onCreate() 
{
	super.onCreate();
	mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);
}

onDestroy is called when the service is stopped by the main Activity with the stopService function. We use it to call the Presentation’s cancel function. As a result, the Presentation’s onStop function will be called, allowing it to clean up after itself.

@Override
public void onDestroy() 
{
	if (presentation != null)
	{
		presentation.cancel();
	}
	super.onDestroy();
}

The onStartCommand function is where we do most of our work. We set up a notification object and start it so that the user can have an object in the Android dropdown menu to easily navigate back to the app and manipulate the service from the main Activity. This is also where we instantiate our Presentation class to play back video, get the URI that was passed to the service as a Parcel, and select the external display.

@Override
public int onStartCommand(Intent intent, int flags, int startId) 
{
	CharSequence text = getText(R.string.app_name);
	Intent startApp = new Intent(this, MainActivity.class);
	PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, startApp, 0);
	Notification.Builder bld = new Notification.Builder(this);
	Notification not = bld
			.setSmallIcon(R.drawable.ic_launcher)
			.setContentIntent(pendingIntent)
			.setContentTitle(text)
			.build();

	startForeground(1, not);

	Uri video = (Uri)intent.getParcelableExtra(URI);

	//Select Display
	Display[] displays = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
	for (Display display : displays) 
	{
		//Set up Presentation class and show
		presentation = new RemoteVideoPresentation(this, display, video);
		presentation.show();
	}

	return START_NOT_STICKY;
}

Dual Stream Audio

On Intel processor-based Android devices, you can set up the audio to allow two audio streams to be played separately over the device’s local speakers/headphones and an external display capable of playing audio such as an HDMI/Intel WiDi technology-capable display. This essentially allows an app creator to play video content with its audio over the external display while simultaneously playing a separate video (with audio) on the local display. Another example would be to play video externally while taking a phone call locally on the device. The code for doing so in this example is relatively simple and is all done in the Presentation class. When playing video, we just need to set up the audio manager to use the music stream and set the bgm_state parameter to true.

OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
	public void onAudioFocusChange(int focusChange) {
		if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {

		} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {

		} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
			mAudManager.abandonAudioFocus(afChangeListener);
		}
	}
};
int result = mAudManager.requestAudioFocus(afChangeListener,
		// Use the music stream.
		AudioManager.STREAM_MUSIC,
		// Request permanent focus.
		AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED)
{
	//Error
}
mAudManager.setParameters("bgm_state=true");

We also need to set the manifest xml file to indicate that our app will be modifying the audio settings.

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

This basic sample shows how to add Intel WiDi technology video or audio playback to your application, allowing users to multitask and do many different activities locally without interrupting the playback of the external content on Intel processor-based Android devices. Happy programming!

Author Bio

Gideon is a member of the Intel’s Software and Services Group and works with independent software vendors to help them optimize their software for Intel® Atom™ processors. In the past he worked on a team that wrote Linux* graphics drivers for platforms running the Android OS.

Related Links

Intel® WiDi Dual Screen Enabling Code Samples: http://software.intel.com/en-us/intel-widi#pid-19198-1607
Dual Screen Intel® WiDi Application http://software.intel.com/en-us/articles/dual-screen-intel-widi-application
How to Enable Intel® Wireless Display Differentiation for Miracast* on Intel® Architecture phone http://software.intel.com/en-us/articles/how-to-enable-intel-wireless-display-differentiation-for-miracast-on-intel-architecture

To learn more about Intel tools for the Android developer, visit Intel® Developer Zone for Android.

Intel and the Intel logo are trademarks of Intel Corporation in the US and/or other countries
Copyright © 2012 Intel Corporation. All rights reserved.
*Other names and brands may be claimed as the property of others.

Para obter informações mais completas sobre otimizações do compilador, consulte nosso aviso de otimização.