Exemplo de Mídia Usando PhoneGap*: Gravação e Reprodução em Dispositivos Móveis

Índice

  1. Introdução
  2. Configurando o Ambiente de Desenvolvimento
  3. Considerações de Design
  4. Desenvolvendo e Testando em Dispositivos Android usando o Eclipse e o adb
  5. Depurando e Testando em um Dispositivo Apple iOS* usando a XCode* IDE
  6. Problemas Encontrados
O código fonte deste aplicativo pode ser encontrado aqui: https://github.com/gomobile/sample-phonegap-audio.
 

Introdução

Este artigo descreve o design e a implementação de um exemplo simples de manipulação de Mídia usando o PhoneGap*. A app demonstra a utilização do objeto Media do Apache Cordova* (PhoneGap) 2.0. A interface é bem simples. Mesmo com a API de Media do PhoneGap sendo bem documentada no website do PhoneGap, fazer com que mesma aplicação possa ser executada em dispositivos Google Android* e Apple iOS* não é trivial. Vamos discutir os problemas encontrados neste artigo. As máquinas utilizadas para o desenvolvimento deste aplicativo foram um laptop com Windows 7* x64 e um notebook Apple Mac* 10.5 para testes.

Os requisitos do programa de exemplo de Mídia são:

  • Usar o objeto Media do PhoneGap 
  • Gravar o som através do microfone do dispositivo
  • Reproduzir o som recém gravado e também outras gravações 
  • Suportar dispositivos Android* 
  • Suportar dispositivos Apple iOS*  

O aplicativo final se parece com a imagem abaixo, e o som gravado está no formato WAV, porquê o PhoneGap suporta apenas gravação neste formato em dispositivos iOS.

Media Sample 

Configurando o Ambiente de Desenvolvimento

  1. Para o desenvolvimento Android: nós usamos um laptop com o Windows 7* x64 instalado, e as seguintes ferramentas, de acordo com o Cordova/PhoneGap Getting Started article for Android*.

    Preparando o smartphone Android para testes: ver as  instruções sobre como configurar um dispositivo Android para desenvolvimento.

  2. Para o desenvolvimento em iOS*: Usamos um Apple Mac com o Leopard Mac OS X* e instalamos as seguintes ferramentas, de acordo com o PhoneGap's Getting Started Guide for iOS*.
    • Apple XCode* 4.3 e superior
    • Utiliários de linha de comando do XCode
    • O desenvolvimento de aplicativos para dispositivos iOS requer o acesso a uma conta em https://developer.apple.com/programs/ios/. Depois de criar a sua conta, você poderá distribuir o app para o dispositivo iOS usando o XCode.Isso facilita muito a depuração e os testes.
    • PhoneGap para iOS

    Preparando o dispositivo iOS, um tablet Apple iPad*, para testes: nada precisa ser feito.

Considerações de Design

Primeiro, este app demonstra as funcionalidades do objeto media do PhoneGap. A interface de usuário (UI) precisa ser simples e limpa. Todos os botões precisam estar em um bom estado quando o aplicativo for iniciado. O botão [Play] deve ser habilitado apenas se existir um arquivo de áudio gravado.

Segundo, o app limita o tempo de gravação em 10ms, pois é apenas um app de demonstração

Finalmente, a meta é ter uma única base de código que suporte múltiplas plataformas utilizando o PhoneGap. Porém, por conta das diferenças de suporte a mídia e no sistema de arquivos entre o iOS* e o Android*, você vai encontrar diversos lugares onde código específico de plataforma foi implemetado para cada uma delas.

Desenvolvendo e Testando em Dispositivos Android usando o Eclipse e o adb

Para a depuração com o Eclipse, tanto o Eclipse quanto o adb são utilizados. Então, usando o Eclipse, utilize "tag:web" para filtrar todas as mensagens não relevantes para este exemplo espeífico. Você pode utilizar outros filtros também.

Media Sample

Seguem abaixo as instruções para a depuração usando o "adb". Este método pode ser usado para depurar com o Emulador Android bem como em dispositivos Android.

  • Adicione qualquer código de depuração, como "console.log('*** antes de chamar o evento xxxx');" no seu app
  • Abra uma janela de comandos
  • Digite: adb devices para ver os nomes dos dispositivos
  • Digite: adb -s [device-name] logcat para exibir as mensagens de debug, como: 
    D/CordovaLog( 9946): onDeviceReady: Record with PhoneGap version: 2.0.0
    D/CordovaLog( 9946): file:///android_asset/www/index.html: Line 46 : onDeviceReady: Record with PhoneGap version: 2.0.0
    I/Web Console( 9946): onDeviceReady: Record with PhoneGap version: 2.0.0 at file:///android_asset/www/index.html:46
    D/CordovaLog( 9946): *** phoneCheck.android: android
    D/CordovaLog( 9946): file:///android_asset/www/index.html: Line 48 : *** phoneCheck.android: android
    I/Web Console( 9946): *** phoneCheck.android: android at file:///android_asset/www/index.html:48
    D/CordovaLog( 9946): *** phoneCheck.ios: null
    D/CordovaLog( 9946): file:///android_asset/www/index.html: Line 49 : *** phoneCheck.ios: null 

A gravação de mídia também interage com o sistema de arquivos do dispositivo, e o sistema de arquivos é diferente de uma plataforma para outra. O seguinte código em deviceCheck.js é utilizado para verificar a plataforma:


