×
Namespaces

Variants
Actions

Como gerar e ler códigos de barras em Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search

Este artigo explica como gerar e ler códigos de barras em aplicações Windows Phone, usando a biblioteca ZXing.Net.

WP Metro Icon Multimedia.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata

Exemplo de código
Código fonte: Media:WPBarcodes.zip

Testado com
Aparelho(s): Nokia Lumia 800, Windows Phone 8 Emulator

Compatibilidade
Platform Security
Capabilities: ID_CAP_ISV_CAMERA

Artigo
Tradução:
Por PedroQ
Última alteração feita por lpvalente em 25 Aug 2013
See Also

Contents

Introdução

Um código de barras é uma forma de representar informação de modo a que possa ser lida por uma máquina. É bastante comum encontrar códigos de barra no dia a dia, seja numa embalagem de comida, num livro, num CD. Em geral, o esse código de barras pode ser usado para identificar o objeto ao qual está anexado. Existem vários tipos e formatos de códigos de barras. Alguns são simplesmente grupos de linhas verticais paralelas, onde a informação é codificada ao variar a largura de cada linha. Estes são chamados os códigos de barras 1D (uma dimensão). Outros codificam a informação utilizando um conjunto de padrões geométricos. Estes são os códigos de barras 2D (ou códigos de matriz) e podem conter uma maior quantidade de informação. Um exemplo comum de um código de barras 2D é um formato chamado QR Code QR Code. Com a revolução dos smartphones, os QR Codes tornaram-se bastante populares. Em publicidade, por exemplo, é possível visitar o site do produto ao ler um QR Code com o aparelho. Outro exemplo é a possibilidade de partilhar o seu cartão de visita de forma virtual.

