Video dual en aplicaciones Android* mediante la tecnología WiDi de Intel®

Descarga

Descargar ejemplos de código de Widi para video dual [ZIP 112KB]

Este ejemplo indica cómo usar la clase Presentation para mostrar contenido de video en una pantalla externa por medio de la tecnología WiDi de Intel®. Además, muestra cómo usar un servicio para reproducir el contenido en la pantalla externa, lo cual permite que continúe la reproducción del contenido de video cuando se inicia otra aplicación en la pantalla principal del dispositivo. Por último, muestra cómo configurar el audio en los dispositivos Android basados en procesadores Intel® con el fin de posibilitar secuencias de audio duales para la reproducción de video o video dual combinada con cualquier otra aplicación que reproduzca contenido de audio.

La clase Presentation con video

La clase Presentation se usa para crear un diálogo que exhiba contenido en una pantalla externa. En este ejemplo, veremos cómo mostrar contenido de video con ella. Cuando se utiliza la API de Presentation para exhibir contenido en una pantalla externa mediante la tecnología WiDi de Intel, es necesario seleccionar la pantalla apropiada a la cual presentar el contenido. Se puede usar la función getSystemService para obtener un puntero que apunte al objeto DisplayManager. Con este objeto, se puede obtener una matriz de todas las pantallas externas que se pueden usar con la clase Presentation con la función getDisplays function y la constante DISPLAY_CATEGORY_PRESENTATION. Una vez que se tiene el puntero a la pantalla a la cual se desea enviar la presentación, se puede crear una instancia de la clase RemoteVideoPresentation y usar su función de exhibición para comenzar a representar contenido en la pantalla externa.

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

//Selección de la pantalla
Display[] displays = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
for (Display display : displays) 
{
	//Configuración de la clase Presentation y muestra
	presentation = new RemoteVideoPresentation(this, display, video);
	presentation.show();
}

Nuestra clase RemoteVideoPresentation extiende la clase Presentation de Google e invalida tres funciones: onCreate, onStart y onStop. A OnCreate se la llama de manera similar a la función OnCreate de Activity. Aquí es donde configuramos el diseño que contiene nuestro VideoView y obtenemos un identificador de 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);
}

El método onStart se invoca después de que el creador del objeto llama a su función de muestra. Aquí es donde comenzamos a reproducir el video cuyo URI se pasó al constructor de la pantalla externa que también se pasó al constructor. Configuramos el audio, el URI del video de VideoView y luego llamamos a su función de inicio.

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

public void playVideo()
{
	if (mVideoView != null)
	{
		mVideoView.setVideoURI(mVideoUri);
		int result = mAudManager.requestAudioFocus(afChangeListener,
				// Usamos la secuencia de música.
				AudioManager.STREAM_MUSIC,
				// Solicitud de foco permanente.
				AudioManager.AUDIOFOCUS_GAIN);
		if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED)
		{
			//Error
		}
		mAudManager.setParameters("bgm_state=true");

		mVideoView.start();
	}
}

Cómo administrar la clase Presentation con un servicio

No es necesario que los diálogos de Presentation los administre un servicio, pero si no ocurre así, el diálogo se detendrá cuando lo haga la presentación Para permitir que continúe la reproducción de video en la pantalla externa mientras se cambia de aplicación en la pantalla local, un servicio tiene que encargarse de crear y administrar la clase Presentation que se usa para reproducir el video. Esto también es útil para para reproducir dos secuencias de video distintas en la pantalla externa y la local. Al crear el servicio como clase que extiende la clase Service, podemos iniciar el servicio como Intent y detenerlo de la misma manera. RemoteVideoService es el servicio que hemos extendido desde la clase de servicio base.

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);
}

En el servicio, necesitamos invalidar cuatro funciones: onBind, onCreate, onDestroy y onStartCommand. En la función onBind, solo necesitamos que se devuelva un nuevo objeto Binder.

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

