Desenvolvimento - Mobile

As funcionalidades esquecidas do .NET Compact Framework – Parte I (Fazendo chamadas de voz)

Nesta seqüência de artigos o autor irá indicar o “caminho das pedras”, de forma que as principais perguntas de desenvolvimento do Windows Mobile (mais especificamente o Smartphone) sejam esclarecidas.

por José Antonio Leal de Farias



Artigo para VS .NET 2003 e .NET 1.1

Introdução

Eu escuto muitas reclamações de que o .NET Compact Framework é muito limitado, só tem o "feijão-com-arroz", "blá-blá-blá"...e eles tem razão. Falta de conhecimento a parte, o que importa é que o desenvolvedor não precisa ficar preso às limitações do Compact Framework. Basta uma rápida investigação na arquitetura do Windows Mobile que o desenvolvedor encontrará uma série de módulos em que Compact Framework não oferece acesso nas suas classes nativamente, e que oferecem serviços muito interessantes. Nesta seqüência de artigos irei abordar esses módulos, indicando o "caminho das pedras", de forma que as principais perguntas de desenvolvimento do Windows Mobile (mais especificamente o Smartphone) sejam esclarecidas.

Então, uma pergunta que vem a mim praticamente toda semana é: "Como faço uma ligação programaticamente?". Pra quem programa em C++ é fácil, mas se você quiser usar dentro de seu programa feito em Compact Framework, temos de traduzir, ou seja, temos de fazer um método na linguagem desejada (C#, VB.NET) que represente a função que se deseja chamar. Uma análise no arquivo de cabeçalho (.h) do módulo correspondente será necessário.

O programa

Então vamos lá. Todo Smartphone (e os PocketPC Phone Edition também) tem uma dll chamada "phone.dll" que contém as funções básicas de um celular, ou seja, fazer ligações, através de uma função chamada PhoneMakeCall().

Vamos mostrar como usar essa dll para fazer uma pequena aplicação que faz ligações após um comando do usuário. Claro, não será melhor que a aplicação que JÁ vem com seu Smartphone/PocketPC, mas serve para ilustrar o uso dessa dll, de forma que você possa embutir essa funcionalidade em sua própria aplicação.

Para saber as funcionalidades na "phone.dll", procure pelo arquivo de cabeçalho "phone.h" que vem com o eVC++ 4.0 ou, claro, use o Google (ou MSN Search).

Antes de tudo, temos de importar a função que iremos usar da dll correspondente e também converter as macros e estruturas usadas pela função. Isso já é manjado e é feito como abaixo:

[DllImport("phone.dll")]
private static extern IntPtr PhoneMakeCall(ref PhoneMakeCallInfo ppmci);

A estutura PhoneMakeCallInfo é declarada em C++ da seguinte forma no arquivo "phone.h":

struct tagPHONEMAKECALLINFO {
DWORD cbSize;
DWORD dwFlags;
PCWSTR pszDestAddress;
PCWSTR pszAppName;
PCWSTR pszCalledParty;
PCWSTR pszComment;
}

Como tanto o DWORD quanto o PCWSTR tem 4 bytes, isso em C# fica assim:

private struct PhoneMakeCallInfo
{
public IntPtr cbSize;
public IntPtr dwFlags;
public IntPtr pszDestAddress;
public IntPtr pszAppName;
public IntPtr pszCalledParty;
public IntPtr pszComment;
}

E as constantes declaradas no .h ficam assim:

private static long PMCF_DEFAULT = 0x00000001;
private static long PMCF_PROMPTBEFORECALLING = 0x00000002;

Ok, tudo convertido para C#, falta fazer uma função para fazer a chamada em si. Isso é feito com o código a seguir:

unsafe public static void MakeCall(string PhoneNumber, bool PromptBeforeCall)
{
	IntPtr res;

	// As strings em C++ tem de terminar com um byte zero
	PhoneNumber += "\0";
	char[] cPhoneNumber = PhoneNumber.ToCharArray();

	fixed (char* pAddr = cPhoneNumber) 
	{
		PhoneMakeCallInfo info = new PhoneMakeCallInfo();
		info.cbSize = (IntPtr)Marshal.SizeOf(info);
		info.pszDestAddress = (IntPtr)pAddr;
			
		if (PromptBeforeCall)
		{
			info.dwFlags = (IntPtr)PMCF_PROMPTBEFORECALLING;
		}
		else
		{
			info.dwFlags = (IntPtr)PMCF_DEFAULT;
		}

		// Executa a chamada
		res = PhoneMakeCall(ref info);
	}
} 

O programa da tela abaixo é bastante simples. O usuário informa o número do telefone e se deve exibir a janela de confirmação. Em seguida basta selecionar "Discar".


O programa rodando no emulador.

Basicamente o que importa é que quando o usuário seleciona a opção "discar" o código abaixo é executado:

// Executa a chamada sem intervenção do usuário
MakeCall(this.txtNumber.Text,cbConfirm.Checked);

Simples, não? Imagine as possibilidades...uma aplicação de força de venda pode agora discar automaticamente para um fornecedor escolhido pelo vendedor..você pode fazer seu programa geo-processado ligar para um usuário que está perto de você ou mesmo criar um discador melhor que o que acompanha seu dispositivo, etc.

Não fique limitado ao Compact Framework. Estudando a arquitetura do Windows Mobile, um novo mundo de recursos pode se abrir para você.

Até a próxima!

José Antonio Leal de Farias

José Antonio Leal de Farias - Bacharel em ciências da computação pela UFCG e atualmente é Gerente de Pesquisa e Desenvolvimento da Light Infocon S.A. É programador profissional nas linguagens C++ e C#, líder do grupo de usuários CGSharp e adora Smartphones!
Veja seu blog em
http://thespoke.net/blogs/jalf/default.aspx.