var phoneCheck = {
    ios: ua.match(/(iphone|ipod|ipad)/i),
    blackberry: ua.match(/blackberry/i), // não usado neste exemplo
    android: ua.match(/android/i),
    windows7: ua.match(/windows phone os 7.5/i) // não usado neste exemplo

};


Em dispositivos Android, o objeto de media do PhoneGap possui os seguintes comportamentos que não estão bem documentados:

  • "my_audio = new Media('myRecording100.wav', onMediaCallSuccess, onMediaCallError)":
    quando "myRecording100.wav" não existe,  ele cria o arquivo. quando ele existe, ele o abre.
  • "my_audio.stopRecord()":
    quando "stopRecord()" é chamado, o arquivo de mídia .wav media é movido para o diretório "/sdcard".
    Então, quando for checar se um arquivo .wav gravado anteriormente existe, o código deve olhar dentro da pasta "/sdcard". Se ele existir, ele deve abrir o arquivo de "/sdcard/myRecording100.wav":
    		function playMusic() {
    	if (my_audio === null) { // reproduz a mídia existente gravada em uma sessão anterior
    		
    		// a mídia existente deve estar em /sdcard/ para o Android. 
            if (phoneCheck.android) {
            	my_audio = new Media("/sdcard/" + mediaRecFile, onMediaCallSuccess, onMediaCallError);
    
                console.log("***test:  Open file:" + mediaRecFile);
            } 
            else if (phoneCheck.ios) {
                my_audio = new Media(mediaFileFullName, onMediaCallSuccess, onMediaCallError);
            }
        }
        ... ...
    }
    
    		

Depurando e Testando em um Dispositivo Apple iOS* usando a XCode* IDE

Você pode pensar que uma vez que o app funcione em dispositivos Android, deva ser simples e fácil tê-lo funcionando em dispositivos iOS. Bem, este não é o caso para o exemplo de Mídia.

Primeiro, gravar o áudio é diferente no Android e no iOS.
Para o Android, nós criamos o objeto "my_audio = new Media()" e o utilizamos para gravar, como segue. Isto é simples e direto.


function startRecording() {
    if (phoneCheck.android) {
        my_audio = new Media(mediaRecFile, onMediaCallSuccess, onMediaCallError);
        console.log("***test: new Media() for android ***");

        recordNow();
    }
    ... ... 
}
function recordNow() {
	if (my_audio) {
		my_audio.startRecord();
		document.getElementById('RecStatusID').innerHTML = "Status: recording";
		console.log("***test:  recording started: in startRecording()***");
	}
    ... ... 
}


Mas para o iOS, o aarquivo de áudio"myRecording100.wav" não pode ser criado pela API media.startRecording() do PhoneGap. Ele precisa ser criado primeiro (ou recriado, se existir) pelo sistema de arquivos. Então, a gravação deve começar na função de callback de sucesso na criação de arquivo. O código abaixo faz isso:


function onOK_GetFile(fileEntry) {
    ... ... 
	else { // gravar no iOS
		// criar o objeto media usando o nome completo do arquivo de mídia
		my_audio = new Media(mediaRecFile, onMediaCallSuccess, onMediaCallError);

		// específico para dispositivos iOS: a gravação inicia aqui, na função de call-back
		recordNow();
	}
}

function onSuccessFileSystem(fileSystem) {
	console.log("***test: fileSystem.root.name: " + fileSystem.root.name);
    ... ... 
    	fileSystem.root.getFile(mediaRecFile, { create: true, exclusive: false }, onOK_GetFile, null);
    
}

function startRecording() {
    ... ... 
    else if (phoneCheck.ios) {
    	//primeiro criamos o arquivo
    	checkFileOnly = false;
    	window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onSuccessFileSystem, function() {
    		console.log("***test: failed in creating media file in requestFileSystem");
    	});
    	console.log("***test: new Media() for ios***");
    }
}


Se você tentar usar um código similar ao baseado no Android no iOS, você vai cair na condição onde o arquivo ainda está em processo de criação e o objeto media está tentando utiliza-lo para a gravação.

Um outro problema é simplesmente insensato durante o meu desenvolvimento. Escolhi um iPad para testes e o iPad não possui um microfone interno. Tão logo usei um head-phone para o iPad, funcionou bem.

Problemas Encontrados

  1. O contole <audio> do HTML5 não é suportado em aplicações híbridas. 
    Não confunda isso com o suporte no navegador. Muitos navegadores existentes atualmente em dispositivos móveis suportam o HTML5.
  2. Um problema com o driver USB de um smartphone Samsung Galaxy S2* com Android: "Kies" não inicializa na máquina com Windows 7e o Eclipse não pode detectar o smartphone Samsung Galaxy S2. 
    Um work-around foi encontrado neste post na msdn foi a atualização de todo os aarquivos "C:\Program Files\Samsung\Kies*.config" para remover a seguinte linha:
       <supportedRuntime version="v4.0" />
  3. O objeto Media do PhoneGap pode gravar apenas aquivos WAV no dispositivo iOS - isto está documentado na página da API de mídia do PhoneGap, mas é facilmente esquecido.
AllegatoDimensione
Scarica clip1.png30.43 KB
Per informazioni complete sulle ottimizzazioni del compilatore, consultare l'Avviso sull'ottimizzazione