onCreate es similar a otras funciones onCreate con las que hemos trabajado en Activities. Sin embargo, aquí no es necesaria la configuración de un diseño porque todo se maneja en la clase Presentation. Solo configuramos DisplayManager porque habrá que usarlo para seleccionar la pantalla externa en la cual se establecerá la Presentation.

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

Se llama a onDestroy cuando la Activity principal ha detenido el servicio con la función stopService. La usamos para llamar a la función de cancelación de Presentation. La consecuencia es que se llamará a la función onStop de Presentation, lo cual le permitirá hacer una limpieza después de realizar su proceso.

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

La función onStartCommand es donde hacemos la mayor parte del trabajo. Establecemos un objeto de notificación y lo iniciamos de modo que el usuario pueda tener un objeto en el menú desplegable de Android para navegar fácilmente de regreso a la aplicación y manejar el servicio desde la Activity principal. Aquí es también donde creamos una instancia de nuestra clase Presentation para reproducir video, obtener el URI que se pasó al servicio como Parcel y seleccionar la pantalla externa.

@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);

	//Selección de la pantalla
	Display[] displays = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
	for (Display display : displays) 
	{
		//Configuración de la clase Presentation y muestra
		presentation = new RemoteVideoPresentation(this, display, video);
		presentation.show();
	}

	return START_NOT_STICKY;
}

Secuencia de audio doble

En dispositivos Android basados en procesadores Intel, se puede configurar el audio de manera que se reproduzcan dos secuencias de audio por separado en los altavoces o auriculares locales del dispositivo y pueda haber una pantalla externa capaz de reproducir audio, como podría ser una pantalla con tecnología WiDi de Intel o HDMI. En esencia, esto permite que un creador de aplicaciones reproduzca en la pantalla externa contenido de video junto con el audio mientras reproduce en simultáneo un video aparte (con audio) en la pantalla local. Otro ejemplo sería reproducir video externamente mientras se recibe una llamada telefónica localmente en el dispositivo. El código para hacerlo en este ejemplo es relativamente simple. Todo se hace en la clase Presentation. Cuando se reproduce video, necesitamos configurar el administrador de audio para que use la secuencia de música y establezca el parámetro bgm_state como verdadero.

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,
		// Usamos la secuencia de música.
		AudioManager.STREAM_MUSIC,
		// Solicitud de foco permanente.
		AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED)
{
	//Error
}
mAudManager.setParameters("bgm_state=true");

También necesitamos ajustar el archivo xml de manifiesto para indicar que nuestra aplicación modificará las configuraciones de audio.

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

Este ejemplo básico muestra cómo agregar a una aplicación reproducción de video o audio con la tecnología WiDi de Intel, procedimiento que permite a los usuarios realizar varias tareas y muchas actividades diferentes localmente sin interrumpir la reproducción del contenido externo en dispositivos Android con procesadores Intel. ¡Buena programación!

Biografía del autor

Gideon forma parte del Grupo de Software y Servicios de Intel. Trabaja con proveedores de software independientes y los ayuda a optimizar sus productos para procesadores Intel® Atom™. En el pasado, trabajó en un equipo que escribió controladores gráficos de Linux* para plataformas con Android OS.

Enlaces relacionados

Muestras de código para habilitar Intel® WiDi Dual Screen: http://software.intel.com/es-es/intel-widi#pid-19198-1607 Aplicación WiDi con Dual Screen Intel® http://software.intel.com/es-es/articles/dual-screen-intel-widi-application
Cómo habilitar Intel® Wireless Display Differentiation para Miracast* en un teléfono con arquitectura Intel® http://software.intel.com/es-es/articles/how-to-enable-intel-wireless-display-differentiation-for-miracast-on-intel-architecture

Para conocer más acerca de las herramientas Intel para el desarrollador Android visita Intel® Developer Zone para Android.

Para obtener información más completa sobre las optimizaciones del compilador, consulte nuestro Aviso de optimización.