Por defeito, tanto o Windows Phone 7 como o Windows Phone 8 são capazes de ler alguns tipos de códigos de barras (QR Code, EAN-13, Microsoft Tag) usando a aplicação Bing Vision (para usar, carregue no botão de pesquisa e depois escolha o ícone de um olho na application bar). Contudo, é por vezes necessário ler um código de barras que a Bing Vision não é capaz de ler. Ou pode querer adicionar esta funcionalidade diretamente dentro da sua aplicação (por exemplo, numa aplicação para gerir os DVD's que emprestou a amigos). Bibliotecas como a ZXing.Net podem ajudar nestas tarefas.

Neste artigo é explicado como pode adicionar a capacidade de gerar e ler códigos de barras usando a câmara do telemóvel a uma aplicação Windows Phone. Para exe exemplo vamos criar uma simples aplicação que:

  • Gera um QR Code que contém o número de telemóvel de um contacto escolhido pelo utilizador.
  • É capaz de ler códigos de barras e mostrar a informação neles contida.

Bibliotecas

Vamos usar uma biblioteca chamada ZXing.Net, uma implementação .Net da popular biblioteca ZXing, que permite trabalhar com códigos de barras. A ZXing.Net está disponível como um pacote NuGet, portanto vamos usar este método para adicionar esta referência ao nosso projeto.

Na janela Solution Explorer, clique com o botão direito no ficheiro do projeto e selecione Manage NuGet Packages. Procure por ZXing.Net e clique em Install. Pode também usar a Package Manager Console para adicionar esta referência. Basta para isso executar o seguinte comando: PM> Install-Package ZXing.Net.

Gerar códigos de barras

Para exemplificar como gerar um código de barras, vamos criar um QR Code que contenha o número de telefone. Vamos usar a PhoneNumberChooserTask para permitir permitir ao utilizador escolher o número de telefone de um dos contactos.

PhoneNumberChooserTask phoneNumberChooserTask;
phoneNumberChooserTask = new PhoneNumberChooserTask();
phoneNumberChooserTask.Completed += phoneNumberChooserTask_Completed;


E depois geramos o QR Code com o número de telefone escolhido:

private static WriteableBitmap GenerateQRCode(string phoneNumber)
{
BarcodeWriter _writer = new BarcodeWriter();
 
_writer.Renderer = new ZXing.Rendering.WriteableBitmapRenderer()
{
Foreground = System.Windows.Media.Color.FromArgb(255, 0, 0, 255) // blue
};
 
_writer.Format = BarcodeFormat.QR_CODE;
 
 
_writer.Options.Height = 400;
_writer.Options.Width = 400;
_writer.Options.Margin = 1;
 
var barcodeImage = _writer.Write("tel:" + phoneNumber); //tel: prefix for phone numbers
 
return barcodeImage;
}

A classe BarcodeWriter possui várias propriedades que permitem personalizar o código de barras gerado:

  • A propriedade Renderer define o aspeto do código de barras, tal como a sua cor, a cor de fundo, tipo de letra e o seu tamanho. Neste exemplo escolhemos gerar um código de barras azul sobre um fundo branco (por omissão).
  • A propriedade Format define o tipo de código de barras que será gerado. Para este exemplo escolhemos QR Code.
  • A propriedade Options permite definir as dimensões do código de barras que será gerado, bem como as suas margens.

Deverá ter reparado que neste caso foi colocado um prefixo tel: antes da informação que se pretende codificar. Isto permite aos leitores de QR Code entender que a informação contida neste código de barras é um número de telefone. Este tipo de códigos de barras, o QR Code, permite vários prefixos deste género. Uma lista detalhada destes prefixos pode ser consultada aqui.

Aqui fica o exemplo do QR Code gerado:

Exemplo de QR Code que contém um número de telefone

Estes são outros exemplos de códigos de barras que podem ser gerados:

Ler códigos de barras

Adicionar a funcionalidade de leitura de códigos de barras a uma aplicação pode por vezes ser bastante útil. Por exemplo, numa aplicação de pesquisa de preços, seria muito mais fácil para o utilizador apontar a câmara do telemóvel para o código de barras e clicar em Pesquisar.

Na aplicação exemplo esta funcionalidade encontra-se no ficheiro Scan.xaml. Esta página contém um visor para que o utilizador possa ver para onde a câmara está a apontar e uma área onde são mostradas as informações sobre os códigos de barras lidos. Partes deste exemplo foram retiradas dos seguintes artigos: How to create a base camera app for Windows Phone e How to use camera focus in an app for Windows Phone.

Este é o código XAML da página:

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
 
<Canvas x:Name="viewfinderCanvas">
 
<!--Camera viewfinder -->
<Canvas.Background>
 
<VideoBrush x:Name="viewfinderBrush">
<VideoBrush.RelativeTransform>
<CompositeTransform
x:Name="viewfinderTransform"
CenterX="0.5"
CenterY="0.5"
Rotation="90"/>
</VideoBrush.RelativeTransform>
</VideoBrush>
</Canvas.Background>
<TextBlock
x:Name="focusBrackets"
Text="[ ]"
FontSize="40"
Visibility="Collapsed"/>
</Canvas>
<!--Used for debugging >-->
<StackPanel Grid.Row="1" Margin="20, 0">
<TextBlock x:Name="tbBarcodeType" FontWeight="ExtraBold" />
<TextBlock x:Name="tbBarcodeData" FontWeight="ExtraBold" TextWrapping="Wrap" />
</StackPanel>
</Grid>

E este é o código:

public partial class Scan : PhoneApplicationPage
{
private PhotoCamera _phoneCamera;
private IBarcodeReader _barcodeReader;
private DispatcherTimer _scanTimer;
private WriteableBitmap _previewBuffer;
 
public Scan()
{
InitializeComponent();
}
 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
// Initialize the camera object
_phoneCamera = new PhotoCamera();
_phoneCamera.Initialized += cam_Initialized;
_phoneCamera.AutoFocusCompleted += _phoneCamera_AutoFocusCompleted;
 
CameraButtons.ShutterKeyHalfPressed += CameraButtons_ShutterKeyHalfPressed;
 
//Display the camera feed in the UI
viewfinderBrush.SetSource(_phoneCamera);
 
 
// This timer will be used to scan the camera buffer every 250ms and scan for any barcodes
_scanTimer = new DispatcherTimer();
_scanTimer.Interval = TimeSpan.FromMilliseconds(250);
_scanTimer.Tick += (o, arg) => ScanForBarcode();
 
viewfinderCanvas.Tap += new EventHandler<GestureEventArgs>(focus_Tapped);
 
base.OnNavigatedTo(e);
}
 
void _phoneCamera_AutoFocusCompleted(object sender, CameraOperationCompletedEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
focusBrackets.Visibility = Visibility.Collapsed;
});
}
 
void focus_Tapped(object sender, GestureEventArgs e)
{
if (_phoneCamera != null)
{
if (_phoneCamera.IsFocusAtPointSupported == true)
{
// Determine the location of the tap.
Point tapLocation = e.GetPosition(viewfinderCanvas);
 
// Position the focus brackets with the estimated offsets.
focusBrackets.SetValue(Canvas.LeftProperty, tapLocation.X - 30);
focusBrackets.SetValue(Canvas.TopProperty, tapLocation.Y - 28);
 
// Determine the focus point.
double focusXPercentage = tapLocation.X / viewfinderCanvas.ActualWidth;
double focusYPercentage = tapLocation.Y / viewfinderCanvas.ActualHeight;
 
// Show the focus brackets and focus at point.
focusBrackets.Visibility = Visibility.Visible;
_phoneCamera.FocusAtPoint(focusXPercentage, focusYPercentage);
}
}
}
 
void CameraButtons_ShutterKeyHalfPressed(object sender, EventArgs e)
{
_phoneCamera.Focus();
}
 
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
//we're navigating away from this page, we won't be scanning any barcodes
_scanTimer.Stop();
 
if (_phoneCamera != null)
{
// Cleanup
_phoneCamera.Dispose();
_phoneCamera.Initialized -= cam_Initialized;
CameraButtons.ShutterKeyHalfPressed -= CameraButtons_ShutterKeyHalfPressed;
}
}
 
void cam_Initialized(object sender, Microsoft.Devices.CameraOperationCompletedEventArgs e)
{
if (e.Succeeded)
{
this.Dispatcher.BeginInvoke(delegate()
{
_phoneCamera.FlashMode = FlashMode.Off;
_previewBuffer = new WriteableBitmap((int)_phoneCamera.PreviewResolution.Width, (int)_phoneCamera.PreviewResolution.Height);
 
_barcodeReader = new BarcodeReader();
 
// By default, BarcodeReader will scan every supported barcode type
// If we want to limit the type of barcodes our app can read,
// we can do it by adding each format to this list object
 
//var supportedBarcodeFormats = new List<BarcodeFormat>();
//supportedBarcodeFormats.Add(BarcodeFormat.QR_CODE);
//supportedBarcodeFormats.Add(BarcodeFormat.DATA_MATRIX);
//_bcReader.PossibleFormats = supportedBarcodeFormats;
 
_barcodeReader.TryHarder = true;
 
_barcodeReader.ResultFound += _bcReader_ResultFound;
_scanTimer.Start();
});
}
else
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Unable to initialize the camera");
});
}
}
 
void _bcReader_ResultFound(Result obj)
{
// If a new barcode is found, vibrate the device and display the barcode details in the UI
if (!obj.Text.Equals(tbBarcodeData.Text))
{
VibrateController.Default.Start(TimeSpan.FromMilliseconds(100));
tbBarcodeType.Text = obj.BarcodeFormat.ToString();
tbBarcodeData.Text = obj.Text;
}
}
 
private void ScanForBarcode()
{
//grab a camera snapshot
_phoneCamera.GetPreviewBufferArgb32(_previewBuffer.Pixels);
_previewBuffer.Invalidate();
 
//scan the captured snapshot for barcodes
//if a barcode is found, the ResultFound event will fire
_barcodeReader.Decode(_previewBuffer);
 
}
 
}

Depois de ter implementadas as funcionalidades de acesso à câmara, a leitura de códigos de barras é bastante simples. A biblioteca ZXing.Net contém uma classe chamada BarcodeReader. É possível usar o método Decode para extrair a informação de um código de barras contido numa imagem, neste caso WriteableBitmap. Caso seja encontrado um código de barras, o evento ResultFound é disparado.

Neste caso, o DispatcherTimer _scanTimer é usado para obter uma imagem da câmara a cada 250ms que depois é usada pela classe BarcodeReader.

Por defeito, a classe BarcodeReader vai procurar por todos os tipos de códigos de barras suportados. Caso queira limitar este processo a apenas alguns formatos, tudo o que é necessário é definir a propriedade PossibleFormats. Caso verifique algumas dificuldades a ler códigos de barras, especialmente códigos 1D, pode tentar definir a propriedade TryHarder como true. Note que este modo pode ter algum impacto no desempenho. No entanto nos testes feitos com o meu Lumia 800, este impacto não é notório.

Aqui ficam alguns exemplos de códigos de barras lidos:

Sumário

Neste artigo vimos como é possível ler e gerar códigos de barras na plataforma Windows Phone usando a biblioteca ZXing.Net. Esta biblioteca suporta um vasto número de plataformas, o que poderá ser útil caso não esteja apenas a desenvolver para Windows Phone. Como esta é uma implementação de uma biblioteca muito usada em aplicações Android, encontrará muita documentação e exemplos que podem ajudar. Pode descarregar a aplicação de exemplo (File:WPBarcodes.zip) e experimentar. Existem outras bibliotecas que oferecem estas funcionalidades, por exemplo a suite Telerik RadControls for Windows Phone. Membros do Nokia Premium Developer Program for Lumia têm acesso gratuito a esta biblioteca.

This page was last modified on 25 August 2013, at 05:38.
302 page views in the last 30 days.
×