tag:blogger.com,1999:blog-82057444472440840962024-03-22T05:00:32.077+00:00eunaoqueroumblogueSempre tive desde pequenino o sonho de não ter um blogue. Espero que este blogue me ajude a alcançar esse sonho.Unknownnoreply@blogger.comBlogger64125tag:blogger.com,1999:blog-8205744447244084096.post-81837268291360857902014-12-14T22:41:00.004+00:002014-12-14T22:41:46.348+00:00Daemon rTorrent com ScreenUsar o rTorrent como cliente de torrents numa máquina remota ou headless.<br />
<br />
Como o rTorrent é um programa baseado em terminal, para poder correr precisa de um terminal, ou em alternativa de um screen ou dtach.<br />
Vou usar o screen e também a interface web RTGui.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">aptitude install rtorrent screen rtgui</span><br />
<br />
Adiciona-se um utilizador que será usado apenas para executar o rTorrent:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">adduser rtorrent</span><br />
<br />
Cria-se o ficheiro /etc/init.d/rtorrent com o seguinte conteúdo:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">#! /bin/sh</span><br />
<span style="font-family: Courier New, Courier, monospace;"># rTorrent init script</span><br />
<span style="font-family: Courier New, Courier, monospace;">#</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">case "$1" in</span><br />
<span style="font-family: Courier New, Courier, monospace;"> start)</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>echo "Starting rtorrent..."</span><br />
<span style="font-family: Courier New, Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>su rtorrent -c 'screen -dmS rtorrent rtorrent'</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ;;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> stop)</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>echo "Stopping rtorrent..."</span><br />
<span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>killall -s 2 rtorrent</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ;;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> *)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> echo "Usage: $0 {start|stop}"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> exit 1</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ;;</span><br />
<span style="font-family: Courier New, Courier, monospace;">esac</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">exit 0</span><br />
<br />
Definem-se as permissões e as opções necessárias:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">chmod 755 /etc/init.d/rtorrent</span><br />
<span style="font-family: Courier New, Courier, monospace;">update-rc.d rtorrent defaults</span><br />
<span style="font-family: Courier New, Courier, monospace;">mkdir /etc/rtorrent</span><br />
<span style="font-family: Courier New, Courier, monospace;">cd /etc/rtorrent</span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span style="font-family: Courier New, Courier, monospace;">usermod -d /etc/rtorrent rtorrent</span></div>
<span style="font-family: Courier New, Courier, monospace;">wget http://rtgui.googlecode.com/files/.rtorrent.rc</span><br />
<br />
O ficheiro está em formato DOS, é preciso converter para formato linux para o rTorrent o conseguir ler.<br />
Edita-se o ficheiro .rtorrent.rc, para conter os caminhos certos das diretorias, por exemplo:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">directory=/media/disk1</span><br />
<br />
Para configurar a interface web edita-se o ficheiro /etc/apache2/sites-enabled/000-default e adicionam-se estas linhas antes do último "</VirtualHost >"<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">LoadModule scgi_module /usr/lib/apache2/modules/mod_scgi.so</span><br />
<span style="font-family: Courier New, Courier, monospace;">SCGIMount /RPC2 127.0.0.1:5000</span><br />
<div>
<br /></div>
<div>
Após esta alteração é preciso reniciar o Apache.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-39885034227124471502014-12-14T12:18:00.001+00:002014-12-14T12:24:10.993+00:00Servidor de impressão para Windows e Linux com CUPSServidor linux, no meu caso, Debian 6.0 Squeeze, a servir para a rede a impressora HP 1050 com o CUPS 1.4.4.<br />
<br />
Entrar no servidor como root e instalar:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">aptitude install cups hplip</span><br />
<br />
O script de instalação inicia o cups, mas o daemon tem de estar desligado para as alterações nos ficheiros de configuração funcionarem, por isso fazemos:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">/etc/init.d/cups stop</span><br />
<br />
Editamos o ficheiro nano /etc/cups/cupsd.conf:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">#</span><br />
<span style="font-family: Courier New, Courier, monospace;">#</span><br />
<span style="font-family: Courier New, Courier, monospace;"># Sample configuration file for the Common UNIX Printing System (CUPS)</span><br />
<span style="font-family: Courier New, Courier, monospace;"># scheduler. See "man cupsd.conf" for a complete description of this</span><br />
<span style="font-family: Courier New, Courier, monospace;"># file.</span><br />
<span style="font-family: Courier New, Courier, monospace;">#</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;"># Log general information in error_log - change "info" to "debug" for</span><br />
<span style="font-family: Courier New, Courier, monospace;"># troubleshooting...</span><br />
<span style="font-family: Courier New, Courier, monospace;">LogLevel warn</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;"># Only listen for connections from the local machine.</span><br />
<span style="font-family: Courier New, Courier, monospace;"><b>Listen 0.0.0.0:631</b></span><br />
<span style="font-family: Courier New, Courier, monospace;">Listen /var/run/cups/cups.sock</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;"># Show shared printers on the local network.</span><br />
<span style="font-family: Courier New, Courier, monospace;">Browsing On</span><br />
<span style="font-family: Courier New, Courier, monospace;">BrowseOrder allow,deny</span><br />
<span style="font-family: Courier New, Courier, monospace;">BrowseAllow all</span><br />
<span style="font-family: Courier New, Courier, monospace;"><b>BrowseAddress @LOCAL</b></span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;"># Default authentication type, when authentication is required...</span><br />
<span style="font-family: Courier New, Courier, monospace;">DefaultAuthType Basic</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span><b><span style="font-family: Courier New, Courier, monospace;">JobRetryInterval 60</span></b><br />
<b><span style="font-family: Courier New, Courier, monospace;">JobRetryLimit 10</span></b><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;"># Restrict access to the server...</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /><Location /><br /> Order allow,deny<br /><b> Allow localhost<br /> Allow @LOCAL</b><br /></Location></span><span style="font-family: Courier New, Courier, monospace;"><br /># Restrict access to the admin pages...<br /><Location /admin><br /><b> Encryption Required</b><br /> Order allow,deny<br /><b> Allow @LOCAL</b><br /></Location><br /><br /># Restrict access to configuration files...<br /><Location /admin/conf><br /><b> AuthType Basic</b><br /> Require user @SYSTEM<br /> Order allow,deny<br /><b> Allow @LOCAL</b><br /></Location><br />(...)</span><br />
<div>
<br /></div>
Editamos o ficheiro /etc/cups/cups-files.conf:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"># Administrator user group...</span><br />
<span style="font-family: Courier New, Courier, monospace;">SystemGroup lpadmin</span><br />
<br />
Inicia-se o daemon cups e adicionam-se as impressoras. O painel de configuração está em https://<endereço_ip>:631, onmde <endereço_ip> é o endereço ip da máquina onde o CUPS está instalado.<br />
Depois volta a desativar-se o cups e edita-se o ficheiro /etc/cups/printers.conf, para mudar a política em caso de erro:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">(...)</span><br />
<span style="font-family: Courier New, Courier, monospace;">ErrorPolicy retry-job</span><br />
<span style="font-family: Courier New, Courier, monospace;">(...)</span><br />
<br />
Podemos ainda dizer qo SAMBA para usar o cups para fazer impressões. Editar /etc/samba/smb.conf<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">[printers]</span><br />
<span style="font-family: Courier New, Courier, monospace;"> comment = All Printers</span><br />
<span style="font-family: Courier New, Courier, monospace;"> browseable = no</span><br />
<span style="font-family: Courier New, Courier, monospace;"> path = /tmp</span><br />
<span style="font-family: Courier New, Courier, monospace;"> printable = yes</span><br />
<span style="font-family: Courier New, Courier, monospace;"> public = yes</span><br />
<span style="font-family: Courier New, Courier, monospace;"> writable = no</span><br />
<span style="font-family: Courier New, Courier, monospace;"> create mode = 0700</span><br />
<span style="font-family: Courier New, Courier, monospace;"> printcap name = /etc/printcap</span><br />
<span style="font-family: Courier New, Courier, monospace;"> print command = /usr/bin/lpr -P%p -r %s</span><br />
<span style="font-family: Courier New, Courier, monospace;"> printing = cups</span><br />
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-46929234616934829302013-10-06T15:36:00.000+01:002013-10-06T15:38:11.210+01:00Desativar serviços no Windows 7O Windows 7 ( e todos os outros Windows depois e antes) tem uma grande quantidade de serviços a correr em background cuja única finalidade parece ser consumir recursos sem fornecer grande serviço...<br />
Infelizmente, desligar serviços à toa pode ter consequências desagradáveis, pois estão interligados por uma rede de dependências e nem sempre é claro qual a consequência de desativar determinado serviço.<br />
Ainda assim, compilei uma lista de serviços que são mais ou menos seguros de desativar, em determinadas situações.<br />
A partir da linha de comandos os serviços podem ser desligados com <span style="font-family: Courier New, Courier, monospace;">sc stop "nome_do_serviço" </span>e ligados com <span style="font-family: Courier New, Courier, monospace;">sc start "nome_do_serviço"</span>. Para desativar realmente o serviço também pode ser usado a linha de comandos, mas não vou aqui fazer isso. Apenas voi criar dois batch files para parar e reiniciar os respetivos serviços. Os comentários das batch files são auto-explicativos.<br />
<h4>
</h4>
<h4>
Desligar seviços</h4>
<div>
<br /></div>
<span style="font-family: Courier New, Courier, monospace;">@echo off</span><br />
<span style="font-family: Courier New, Courier, monospace;">rem Sem Homegroup estes seviços são desnecessários</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "upnphost"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "Mcx2Svc"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "SSDPSRV"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "HomeGroupProvider"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Desligar o aero, temas, animações, etc do ecrã</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "UxSms"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "Themes"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Desligar a impressora, scanner, fax</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "Spooler"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "StiSvc"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "TapiSrv"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "Fax"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Desligar o diagnóstico e relato de erros</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "DPS"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Desligar o ambiente de trabalho remoto</span><br />
<span style="font-family: Courier New, Courier, monospace;">rem (tanto cliente como servidor)</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "UmRdpService"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "SessionEnv"</span><br />
<span style="font-family: Courier New, Courier, monospace;">echo Esperar 2 segundos...</span><br />
<span style="font-family: Courier New, Courier, monospace;">choice /c sn /n /t 2 /d s</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "TermService"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Desligar as atualizações e pesquisa do Windows</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "wuauserv"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "WSearch"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "WPDBusEnum"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "BITS"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "lmhosts"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Desligar outras atualizações (adobe e google)</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "AdobeARMService"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "gupdate"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc stop "gupdatem"</span><br />
<h4>
</h4>
<h4>
Ligar os serviços</h4>
<div>
<br /></div>
<span style="font-family: Courier New, Courier, monospace;">@echo off</span><br />
<span style="font-family: Courier New, Courier, monospace;">rem Para usar o Homegroup</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "upnphost"</span><br />
<span style="font-family: Courier New, Courier, monospace;">rem sc start "Mcx2Svc"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "SSDPSRV"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "HomeGroupProvider"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Ativar aero e animações de ecrã, etc</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "UxSms"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "Themes"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Ativar a impressora e scanner</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "Spooler"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "StiSvc"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "TapiSrv"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Ativar o diagnósticos e relato de erros</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "DPS"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Ativar o ambiente de trabalho remoto</span><br />
<span style="font-family: Courier New, Courier, monospace;">rem (cliente e servidor)</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "SessionEnv"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "TermService"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "UmRdpService"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Ativar atualizações e pesquisa do Windows</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "wuauserv"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "WSearch"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "WPDBusEnum"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "BITS"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "lmhosts"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">rem Ativar outras atualizações (adobe, google)</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "AdobeARMService"</span><br />
<span style="font-family: Courier New, Courier, monospace;">sc start "gupdate"</span><br />
<br />
Parando todos os serviços é possível libertar várias centenas de MiB de memória RAM e muitos ciclos de processador.<br />
<h4>
</h4>
<h4>
<br /></h4>
<h4>
Referências</h4>
<div>
<br /></div>
<div>
<a href="http://windows7themes.net/windows-7-services-safe-to-disable.html">http://windows7themes.net/windows-7-services-safe-to-disable.html</a></div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-8205744447244084096.post-86343773405405471622013-10-04T21:23:00.000+01:002013-10-04T21:31:06.796+01:00Restaurar WIM no LinuxOs ficheiros WIM (Windows IMage) são ficheiros comprimidos que contêm uma estrutura de diretórios ou um sistema de ficheiros inteiro do Windows e mais alguns metadados necessários para restaurar os ficheiros.<br />
Os ficheiros WIM são normalmente usados para guardar e restaurar a partição de sistema do Windows, sendo portanto usados nas partições e discos de recuperação.<br />
Um ficheiro WIM pode conter vários "volumes" internamente. A reposição do sistema normalmente implica a reposição de todos os volumes do ficheiro.<br />
O ficheiro de reposição tem geralmente o nome boot.wim, mas pode ter outros nomes (como install.wim, final.wim, etc).<br />
Os portáteis costumam trazer um programa específico para ler estes ficheiros e executar a recuperação do sistema.<br />
Também é possível fazer a recuperação "à mão" usando o utilitário imagex.exe da Microsoft.O imagex é um executável de menos de 1 MiB que está incluído no WAIK (Windows Automated Installation Kit), que é um download de quase 2 GiB.<br />
A recuperação pela linha de comandos não é propriamente simples, pois é preciso ter outro Windows onde executar os comandos, uma vez que vamos apagar completamente o Windows "original" do disco.<br />
Existe, no entanto, um pacote wimtools para linux que permite manipular os ficheiros WIM de forma muito semelhante ao Windows.<br />
As wimtools estão disponíveis em várias distribuições, mas o mais simples é usar Ubuntu, pois há um PPA para várias versões de Ubuntu:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">sudo add-apt-repository ppa:nilarimogard/webupd8</span><br />
<span style="font-family: Courier New, Courier, monospace;">sudo apt-get update</span><br />
<span style="font-family: Courier New, Courier, monospace;">sudo apt-get install wimtools</span><br />
<br />
Admitindo que o ficheiro WIM está em /media/pen/boot.wim e que a partição de destino é /dev/sda2, é preciso:<br />
<br />
<ol>
<li>Formatar a partição /dev/sda2 para ntfs</li>
<li>Recuperar o ficheiro WIM: <br /><span style="font-family: Courier New, Courier, monospace;">wimlib-imagex apply /media/pen/boot.wim 1 /dev/sda2</span></li>
<ol>
<li>Repetir o comando anterior para todos os volumes dentro de boot.wim (o número identifica o volume)</li>
</ol>
<li>Atualizar o gestor de arranque (por exemplo o Grub) para reconhecer os novos ficheiros na partição /dev/sda2</li>
<li>Reiniciar e esperar</li>
</ol>
<div>
Depois fazer uma imagem com o partimage e salvar o setor de arranque e tabela de partições com o dd, porque os ficheiros WIM são muito chatos de usar.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-36156613577824119622013-08-29T19:15:00.000+01:002013-10-04T21:24:56.877+01:00Raspberry Pi<br />
<br />
A Universidade de Cambridge é uma das mais conceituadas universidades do mundo, mas desde há alguns anos se tem vindo a debater com um problema nos cursos de informática. A cada ano que passa os candidatos a estes cursos parecem vir cada vez pior preparados! O que significa que tem de ser investido mais tempo a ensinar a estes alunos conceitos que já deveriam ter adquirido. Sobra portanto menos tempo para aprender tópicos mais avançados, que fazem a diferença quando as empresas de informática pretendem contratar novos colaboradores. É claro que isto acaba por ter um efeito direto muito mais importante em nós os utilizadores finais: os jogos perdem qualidade, porque não há bons programadores para os fazer!<br />
<br />
<br />
A Universidade procurou descobrir a razão desta tendência e chegou à conclusão de que se deve ao facto de as crianças terem menos necessidade de "experimentar" os computadores. Quando Bill Gates e Steve Jobs iniciaram as suas fortunas, os computadores eram apenas para "entusiastas" da eletrónica. Os computadores eram vendidos em kits (ou era preciso comprar as peças) e montá-los e programá-los manualmente para funcionarem. Atualmente os computadores são comprados já prontos para ser usados, com uma interface colorida, simples, bonita e cara, que desincentiva os utilizadores a desmontar a máquina e a experimentar.<br />
<br />
<br />
Iniciou-se assim um projeto para trazer de volta os "bons velhos tempos" em que os utilizadores eram incentivados a experimentar com as suas máquinas. Nasceu o projeto <a href="http://www.raspberrypi.org/">Raspberry Pi</a>.<br />
<a href="http://www.raspberrypi.org/wp-content/uploads/2012/11/2012-11-29-14.48.47-HDR.jpg"><img height="300" src="http://www.raspberrypi.org/wp-content/uploads/2012/11/2012-11-29-14.48.47-HDR.jpg" width="400" /></a> <br />
<br />
Raspberry Pi Modelo A<br />
<br />
<br />
Um Raspberry Pi é um dispositivo do tamanho de um cartão de crédito, capaz de realizar as mesmas tarefas de um computador de secretária de entrada de gama, mas produzido de forma a ser de baixo custo.<br />
<br />
<br />
O modelo A (mais limitado) tem 128 MB de RAM, uma porta USB. O modelo B tem 256 MB de RAM, duas portas USB e uma porta ethernet. Ambos os modelos têm uma porta <a href="http://en.wikipedia.org/wiki/HDMI">HDMI</a> e saída vídeo <a href="http://en.wikipedia.org/wiki/RCA">RCA</a> e audio stereo. No lugar de disco rígido possuiu uma ligação a um cartão SD interno. O processador é um ARM 11 a 700 MHz incluído num SoC (<a href="http://en.wikipedia.org/wiki/System_on_a_chip">System on Chip</a> - todo o sistema está incluído num único chip) que contém também um processador gráfico <a href="http://en.wikipedia.org/wiki/VideoCore">Videocore</a> 4, capaz de descodificar vídeo em alta resolução.<br />
<br />
<br />
Todos os componentes foram escolhidos de forma a serem baratos, mas capazes de desempenho aproximadamente equivalente a um PC de secretária e capazes de correr com uma fonte limitada de energia. A alimentação elétrica é fornecida através de uma ligação micro-USB padrão com 5 V, pelo que pode ser alimentada por 4 pilhas AA.<br />
<br />
<br />
O Raspberry não inclui na embalagem disco, teclado, rato nem monitor. O disco é substituído por um cartão SD que pode ser facilmente trocado (evitando portanto que o sistema fique "bricado", pois se encravar basta substituir o cartão SD). O monitor é o componente mais caro de um PC, por isso o Raspberry possui uma saída HDMI que lhe permite ser ligado a uma televisão ou monitor recentes e uma saída RCA para ligar a televisões mais antigas.<br />
<br />
<br />
O dispositivo é compatível com uma série de distribuições linux, existindo na internet muitos recursos, tanto oficiais como de entusiastas, sobre como colocar uma determinada distribuição (versão) de linux no Raspberry Pi. Agora perguntam-se "<a href="http://en.wikipedia.org/wiki/Linux">Linux</a>?! Então e Windows?". O objetivo do Raspberry é que os utilizadores experimentem e compreendam o funcionamento do sistema, o que não é possível usando um sistema fechado, como o Windows.<br />
<br />
<br />
Há utilizadores que transformram o Raspberry em PCs de secretária, servidores, estações multimédia para a sala, colocaram-nos em balões e aviões telecomandados, usaram-nos como partes de um sistema de domótica, etc. O limite é a imaginação :)<br />
<br />
<br />
<img src="http://img2.blogblog.com/img/video_object.png" />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-26870660282890665362013-08-27T12:38:00.002+01:002015-02-12T19:48:23.957+00:00Rádios Online<h2>
Rádios Online</h2>
<ul>
<li><a href="http://7709.live.streamtheworld.com:3690/RADIO_RENASCENCA_SC">Rádio Renascença</a></li>
<li><a href="http://www.rtp.pt/play/direto/antena1">Antena 1</a></li>
<li><a href="http://www.rtp.pt/play/direto/antena2">Antena 2</a></li>
<li><a href="http://www.rtp.pt/play/direto/antena3">Antena 3</a></li>
<li><a href="http://7779.live.streamtheworld.com:3690/RFM_SC">RFM</a></li>
<li><a href="http://7719.live.streamtheworld.com:3690/OCEANPACIFIC_SC">RFM Oceano Pacífico</a></li>
<li><a href="http://7749.live.streamtheworld.com:3690/GR80SRFM_SC">RFM Amos 80</a></li>
<li><a href="http://emdirecto.tsf.pt/tsfdirecto?MSWMExt=.asf">TSF</a></li>
</ul>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-24292894399697253582013-06-23T15:04:00.000+01:002013-06-23T15:04:51.575+01:00PXE Boot ServerCriar um servidor de imagens PXE com Debian Wheezy<br />
<br />
Iniciando com uma máquina Debian já instalada é preciso:<br />
<br />
<ol>
<li>Instalar o TFTP e DHCP</li>
<li>Configurar o TFTP e DHCP</li>
<li>Criar uma imagem PXE</li>
</ol>
<div>
O servidor DHCP escolhido é o isc-dhcp-server e o servidor TFTP é o tftpd-hpa.</div>
<div>
A interface onde vai funcionar o servidor DHCP tem de estar já configurada e ter um IP estático (não pode haver dois servidores DHCP no mesmo segmento de rede).</div>
<div>
<br /></div>
<h3>
1. Instalar o TFTP e DHCP</h3>
<div>
<br /></div>
<div>
Como de costume com Debian, a instalação é muito simples, a configuração é que é complicada.</div>
<div>
<br /></div>
<div>
<span style="font-family: Georgia, Times New Roman, serif; font-size: x-small;">aptitude install isc-dhcp-server tftpd-hpa</span></div>
<div>
<br /></div>
<h3>
2. Configurar o TFTP e o DHCP</h3>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">nano /etc/default/tftpd-hpa</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<br />
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">TFTP_USERNAME="tftp"</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">TFTP_DIRECTORY="/srv/tftp"</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">TFTP_ADDRESS="0.0.0.0:69"</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">TFTP_OPTIONS="--secure"</span></div>
</div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">nano /etc/default/isc-dhcp-server</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">INTERFACES="eth1"</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">nano /etc/dhcp/dhcpd.conf</span></div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">allow booting;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">allow bootp;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">authoritative;</span></div>
</div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">subnet 10.0.0.0 netmask 255.255.255.0 {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> range dynamic-bootp 10.0.0.20 10.0.0.100;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> option routers 10.0.0.254;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> option broadcast-address 10.0.0.255;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> option domain-name-servers 208.67.222.222;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> allow unknown-clients;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> next-server 10.0.0.254;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> filename "pxelinux.0";</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div>
</div>
<div>
<br /></div>
<div>
Reiniciar os serviços:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">service tftpd-hpa restart</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">service isc-dhcp-server restart</span></div>
<div>
<br /></div>
<h3>
3. Criar uma imagem PXE</h3>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">aptitude install debootstrap nfs-kernel-server</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">mkdir /srv/tftp/pxeroot</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">debootstrap wheezy /srv/tftp/pxeroot</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">cd /srv/tftp/pxeroot</span></div>
</div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">nano etc/network/interfaces</span></div>
<div>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">auto lo</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">iface lo inet loopback</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">auto eth0</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">iface eth0 inet dhcp</span></blockquote>
</div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">nano etc/fstab</span></div>
<div>
<div>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">/dev/ram0 / ext2 defaults 0 0</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">proc /proc proc defaults 0 1</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">tmpfs /tmp tmpfs defaults 0 1</span></blockquote>
</div>
</div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">chroot /srv/tftp/pxeroot</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">aptitude install linux-image-486</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">aptitude install partimage</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">aptitude install locales</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">dpkg-reconfigure locales</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">adduser root</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">adduser user</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">aptitude install xorg icewm slim</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">exit</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">cd /srv/tftp</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">wget http://ftp.debian.org/debian/dists/wheezy/main/installer-i386/current/images/netboot/pxelinux.0</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">cp pxeroot/vmlinuz ./</span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">cp pxeroot/initrd.img ./</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">mkdir pxelinux.cfg</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">nano pxelinux.cfg/default</span></div>
</div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">default menu.c32</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">prompt 0</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">timeout 300</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">ONTIMEOUT local</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">MENU TITLE Welcome to PXE</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">LABEL Debian Wheezy x86</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> MENU LABEL Debian Wheezy x86</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> KERNEL images/deb-installer/linux</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> APPEND initrd=images/deb-installer/initrd.gz</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">LABEL linux</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> kernel pxeroot/vmlinuz</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> append vga=normal initrd=pxeroot/boot/initrd.img-3.2.0-4-486 ramdisk_size=14332 root=/dev/nfs nfsroot=10.0.0.254:/srv/tftp/pxeroot rw --</span></blockquote>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">nano /etc/exports</span></div>
<div>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">/srv/tftp/pxeroot 10.0.0.0/255.255.255.0(rw,sync,no_root_squash,no_subtree_check)</span></blockquote>
</div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">service nfs-kernel-server restart</span></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-66920685601340490052013-03-10T21:06:00.000+00:002013-03-10T23:27:52.023+00:00Checklist de segurança Joomla!Algumas dicas de segurança mais ou menos avulsas para Joomla.<br />
<h2>
A. Geral</h2>
<ol>
<li>Aplicam-se as regras de segurança genéricas para o Apache, PHP e MySQL.</li>
</ol>
<h2>
B. Instalação</h2>
<div>
<ol>
<li>Não usar o prefixo de tabela MySQL "jos_".</li>
<li>Definir as permissões do configuration.php para 444 (ou pelo menos 644).</li>
<li>Em geral, os ficheiro PHP precisam de permissões 644 (preferencialmente 444) e as diretorias 755 (ou preferencialmente 555).</li>
<li>De forma geral é boa ideia mover as diretorias /tmp, /log e todas as diretorias que precisem permissão de escrita (caches, imagens, uploads, etc) para FORA da diretoria pública (public_html), retirando-lhes portanto a possibilidade de acesso através de HTTP. No entanto isto pode causar problemas com a diretiva open_basedir do PHP e com algumas extensões.</li>
<li>Não permitir o upload de scripts</li>
<li>Renomear o ficheiro <span style="font-family: Courier New, Courier, monospace;">htaccess.txt</span> para <span style="font-family: Courier New, Courier, monospace;">.htaccess</span> e ligar o RewriteEngine.</li>
<li>A adição destas linhas ao <span style="font-family: Courier New, Courier, monospace;">.htaccess</span> bloqueia alguns exploits mais comuns:</li>
</ol>
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">########## Begin - Rewrite rules to block out some common exploits<br />#<br /># Block out any script trying to set a mosConfig value through the URL<br />RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [OR]<br /># Block out any script trying to base64_encode crap to send via URL<br />RewriteCond %{QUERY_STRING} base64_encode.*(.*) [OR]<br /># Block out any script that includes a < script> tag in URL<br />RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]<br /># Block out any script trying to set a PHP GLOBALS variable via URL<br />RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR]<br /># Block out any script trying to modify a _REQUEST variable via URL<br />RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2}) [OR]<br /># Block out any script that tries to set CONFIG_EXT (com_extcal2 issue)<br />RewriteCond %{QUERY_STRING} CONFIG_EXT([|%20|%5B).*= [NC,OR]<br /># Block out any script that tries to set sbp or sb_authorname via URL (simpleboard)<br />RewriteCond %{QUERY_STRING} sbp(=|%20|%3D) [OR]<br />RewriteCond %{QUERY_STRING} sb_authorname(=|%20|%3D)<br /># Send all blocked request to homepage with 403 Forbidden error!<br />RewriteRule ^(.*)$ index.php [F,L]<br />#<br />########## End - Rewrite rules to block out some common exploits</span></div>
<h2>
C. Utilizadores e passwords</h2>
<ol>
<li>Usar passwords não triviais.</li>
<li>Criar uma conta de administrador com um username não trivial (ou seja, diferente de admin, administrator, root, etc). Promover esse utilizador a super-user e apagar a conta de admin. Além de ser um username conhecido, a conta de admin tem sempre o id 42 (homenagem ao Hitchhicker's Guide to The Galaxy), por isso é uma vulnerabilidade potencial (para Joomla anterior a 2.5.5).</li>
</ol>
<h2>
D. Extensões</h2>
<ol>
<li>Não instalar extensões desnecessárias.</li>
<li>A extensão <b>sh404SEF</b> adiciona mais um nível de segurança e capacidades SEF (Search Engine Friendly). Esta extensão é vulnerável nas versões < 3.7.0.</li>
<li>A extensão <b>Admin Tools Core</b> permite aplicar num único local várias das proteções aqui referidas.</li>
<li>A extensão <b>Akeeba Backup Core</b> permite fazer backups completos de forma simples.</li>
<li>Há outras extensões que melhoram a segurança (mas ver regra D.1).</li>
</ol>
<h2>
E. Não fornecer informação gratuita</h2>
<ol>
<li>Não publicitar o nome e versão do Joomla. Remover a meta tag "Generator".</li>
<li>Não publicitar o nome e versão das extensões.</li>
</ol>
<h2>
F. Ações periódicas</h2>
<ol>
<li>Fazer backups regulares (por exemplo com o Akeeba Backup)</li>
<li>Fazer regularmente uma "inspeção visual" e eliminar ficheiros suspeitos/desnecessários.</li>
<li>Fazer testes de vulnerabilidades (com o nikto, joomscan, etc) e corrigir as vulnerabilidades detetadas.</li>
<li>Manter-se atualizado sobre as novas vulnerabilidades descobertas consultando sites especializados (<a href="http://secunia.com/search/?search=joomla">http://secunia.com/search/?search=joomla</a>, <a href="http://www.frsirt.com/english">http://www.frsirt.com/english</a>, <a href="http://www.milw0rm.com/">http://www.milw0rm.com/</a>, por exemplo)</li>
</ol>
<h2>
G. Atualizar</h2>
<ol>
<li>Manter o Apache, PHP e MySQL atualizados.</li>
<li>Manter o Joomla atualizado. A partir da versão 1.6 há a opção de o Joomla se autoatualizar (mas é necessário verificar a disponibilidade das extensões). Não usar Joomla 1.5 ou anterior.</li>
<li>Manter as extensões atualizadas. Mesmo as extensões mais conhecidas e populares têm problemas de segurança.</li>
</ol>
<h2>
Referências</h2>
<div>
<a href="http://docs.joomla.org/Security">http://docs.joomla.org/Security</a></div>
<div>
<a href="http://docs.joomla.org/Security_Checklist/Joomla!_Setup">http://docs.joomla.org/Security_Checklist/Joomla!_Setup</a><br />
<a href="http://docs.joomla.org/Joomla_Administrators_Security_Checklist">http://docs.joomla.org/Joomla_Administrators_Security_Checklist</a><br />
<a href="http://www.marcofolio.net/joomla/7_tips_to_optimize_joomla_security.html">http://www.marcofolio.net/joomla/7_tips_to_optimize_joomla_security.html</a></div>
<div>
<br /></div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8205744447244084096.post-22992761445295046352013-03-10T11:28:00.000+00:002013-03-10T11:32:35.858+00:00Cliente GoogleDrive em DebianO Google Drive já anda por aí há uns bons meses e a Google ainda não libertou o cliente para linux.<br />
Há já varias alternativas não oficiais, algumas open source outras não.<br />
A insync disponibiliza um cliente de sincronização para Google Drive em linux (muitas distribuições suportadas) que é gratuito em versão beta, mas que se vai tornar pago quando sair de beta. Enquanto está em beta e a Google não acaba o seu próprio cliente esta é a maneira de instala o insync.<br />
Em Debian (ou Ubuntu ou Mint) basta importar a chave do repositório com:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">wget -qO - https://d2t3ff60b2tol4.cloudfront.net/services@insynchq.com.gpg.key | sudo apt-key add -</span><br />
<br />
Acrescentar um ficheiro <span style="font-family: Courier New, Courier, monospace;">/etc/apt/sources.list.s/insync.list</span>, com a linha:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">deb http://apt.insynchq.com/[DISTRIBUTION] [CODENAME] non-free</span><br />
<br />
Em que<span style="font-family: Courier New, Courier, monospace;"> [DISTRIBUTION]</span> é o nome da distribuição e <span style="font-family: Courier New, Courier, monospace;">[CODENAME]</span> é o nome da versão. Por exemplo, para Debian 6 (squeeze) fica:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">deb http://apt.insynchq.com/debian squeeze non-free</span><br />
<br />
Atualizar os repositórios:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">apt-get update</span><br />
<br />
Há pacotes diferentes para cada interface gráfico. Instalar com<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">apt-get install insync-beta-[INTERFACE]</span><br />
<br />
Para debian com Gnome fica:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">apt-get install insync-beta-gnome</span><br />
<br />
[INTERFACE] pode ser: ubuntu, cinnamon, gnome, kde, mate, xfce<br />
O pacote kde suporta KDE 4.<br />
O pacote gnome, aparentemente, só suporta Gnome 3, porque não consegui instalar em Squeeze.<br />
<br />
<br />
<span style="font-size: large;"><b>Referência:</b></span><br />
<a href="https://www.insynchq.com/linux">https://www.insynchq.com/linux</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-83714484911008040902013-02-03T15:51:00.000+00:002013-02-03T15:51:59.664+00:00<h2>
Proteger o acesso a uma página web do Apache com .htaccess</h2>
O ficheiro .htaccess permite modificar o comportamento do servidor web Apache de várias formas. Uma dessas formas é a definição de uma password que tem de ser digitada para poder aceder à página.<br />
Este método envolve a criação de dois ficheiros: .htpasswd (que vai conter a password) e .htaccess (que contém as instruções para o Apache pedir a password). É necessário também ter acesso à linha de comandos do servidor (acesso físico ou por SSH).<br />
<br />
<h3>
.htpasswd</h3>
Criamos o ficheiro .htpasswd com o seguinte conteúdo:<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">myuser:X4r!23dF</span></blockquote>
Em que "<span style="font-family: Courier New, Courier, monospace;">myuser</span>" é o nome de utilizador e o "<span style="font-family: Courier New, Courier, monospace;">X4r!23dF</span>" é a password. O "<span style="font-family: Courier New, Courier, monospace;">:</span>" é o separador entre o username e a password.<br />
O .htpassword, por uma questão de segurança, deve ser criado numa pasta <b>não acessível</b> a partir da web.<br />
O ficheiro .htpasswd tem de ser encriptado para poder ser utilizado. A encriptação é feita usando o utilitário htpasswd. Portanto executamos:<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">htpasswd -c .htpasswd myuser</span></blockquote>
O parâmetro -c indica que queremos criar um novo ficheiro encriptado. O "<span style="font-family: Courier New, Courier, monospace;">myuser</span>" é o username que queremos usar. É nos pedida a password (duas vezes).<br />
Se tentarmos ver o conteúdo do .htpasswd com:<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">cat .htpasswd</span></blockquote>
Verificamos que o nome de utilizador continua visível, mas a password está encriptada.<br />
<br />
<h3>
.htaccess</h3>
Vamos agora criar o ficheiro .htaccess. Ao contrário do .htpasswd, este deve ser criado na pasta web que pretendemos proteger.<br />
O .htaccess deve ficar com este conteúdo:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">AuthUserFile /caminho/completo/.htpasswd</span><span style="font-family: Courier New, Courier, monospace;">AuthType Basic</span><span style="font-family: Courier New, Courier, monospace;">AuthName "Documento protegido"</span><span style="font-family: Courier New, Courier, monospace;">Require valid-user</span></blockquote>
<br />
<h3>
Erro comum</h3>
Se as diretivas no ficheiro .htacces aparentam não estar a funcionar, a causa mais provável é a existência da diretiva<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">AllowOverride none</span></blockquote>
na configuração da pasta no Apache. Com esta opção o ficheiro .htaccess é completamente ignorado pelo Apache. Apenas é necessário editar a linha para<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">AllowOverride all</span></blockquote>
para permitir todas as diretivas no .htaccess, ou então<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">AllowOverride AuthConfig</span></blockquote>
para autorizar apenas as oções relativas à autrnticação.<br />
Depois de alterar a configuração do Apache é necessário reiniciá-lo com<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">/etc/init.d/apache2 restart</span></blockquote>
ou com um comando equivalente.<br />
<br />
<h3>
Referências</h3>
<br />
<a href="http://www.elated.com/articles/password-protecting-your-pages-with-htaccess/">http://www.elated.com/articles/password-protecting-your-pages-with-htaccess/</a><br />
<a href="http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride">http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-78356839389389729502012-10-19T11:30:00.001+01:002012-11-30T11:44:19.792+00:00Repositórios Debian<h2>
Alguns repositórios Debian</h2>
Aqui fica uma lista de alguns repositórios Debian bem jeitosos. O sources.list fica apenas com os repositórios oficiais Debian. Os outros repositórios ficam cada um no seu ficheiro .list na diretoria sources.list.d, para ser mais fácil gerir.<br />
<h3>
</h3>
<h3>
sources.list </h3>
<br />
deb http://ftp.pt.debian.org/debian/ squeeze main contrib non-free<br />
<br />
deb-src http://ftp.pt.debian.org/debian/ squeeze main contrib non-free<br />
<br />
deb http://security.debian.org/ squeeze/updates main contrib non-free<br />
deb-src http://security.debian.org/ squeeze/updates main contrib non-free<br />
<br />
# squeeze-updates, previously known as 'volatile'<br />
deb http://ftp.pt.debian.org/debian/ squeeze-updates main contrib non-free<br />
deb-src http://ftp.pt.debian.org/debian/ squeeze-updates main contrib non-free<br />
<br />
<h3>
sources.list.d/dropbox.list</h3>
<br />
# dropbox<br />
# apt-key adv --keyserver pgp.mit.edu --recv-keys 5044912E<br />
deb http://linux.dropbox.com/debian squeeze main<br />
<br />
<h3>
sources.list.d/google.list</h3>
<br />
##########################<br />
# Google APT Repositories #<br />
##########################<br />
# wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -<br />
# Google Chrome repo http://www.google.com/linuxrepositories/<br />
deb http://dl.google.com/linux/chrome/deb/ stable main<br />
# Google Talk browser plugin http://www.google.com/chat/video<br />
# deb http://dl.google.com/linux/talkplugin/deb/ stable main<br />
# Google Earth<br />
# deb http://dl.google.com/linux/earth/deb/ stable main<br />
# Google's Music Manager<br />
# http://www.google.com/support/music/bin/answer.py?answer=1229970<br />
# deb http://dl.google.com/linux/musicmanager/deb/ stable main<br />
<br />
<h3>
sources.list.d/mozilla.list</h3>
<br />
# mozilla<br />
# http://mozilla.debian.net<br />
# iceweasel, icedove, iceape<br />
# apt-get install pkg-mozilla-archive-keyring<br />
# deb http://mozilla.debian.net/ squeeze main<br />
# firefox, thunderbird<br />
# apt-key adv --recv-keys --keyserver keyserver.ubuntu.com C1289A29<br />
deb http://downloads.sourceforge.net/project/ubuntuzilla/mozilla/apt all main<br />
# os pacotes são firefox-mozilla-build, thunderbird-mozilla-build, seamonkey-mozilla-build<br />
<br />
<h3>
sources.list.d/multimedia.list</h3>
<br />
# deb multimedia<br />
# http://deb-multimedia.org<br />
# apt-get update<br />
# apt-get install deb-multimedia-keyring<br />
deb http://deb-multimedia.org squeeze main non-free<br />
# deb http://deb-multimedia.org squeeze-backports main<br />
<br />
<h3>
sources.list.d/playonlinux.list</h3>
<br />
# play-on-linux<br />
# wget -q "http://deb.playonlinux.com/public.gpg" -O- | apt-key add -<br />
deb http://deb.playonlinux.com/ squeeze main<br />
<br />
<h3>
sources.list.d/virtualbox.list</h3>
<br />
# virtualbox<br />
# wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add -<br />
deb http://download.virtualbox.org/virtualbox/debian squeeze contrib non-free<br />
<br />
<h3>
sources.list.d/scribus.list</h3>
<br />
# scribus<br />
# apt-key adv --recv-keys --keyserver subkeys.pgp.net EEF818CF<br />
deb http://debian.scribus.net/debian stable main<br />
deb-src http://debian.scribus.net/debian stable main<br />
<h2>
Referências</h2>
<a href="https://sites.google.com/site/mydebiansourceslist/">https://sites.google.com/site/mydebiansourceslist/</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-35174118238786965302012-08-23T22:26:00.003+01:002012-08-23T22:58:33.524+01:00logwatch, fail2ban, molly-guard<i>Mais umas excelentes ferramentas para sistemas linux</i><br />
<br />
<h3>
logwatch</h3>
<br />
Instala-se com o habitual<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">apt-get install logwatch</span><br />
<br />
E já está.<br />
A instalação cria um script em <span style="font-family: 'Courier New', Courier, monospace;">/etc/cron.daily</span> que se encarrega de correr o logwatch e enviar um email para o root.<br />
<br />
Para modificar as opções pré-definidas é preciso copiar o ficheiro de configuração de exemplo para <span style="font-family: 'Courier New', Courier, monospace;">/etc/logwatch/conf</span>:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">cp /usr/share/logwatch/default.conf/logwatch.conf /etc/logwatch/conf/</span><br />
<div>
<br /></div>
<div>
E editar o ficheiro. No Debian a opção TmpDir estava mal configurada, deve ser mudada para <span style="font-family: 'Courier New', Courier, monospace;">/tmp</span>.</div>
<div>
Todas as opções podem ser sobrepostas através de parâmetros na linha de comandos.</div>
<div>
<br /></div>
<div>
O logwatch apenas cria o relatório com os eventos mais significativos do sistema, é responsabilidade do administrador ler o relatório e agir em conformidade.<br />
<br />
<h3>
fail2ban</h3>
<span style="font-family: 'Courier New', Courier, monospace;">apt-get install fail2ban</span><br />
<br />
E já está.<br />
A configuração básica está em <span style="font-family: 'Courier New', Courier, monospace;">/etc/fail2ban/fail2ban.conf</span> e a configuração mais específica em <span style="font-family: 'Courier New', Courier, monospace;">/etc/fail2ban/jail.conf</span>.<br />
<br />
Apenas a proteção das ligações SSH está pré-definida, para outros protocolos/aplicações é preciso editar o <span style="font-family: 'Courier New', Courier, monospace;">/etc/fail2ban/jail.conf</span>.<br />
<br />
<h3>
molly-guard</h3>
<span style="font-family: 'Courier New', Courier, monospace;">apt-get install molly-guard</span><br />
<br />
E já está.<br />
O molly-guard pede o nome da máquina quando tentamos desligar uma máquina através de SSH.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-90623612603077968832012-08-23T21:24:00.003+01:002012-08-23T21:33:13.088+01:00Algumas coisas básicas a fazer numa máquina nova<i>Um pequeno conjunto de aplicações e configurações a executar em máquinas novas (linux claro, Debian de preferência)</i><br />
<br />
<h3>
Rede</h3>
<br />
Primeiro que tudo é sempre preciso configurar corretamente a rede.<br />
Se a interface de rede é configurada por DHCP não há muito a fazer, mas se queremos um IP estático é preciso editar o /etc/network/interfaces e substituir o dhcp por static na interface pretendida e indicar, pelo menos o endereço, netmask e gateway, qualquer coisa assim:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">auto eth0</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">iface eth0 inet static</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> address 192.168.1.31</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> netmask 255.255.255.0</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> gateway 192.168.1.254</span><br />
<div>
<br /></div>
<div>
Mas nem só de IP vive a rede. Também é importante definir os servidores de DNS, o hostname e o domain name. Mais uma vez o DHCP trata disto, mas se quisermos um IP estático temos de editar <span style="font-family: 'Courier New', Courier, monospace;">/etc/resolv.conf</span>, <span style="font-family: 'Courier New', Courier, monospace;">/etc/hostname</span> e <span style="font-family: 'Courier New', Courier, monospace;">/etc/hosts</span>.</div>
<div>
<br /></div>
<div>
É preciso escolher um hostname, que identifica a máquina e um nome de domínio, que identifica a rede local. Vamos usar <span style="font-family: 'Courier New', Courier, monospace;">server001</span> e <span style="font-family: 'Courier New', Courier, monospace;">lan</span>, respetivamente.</div>
<div>
<br /></div>
<div>
Em <span style="font-family: 'Courier New', Courier, monospace;">/etc/resolv.conf</span> colocamos o nome de domínio e os servidores de DNS. DNS é um serviço crítico, por isso normalmente são definidos pelo menos dois. O ficheiro pode ficar com este conteúdo:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">domain lan</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">search lan</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">nameserver 208.67.220.220</span></div>
</div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">nameserver 208.67.222.222</span></div>
<div>
<br /></div>
<div>
Neste caso o domínio chama-se <span style="font-family: 'Courier New', Courier, monospace;">lan</span> (é o pré-definido) e dizemos que queremos pesquisar o domínio <span style="font-family: 'Courier New', Courier, monospace;">lan</span>. As duas entradas nameserver são os dois servidores DNS a usar. Os IPs indicados são do serviço OpenDNS e podem ser usados livremente. Por vezes há uma única entrada nameserver que corresponde ao gateway da rede, é usual em sistemas configurados por DHCP.</div>
<div>
<br /></div>
<div>
Em <span style="font-family: 'Courier New', Courier, monospace;">/etc/hostname</span> colocamos o hostname (basicamente o nome da máquina), assim:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">server001</span></div>
<div>
<br /></div>
<div>
No ficheiro hosts convém colocar uma entrada para o hostname definido antes, qualquer coisa como:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">127.0.0.1 localhost</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">127.0.0.1 server001 server001.lan</span></div>
<br />
Para que tudo funcione é preciso reiniciar os serviços respetivos:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">/etc/init.d/networking restart</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">/etc/init.d/hostname start</span><br />
<h3>
Tempo</h3>
<div>
<br /></div>
<div>
Parecendo que não, é bastante importante que o relógio e o fuso horário do sistema estejam certos, principalmente se vamos usar coisas como servidores de mail, serviços de autenticação e até para os logs do sistema.</div>
<div>
Para configurar o fuso horário:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">dpkg-reconfigure tzdata</span></div>
<div>
<br /></div>
<div>
Para acertar a hora o melhor é deixar que o sistema se atualize automaticamente, é para isso que existe o serviço NTP. Basta fazer:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">apt-get install ntp</span></div>
<div>
<br /></div>
<div>
E esperar um pouco enquanto o sistema sincroniza.</div>
<div>
Podemos ver o estado do NTP com:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">ntpq -p</span></div>
<div>
<br /></div>
<div>
Para ver a data e hora atual fazer:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">date</span></div>
<div>
<br /></div>
<div>
Quando a hora estiver certa convém atualizar o relógio de hardware, para poder manter a hora certa (pelo menos com pequenas variações) mesmo enquanto o sistema está desligado. Para atualizar o relógio de hardware fazemos:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">hwclock --systohc</span></div>
<div>
<br /></div>
<h3>
Locale</h3>
<div>
Chama-se locale ao conjunto de definições que informam o sistema a língua a utilizar e os formatos para apresentação de datas, horas, valores monetários, etc.</div>
<div>
É importante definir corretamente o locale que pretendemos usar, pois se não o fizermos arriscamo-nos a receber mensagens numa língua que não entendemos.</div>
<div>
Para escolher os locales a gerar fazemos:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">dpkg-reconfigure locales</span></div>
<div>
<br /></div>
<div>
Os locales selecionados serão criados. Pode demorar alguns segundos (ou minutos) a gerar cada locale.</div>
<div>
O comando <span style="font-family: 'Courier New', Courier, monospace;">locale</span> mostra as variáveis definidas.</div>
<div>
Se alguma estiver em branco pode ser necessário defini-la manualmente com, por exemplo:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">export LC_TIME=en_US.UTF-8</span></div>
<div>
<br /></div>
<div>
Ainda não consegui descobrir porque é que o dpkg-reconfigure locales nem sempre define todas as variáveis LC_* e LANG*.<br />
<br />
Um script útil em servidores (principalmente os que têm pouco espaço em disco) é o localepurge. É só instalar com:<br />
<br />
apt-get install localepurge<br />
<br />
É preciso selecionar os locales a MANTER, todos os outros serão apagados.<br />
Da próxima vez que se fizer uma instalação com o apt-get, ou se correr manualmente o localepurge, serão apagados os locales que não foram selecionados. Este script não é 'oficial' e pode causar alguns erros (inofensivos). Usar com precaução e RTFM.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-53897516400772410242012-08-23T18:54:00.000+01:002012-08-23T18:54:45.989+01:00rkhunter<i>Um caçador de rootkits para linux e BSD</i><br />
<br />
Para instalar o rkhunter pode fazer-se o download a partir do site oficial e correr o script de instalação, mas como de costume prefiro os repositórios Debian:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">apt-get install rkhunter</span><br />
<br />
Ou para quem prefere otimizar o código (e tiver o apt-build instalado):<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">apt-build install rkhunter</span><br />
<br />
Para correr manualmente, convém fazer uma atualização e só depois fazer a verificação:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">rkhunter --update</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">rkhunter --check</span><br />
<br />
Também podemos correr o comando:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">rkhunter --propupd</span><br />
<br />
Que cria uma base de dados com as propriedades dos ficheiros executáveis presentes no sistema. Das próximas vezes que o rkhunter for executado (SEM a opção --propupd) compara os ficheiros com a informação guardada e avisa se ocorreu alguma alteração. É claro que:<br />
<br />
<ol>
<li>É da responsabilidade do utilizador assegurar que todos os executáveis são legítimos quando se executa o --propupd;</li>
<li>O rkhunter apenas avisa se ocorrer alguma alteração dos ficheiros, não tem forma de saber se essa alteração é fidedigna ou não (por exemplo, um apt-get upgrade altera as propriedades dos ficheiros).</li>
</ol>
<br />
O rkhunter costuma gerar alguns avisos 'falsos positivos', mas devem ser investigados, porque às vezes um verdadeiro positivo está escondido atrás de um falso.<br />
<br />
A instalação do rkhunter cria os scripts <span style="font-family: 'Courier New', Courier, monospace;">/etc/cron.daily/rkhunter</span> e <span style="font-family: 'Courier New', Courier, monospace;">/etc/cron.weekly/rkhunter</span> que se encarregam de correr o rkhunter diariamente e de o atualizar semanalmente.<br />
Os ficheiros <span style="font-family: 'Courier New', Courier, monospace;">/etc/default/rkhunter</span> e <span style="font-family: 'Courier New', Courier, monospace;">/etc/rkhunter.conf</span> têm as configurações a usar, mas as que estão pré-definidas são normalmente suficientes.<br />
<h4>
Referências</h4>
<a href="http://rkhunter.sourceforge.net/">http://rkhunter.sourceforge.net/</a><br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-23115722170073075142012-07-30T14:30:00.000+01:002012-07-30T14:34:28.765+01:00Wake on lan e auto shutdown<h2>
Wake on lan e auto shutdown</h2>
<h3>
Auto shutdown</h3>
O autoshutdown é simples, basta colocar o comando no crontab, mas esqueço-me sempre que os comandos no crontab precisam do caminho completo, porque a PATH é mais limitada.<br />
Basta editar (como root) o crontab com:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">crontab -e</span><br />
<br />
E acrescentar uma linha do tipo:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">00 03 * * * /sbin/shutdown -h +5</span><br />
<br />
Isto vai fazer com que o computador se desligue às 3:05 da manhã, dando um aviso com 5 minutos de antecedência.<br />
<h3>
Wake on LAN</h3>
<div>
O Wake on LAN não é uma opção muito segura. Apesar de haver extensões ao protocolo original que acrescentam autenticação, o WOL original é muito inseguro. Mesmo assim pode dar jeito em casa :)</div>
<div>
O computador deve ser configurado na BIOS para suportar o Wake on LAN. Nem todas as BIOS o suportam, nem todas as interfaces de rede o suportam e a forma como aparece na BIOS pode ser muito variada. Pode aparacer mesmo como "Wake on LAN" ou "Wake on PCI event" ou "Wake on PCI-E event" ou qualquer coisa parecida.</div>
<div>
Mesmo assim pode ainda não ser suficiente para que o WOL funcione. O sistema operatvo também tem de colaborar. No Windows isso faz-se nas propriedades avançadas da interface de rede. No linux faz-se com o ethtool.</div>
<div>
Para verificar se a interface de rede suporta Wak on LAN basta executar (como root):</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">ethtool eth0|grep Wake</span></div>
<div>
<br /></div>
<div>
Se não aparecer nada significa que a interface não suporta WOL.</div>
<div>
Para assegurar que o linux habilita o WOL criei um script em /etc/network/if-ip.d/wolenable, com o seguinte conteúdo:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">#!/bin/sh</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">ethtool -s eth0 wol g</span></div>
<div>
<br /></div>
<div>
Não esquecer de tornar o script executável com:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">chmod +x /etc/network/if-up.d/wolenable</span></div>
<div>
<br /></div>
<div>
Para que o script seja executado é preciso adicionar uma linha à configuração da interface de rede em /etc/network/interfaces:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">auto eth0</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">iface eth0 inet dhcp</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <b>post-up /etc/network/if-up.d/wolenable</b></span></div>
<div>
<br /></div>
<div>
Isto vai executar o script cada vez que a interface eth0 seja iniciada (a linha nova está a negrito).</div>
<div>
Depois é só uma questão de a partir de outra máquina (no mesmo domínio de broadcast) executar:</div>
<div>
<br /></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">wakeonlan 01:23:45:67:89:ab</span></div>
<div>
<br /></div>
<div>
Substituindo o 01:23:45:67:89:ab pelo MAC address da máquina, claro.</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-90934853629249072932012-07-27T18:14:00.000+01:002012-07-29T00:57:49.383+01:00Instalar o Debian por PXE<h2>Instalar o Debian por PXE</h2>
A documentação do Debian, mas por vezes está um pouco desatualizada, como é o caso, por isso aqui fica um guião para instalar o Debian 6 por PXE.<br />
Para instalar por PXE é preciso:<br />
<br /><br />
<ol>
<li>Que o cliente esteja definido para arrancar por rede</li>
<li>Um servidor de PXE com:</li>
<ol>
<li>Servidor DHCP corretamente configurado</li>
<li>Servidor TFTP corretamente configurado</li>
<li>Os ficheiro de arranque do Debian colocados no sítio certo.</li>
</ol>
</ol>
<br /><br />
<h3>1. Definir o arranque por rede</h3>
É preciso aceder à configuração da BIOS e definir o arranque por rede (ou PXE, ou LAN, ou ...). às vezes é mais complicado que que parece. Em algumas motherboards é preciso ativar a placa de rede e ou o arranque por PXE e depois reiniciar e voltar a entrar nas configurações da BIOS e só então aparece o arranque por LAN como opção de arranque. Caso o equipamento não suporte mesmo arranque por LAN, ainda assim é possível criar uma disquete com o <a href="http://rom-o-matic.net/">http://rom-o-matic.net/</a> (o guião fica para outro dia).<br />
<br /><br />
<h3>2. Servidor PXE</h3>
Para fazer o arranque por PXE é necessário configurar os serviços de DHCP e TFTP (há outras opções, usando BOOTP ou RARP, mas DHCP+TFTP é o mais simples e eficaz). Não é necessário que os dois serviços estejam na mesma máquina, nem que sejam linux, mas é mais fácil se estiverem. Aqui vou usar o próprio Debian 6 para fazer um servidor de PXE.<br />
<h4>2.1. Instalar e configurar o DHCP</h4>
O pacote recomendado é o isc-dhcp-server:<br />
apt-get install isc-dhcp-server<br />
A configuração é feita no ficheiro /etc/dhcp/dhcpd.conf.<br />
Coloquei o seguinte conteúdo:<br />
<br />
ddns-update-style none;<br />
<br /><br />
option domain-name "lan";<br />
option domain-name-servers 208.67.222.222, 208.67.220.220;<br />
option subnet-mask 255.255.255.0;<br />
default-lease-time 600;<br />
max-lease-time 7200;<br />
server-name "pxeserver";<br />
allow booting;<br />
allow bootp;<br />
authoritative;<br />
<div>
<br /></div>
<br /><br />
<div>
<div>
subnet 192.168.13.0 netmask 255.255.255.0 {</div>
<div>
range 192.168.13.20 192.168.13.100;</div>
<div>
option routers 192.168.13.254;</div>
<div>
option broadcast-address 192.168.13.255;</div>
<div>
option domain-name-servers 208.67.222.222;</div>
<div>
}</div>
<div>
<br /></div>
<div>
subnet 192.168.1.0 netmask 255.255.255.0 {</div>
<div>
}</div>
<div>
<br /></div>
<div>
group {</div>
<div>
host tftpclient {</div>
<div>
hardware ethernet 08:00:27:FA:3B:A2;</div>
<div>
filename "/pxelinux.0";</div>
<div>
}</div>
<div>
}</div>
</div>
<div>
<br /></div>
<div>
<h4>2.2. Servidor TFTP corretamente configurado</h4>
<div>
O servidor de TFTP é o tftpd-hpa, embora haja outros.</div>
<div>
apt-get install tftpd-hpa</div>
<div>
E em princípio não é preciso mais nada. O TFTP deve ficar instalado e a funcionar. A diretoria que vai usar é a /srv/tftp. Portanto os ficheiros deve ser aí colocados.</div>
<div>
<br /></div>
<h4>2.3. Colocar os ficheiro de arranque do Debian</h4>
</div>
<div>
O CD de arranque do Debian contém um ficheiro netboot/netboot.tar.gz. Apenas é preciso descompactar este ficheiro na diretoria do TFTP (/srv/tftp).<br />
Referências<br />
<a href="http://www.debian.org/releases/stable/i386/ch04s05.html.pt" style="background-color: black;">http://www.debian.org/releases/stable/i386/ch04s05.html.pt</a><br />
<a href="http://wiki.debian.org/DHCP_Server" style="background-color: black;">http://wiki.debian.org/DHCP_Server</a><br />
<a href="http://http.us.debian.org/debian/dists/squeeze/main/installer-i386/current/images/netboot/" style="background-color: black;">http://http.us.debian.org/debian/dists/squeeze/main/installer-i386/current/images/netboot/</a></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-90559403237019066292012-07-27T15:51:00.003+01:002012-07-27T15:55:03.330+01:00Partilhar ligação de internet<h2>
Partilhar a ligação de internet</h2>
Colocar uma máquina linux a partilhar a ligação de internet (desde que tenha pelo menos duas placas de rede, claro), é relativamente simples.<br />
Aqui ficam as instruções para referência futura. Assume-se que wlan0 liga à internet e que eth0 liga à intranet.<br />
<br />
Ligar o sistema de NAT (masquerade) na interface de ligação ao exterior:<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE</span><br />
<br />
Aceitar pedido de encaminhamento proveniente da interface "interior":<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">iptables -A FORWARD -i eth0 -j ACCEPT</span><br />
<br />
Habilitar o forwarding para IPv4:<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">sysctl -w net.ipv4.ip_forward=1</span><br />
<br />
Atribuir um endereço à interface externa. Este passo não é necessário de a interface já tiver um endereço.<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">ifconfig eth0 10.0.0.254/24</span><br />
<br />
Reiniciar o serviço de rede:<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">/etc/init.d/networking restart</span><br />
<div>
<br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-81136704216171134942012-07-23T20:34:00.001+01:002012-07-24T12:44:40.442+01:00Desligar (spindown) os discos automaticamente<h2>
Desligar (spindown) os discos automaticamente</h2>
Esta dica funciona melhor em sistemas com mais de um disco rígido (por exemplo, um homeserver, como é o meu caso) ou num portátil.<br />
A ideia é arranjar maneira de desligar o motor dos discos rígidos quando estes não estão a ser usados. Poupa-se energia, pois o disco consome menos com o motor desligado obviamente e pode prolongar-se o tempo de vida do disco. Para prolongar o tempo de vida do disco é preciso definir um tempo espera generoso antes de fazer o spindown, pois demasiados ciclos de desligar e reiniciar o motor vão ter o efeito contrário, isto é, diminuir o tempo de vida do disco.<br />
Assim, vou usar 30 minutos como tempo recomendado.<br />
Há um projeto aqui <a href="http://code.google.com/p/spindown/">http://code.google.com/p/spindown/</a> de um daemon que faz exatamente o que se pretende, mas eu quero uma solução mais "caseira", que assente mais em bash e que não seja preciso andar a compilar código.<br />
Vou usar Debian para este projeto, pois ando desanimado com o Ubuntu. Está cada vez mais parecido ao Windows.<br />
É preciso executar todos os comandos como root.<br />
<h3>
1. Instalar o sg3-utils</h3>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">apt-get install sg3-utils</span><br />
O pacote sg3-utils tem o comando sg_start que podemos usar para parar o motor do disco.<br />
Aparentemente também se pode fazer com o sdparm e com o hdparm, mas ainda não experimentei.<br />
<h3>
2. Criar um script</h3>
Criei um script em /root/bin/spindown.sh com o seguinte conteúdo:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"># !/bin/sh</span><br />
<span style="background-color: white;"><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">if [ "$(id -u)" != "0" ]; then</span></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> echo "This script must be run as root" 1>&2</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> exit 1</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">fi</span><br />
<span style="background-color: white;"><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">if [ -z $1 ]; then</span></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> echo Usage: $0 sdX</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> exit 1</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">fi</span><br />
<span style="background-color: white;"><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"># isto estava a causar alguns problemas, por enquanto fica desligado</span></span><br />
<span style="background-color: white;"><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">#if ! [ -e /dev/$1 ]; then</span></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"># echo /dev/$1 not found</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"># exit 1</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">#fi</span><br />
<span style="background-color: white;"><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">NEWFILE=/tmp/NewState.$1</span></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">OLDFILE=/tmp/OldState.$1</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">date +"%F %T"</span><br />
<span style="background-color: white;"><span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"># Get new state from diskstats</span></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">NEWstate=$(cat /proc/diskstats | grep $1)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">echo $NEWstate > $NEWFILE</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">if [ -z $(diff OLDstate.txt NEWstate.txt) ]; then</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> echo Stopping $1...</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> # sdparm --flexible --command=stop /dev/$1 &>/dev/null</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> sg_start --stop /dev/$1</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">else</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> echo $1 active</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">fi</span><br />
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"># Write current state to file</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">echo $NEWstate > $OLDFILE</span><br />
<div>
<br /></div>
<div>
Não esquecer de ligar o bit executável no ficheiro:</div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">chmod +x spindown.sh</span></div>
<h3>
3. Adicionar ao crontab</h3>
<div>
Adicionar ao crontab a linha:</div>
<div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">*/30 * * * * /root/bin/spindown.sh sdc</span></div>
<div>
Deve ser adicionada uma linha por cada disco que se pretende controlar, mudando o 'sdc' de acordo com o disco, claro.</div>
<div>
<br /></div>
<div>
Como o script faz algumas verificações antes de ser executado, deve ser seguro de executar na linha de comandos para testes (sem garantias...),</div>
<div>
Não é uma solução muito elegante, mas é relativamente simples.</div>
<div>
<br /></div>
<h3>
Referências</h3>
<div>
<a href="http://code.google.com/p/spindown/">http://code.google.com/p/spindown/</a></div>
<div>
<a href="http://hartvig.de/2009/howto-automatically-spin-down-external-usb-hard-drives-in-ubuntu/">http://hartvig.de/2009/howto-automatically-spin-down-external-usb-hard-drives-in-ubuntu/</a></div>
<div>
<a href="http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html">http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html</a></div>
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-3813820309595564152012-04-25T17:00:00.000+01:002012-05-27T22:59:02.210+01:00<h2>
Programar para Android - 08</h2>
<br />
<i>Botões que lançam outras atividades</i><br />
<br />
Começamos por criar um novo projeto <b>Try06</b> e retirar a string hello world, para ficar com um projeto vazio, mas já com a atividade já criada.<br />
<br />
Desta vez vamos fazer algo um pouco mais longo e vamos ter o primeiro contacto com intents, permissões, obter dados do GPS e do Wifi e editar o <b>AndroidManifest.xml</b>.<br />
<br />
Vamos criar uma atividade com 6 botões que lançam atividades ou realizam outras ações, algumas mais simples outras mais complexas.<br />
<br />
Começamos por criar seis strings no <b>strings.xml</b> com nomes <b>app1</b> a <b>app6</b> e com o conteúdo: <b>Google</b>, <b>Calculadora</b>, <b>Notificação</b>, <b>Vibrar</b>, <b>GPS</b>, <b>Wifi</b>. Os botões irão:<br />
<br />
<ul>
<li>lançar o endereço http://www.google.pt;</li>
<li>lançar a calculadora;</li>
<li>mostrar uma notificação no écrã;</li>
<li>vibrar o telemóvel;</li>
<li>obter informação sobre o GPS;</li>
<li>obter informação sobre a ligação Wifi.</li>
</ul>
<br />
No <b>main.xml</b> vamos criar o layout. Adicionamos três LinearLayout horizontais dentro do LinearLayout vertical. Dentro de cada LinearLayout horizontal criamos dois botões, ficando assim com seis botões. Usando o botão "Distribute Weights Evenly", podemos fazer que os botões ocupem todo o écrã de forma equilibrada. O aspeto fica assim:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr78qg9c6pUowTjC-2DeNV13ZQpC8n0UoCkqLfFafaxqS2Qn1SWBwkO3IzeTNDh1HYG27V3ssh2iK5ZCtIxaIrafp7ThZaVtw3qj92hCe7UXLVj910gkpinzt633ilHREjHU9sniKLqCH9/s1600/try06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr78qg9c6pUowTjC-2DeNV13ZQpC8n0UoCkqLfFafaxqS2Qn1SWBwkO3IzeTNDh1HYG27V3ssh2iK5ZCtIxaIrafp7ThZaVtw3qj92hCe7UXLVj910gkpinzt633ilHREjHU9sniKLqCH9/s320/try06.png" width="191" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
O xml do layout fica assim:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><?xml version="1.0" encoding="utf-8"?></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:orientation="vertical" ></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> <LinearLayout</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="0dp"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_weight="1" ></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> <Button</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:id="@+id/button1"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="0dp"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_weight="1"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:onClick="runApp1"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:text="@string/app1" /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> <Button</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:id="@+id/button2"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="0dp"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_weight="1"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:onClick="runApp2"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:text="@string/app2" /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> </LinearLayout></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> <LinearLayout</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="0dp"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_weight="1" ></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> <Button</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:id="@+id/button3"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="0dp"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_weight="1"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:onClick="runApp3"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:text="@string/app3" /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> <Button</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:id="@+id/button4"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="0dp"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_weight="1"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:onClick="runApp4"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:text="@string/app4" /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> </LinearLayout></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> <LinearLayout</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="0dp"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_weight="1" ></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> <Button</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:id="@+id/button5"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="0dp"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_weight="1"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:onClick="runApp5"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:text="@string/app5" /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> <Button</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:id="@+id/button6"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="0dp"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="fill_parent"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_weight="1"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:onClick="runApp6"</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> android:text="@string/app6" /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"> </LinearLayout></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: 'Courier New', Courier, monospace;"></LinearLayout></span></div>
<div class="separator" style="clear: both;">
<br /></div>
<br />
Já não vamos precisar de mexer mais no <b>strings.xml</b> nem no <b>main.xml</b>.<br />
Vamos agora ver o <b>AndroidManifest.xml</b>. Tal como o <b>strings.xml</b> e o <b>main.xml</b>, o Eclipse mostra uma interface gráfica, mas vamos editar diretamente o XML.<br />
Este ficheiro contém informação sobre a aplicação que é usada, por exemplo, no Android Market (agora Play) para listar e identificar as aplicações.<br />
Muitas das tags são óbvias. Desta vez vamos apenas acrescentar algumas linhas de texto, entre o <span style="font-family: 'Courier New', Courier, monospace;"><uses-sdk ...></span> e o <span style="font-family: 'Courier New', Courier, monospace;"><application ...></span>.<br />
As linhas a acrescentar são estas:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> <uses-permission android:name="android.permission.VIBRATE"/></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> </span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <uses-feature android:name="android.hardware.wifi" /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <uses-feature android:name="android.hardware.location" /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <uses-feature android:name="android.hardware.location.network" /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <uses-feature android:name="android.hardware.location.gps" /></span><br />
<div>
<br /></div>
<br />
Os <span style="font-family: 'Courier New', Courier, monospace;">uses-permission</span> listam as permissões que a aplicação precisa de ter para poder funcionar, neste caso precisa de poder ligar a vibração (<span style="font-family: 'Courier New', Courier, monospace;">VIBRATE</span>), aceder aos dados de localização por GPS e pela rede (<span style="font-family: 'Courier New', Courier, monospace;">ACCESS_FINE_LOCATION</span>, <span style="font-family: 'Courier New', Courier, monospace;">ACCESS_COARSE_LOCATION</span>) e aceder a informação da ligação sem fios (<span style="font-family: 'Courier New', Courier, monospace;">ACCESS_WIFI_STATE</span>).<br />
Esta informação também é mostrada ao utilizador no momento em que instala a aplicação e o utilizador tem de dar estas permissões à aplicação.<br />
As linhas de <span style="font-family: 'Courier New', Courier, monospace;">uses-feature</span> informam que a aplicação só irá funcionar em dispositivos que tenham o hardware indicado (neste caso wifi e GPS). Esta informação é usada no market para filtrar as aplicações que não são compatíveis com o dispositivo do utilizador.<br />
<br />
Finalmente vamos ao código e graças à separação que o Android faz ao colocar o layout e permissões em ficheiros XML, só temos de nos preocupar mesmo com o código.<br />
O método <b>onCreate()</b> que já existe não precisa ser mexido, apenas precisamos criar seis métodos novos, um para cada botão, com os nomes <b>runApp1()</b> a <b>runApp6()</b>. Estes foram os nomes definidos no <b>main.xml</b>.<br />
<br />
O primeiro botão lança um browser para aceder ao endereço http://www.google.pt. Isso consegue-se com este código:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">public void runApp1(View v) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Intent i = new Intent(Intent.ACTION_VIEW, </span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span> Uri.parse("http://www.google.pt/"));</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>startActivity(i);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
Um intent é um objeto que, basicamente, contém uma mensagem que é passada ao sistema. Neste caso o intent é criado com a mensagem (ação) <span style="font-family: 'Courier New', Courier, monospace;">ACTION_VIEW</span> e com um parâmetro "http://www.google.pt". Um intent pode ter várias formas, mas este é uma das mais usadas. Contém dois parâmetros, o primeiro é a ação a executar (pode ser VIEW, PICK, EDIT, DELETE, etc) e o segundo parâmetro é um argumento para a ação. Neste caso estamos a dizer ao sistema que queremos ver (VIEW) o URL indicado. O sistema analisa o intent e escolhe a aplicação certa para executar a ação pedida. Pode haver mais que uma aplicação que possa executar essa ação, então o sistema pergunta ao utilizador qual a aplicação que pretende usar. Neste caso se houvesse dois browsers presentes no dispositivo o sistema iria perguntar que browser se pretendia usar.<br />
<br />
O segundo botão lança a calculadora, usando também um intent.<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> public void runApp2(View v) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>Intent i = new Intent();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>i.setClassName("com.android.calculator2", "com.android.calculator2.Calculator");</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>startActivity(i);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<br />
Este intent é diferente. Começamos por criar um intent vazio e adicionamos um nome de classe. Este nome de classe é definido a partir do packagename da atividade. Por isso é importante que cada atividade tenha um nome único, porque esse nome vai ser utilizado para lançar a atividade e tem portanto de ser único.<br />
<br />
O terceiro botão apenas mostra uma mensagem de notificação, que no Android é chamado um Toast.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">public void runApp3(View v) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>String msg = "Hello World, again!";</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
O quarto botão liga a vibração durante 1 segundo (1000 milisegundos). Usa o serviço de sistema <span style="font-family: 'Courier New', Courier, monospace;">VIBRATOR_SERVICE</span>.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">public void runApp4(View v) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>Vibrator vib;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> vib =</span><span style="font-family: 'Courier New', Courier, monospace;"> (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> vib.vibrate(1000);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
O quinto botão obtém informação de localização do GPS ou da rede. Primeiro tenta obter a informação do GPS (<span style="font-family: 'Courier New', Courier, monospace;">GPS_PROVIDER</span>). Se a informção não estiver disponível (GPS desligado ou sem sinal) pede informação à rede (<span style="font-family: 'Courier New', Courier, monospace;">NETWORK_PROVIDER</span>). A informação obtida é mostrada num Toast.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">public void runApp5(View v) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> LocationManager locator = (LocationManager) getSystemService(Context.LOCATION_SERVICE);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> Location l = locator.getLastKnownLocation(LocationManager.GPS_PROVIDER);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> if (l == null) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> // Fall back to coarse location.</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> l = locator.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> double alt = l.getAltitude();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> double lat = l.getLatitude();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> double lon = l.getLongitude();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> long time = l.getTime();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> float acc = l.getAccuracy();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> float speed = l.getSpeed();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> String prov = l.getProvider();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> String msg =</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>"Lat: " + lat + "\n" +</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>"Long: " + lon + "\n" + <span class="Apple-tab-span" style="white-space: pre;"> </span></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>"Alt: " + alt + "\n" + <span class="Apple-tab-span" style="white-space: pre;"> </span></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>"Time: " + time + "\n" + <span class="Apple-tab-span" style="white-space: pre;"> </span></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>"Accuracy: " + acc + "\n" + <span class="Apple-tab-span" style="white-space: pre;"> </span></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>"Speed: " + speed + "\n" +</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>"Provider: " + prov + "\n";</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>Toast.makeText(this, msg, Toast.LENGTH_LONG).show();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
O sexto e último botão obtém e mostra a informação sobre a ligação wifi atual. Usa o serviço de wifi do sistema (<span style="font-family: 'Courier New', Courier, monospace;">WIFI_SERVICE</span>). A informação obtida também é mostrada num Toast.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">public void runApp6(View v) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>String msg;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> if (wifi.isWifiEnabled()) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> msg = "Wifi ligado\n";</span><br />
<span class="Apple-tab-span" style="font-family: 'Courier New', Courier, monospace; white-space: pre;"> </span><span style="font-family: 'Courier New', Courier, monospace;"> WifiInfo winfo = wifi.getConnectionInfo();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> </span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> int ipadd = winfo.getIpAddress();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> String ip = String.format("%d.%d.%d.%d",</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> <span class="Apple-tab-span" style="white-space: pre;"> </span>ipadd & 0xff,</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> <span class="Apple-tab-span" style="white-space: pre;"> </span>ipadd >> 8 & 0xff,</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> <span class="Apple-tab-span" style="white-space: pre;"> </span>ipadd >> 16 & 0xff,</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> <span class="Apple-tab-span" style="white-space: pre;"> </span>ipadd >> 24 & 0xff);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> msg +=</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> "BSSID: " + winfo.getBSSID() + "\n" +</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> "IP: " + ip + "\n" +</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> "Speed: " + winfo.getLinkSpeed() + "\n" +</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> "MAC: " + winfo.getMacAddress() + "\n" +</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> "RSSI: " + winfo.getRssi() + "\n" +</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> "SSID: " + winfo.getSSID();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>} else</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>msg = "Wifi desligado";</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span> Toast.makeText(this, msg, Toast.LENGTH_LONG).show();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
<br />
O projeto necessita de uma lista relativamente longa de imports, que devem ser gerados pelo Eclipse, mas para referência aqui ficam:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.app.Activity;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.content.Context;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.content.Intent;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.location.Location;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.location.LocationManager;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.net.Uri;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.net.wifi.WifiInfo;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.net.wifi.WifiManager;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.os.Bundle;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.os.Vibrator;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.view.View;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.widget.Toast;</span><br />
<br />
<h4>
Referências:</h4>
<a href="http://www.krvarma.com/2010/07/getting-ip-address-of-the-device-in-android/">http://www.krvarma.com/2010/07/getting-ip-address-of-the-device-in-android/</a><br />
<a href="http://www.damonkohler.com/2009/02/android-recipes.html">http://www.damonkohler.com/2009/02/android-recipes.html</a><br />
além do obrigatório: <a href="http://developer.android.com/reference/packages.html">http://developer.android.com/reference/packages.html</a><br />
<br />Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8205744447244084096.post-82441807827644428402012-04-23T23:19:00.001+01:002012-04-25T17:02:14.603+01:00<h2>
Programar para Android - Índice</h2>
<br />
<br />
<ul>
<li><a href="http://eunaoqueroumblogue.blogspot.pt/2012/04/programar-para-android-melhor-forma-de.html">00 - Instalar o IDE</a></li>
<li><a href="http://eunaoqueroumblogue.blogspot.pt/2012/04/programar-para-android-01-o-classico.html">01 - Hello World!</a> </li>
<li><a href="http://eunaoqueroumblogue.blogspot.pt/2012/04/programar-para-android-02-vamos-fazer.html">02 - Try00 - Programa que não faz absolutamente nada</a></li>
<li><a href="http://eunaoqueroumblogue.blogspot.pt/2012/04/programar-para-android-03-vamos-fazer.html">03 - Try01 - Criar um layout com o editor gráfico</a></li>
<li><a href="http://eunaoqueroumblogue.blogspot.pt/2012/04/programar-para-android-04-vamos-criar.html">04 - Try02 - Criar um layout com XML</a></li>
<li><a href="http://eunaoqueroumblogue.blogspot.pt/2012/04/programar-para-android-05-vamos-agora.html">05 - Try03 - Criar um layout usando Java</a></li>
<li><a href="http://eunaoqueroumblogue.blogspot.pt/2012/04/programar-para-android-06-try04-um.html">06 - Try04 - Um botão que reage à pressão</a></li>
<li><a href="http://eunaoqueroumblogue.blogspot.pt/2012/04/programar-para-android-07-um-botao-que.html">07 - Try05 - Botão que muda um texto</a></li>
<li><a href="http://eunaoqueroumblogue.blogspot.pt/2012/04/programar-para-android-08-botoes-que.html">08 - Try06 - Botões que lançam outras atividades (finalmente algo que se veja)</a></li>
<li>09 - Try07 - Botões que passam informações a subatividades (converter C em F)</li>
<li>10 - Try08 - ...</li>
</ul>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-2232798716375816382012-04-23T23:03:00.005+01:002012-04-23T23:10:59.309+01:00<h2>
Programar para Android - 07</h2>
<br />
<i>Um botão que muda um texto</i><br />
<br />
Criamos um novo projeto <b>Try05</b> da maneira habitual e apagamos a string do hello world, para começarmos com uma Activity já pronta, mas vazia.<br />
Criamos uma string chamada <b>tvText</b> e com o conteúdo <b>Número de clicks:</b> e outra string com o nome <b>btText</b> e conteúdo <b>Clica-me</b>.<br />
No layout (<b>main.xml</b>) adicionamos um botão e um TextView. Ao botão associamos o texto <b>btText</b> e à TextView associamos o texto <b>tvText</b>.<br />
A ideia é que ao clicar no botão o texto vá indicando quantos clicks foram contados.<br />
<br />
Vamos a <b>Try05Activity</b> e adicionamos a seguinte variável à atividade:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">int numClicks = 0;</span><br />
<br />
Esta variável vai contar os clicks e obviamente começa com 0 clicks.<br />
De seguida criamos o seguinte método:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> private void updateText() {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>String s = getString(R.string.tvText) + " " + numClicks;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>TextView tv1 = (TextView) findViewById(R.id.textView1);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>tv1.setText(s); <span class="Apple-tab-span" style="white-space: pre;"> </span></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<br />
Este método atualiza o texto que pareca na TextView. Começa por definir uma string construída a partir do conteúdo da string <b>tvText</b> com um espaço e mais número de clicks registados. Para podermos aceder ao texto na TextView <b>textView1</b> (este é o nome dado à TextView criada no <b>main.xml</b>) precisamos de um objeto a que chamamos <b>tv1</b> e fazemos a ligação ao texto já existente usando o método <b>findViewById()</b>. A última linha atualiza o texto.<br />
<br />
Precisamos agora de um método que aumente o número de clicks cada vez que se clica no botão. Este método é muito simples de implementar. Vamos chamar-lhe <b>processClick()</b>.<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> public void processClick(View v) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>numClicks++;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>updateText();</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<br />
Vamos fazer uma alteração ao método <b>onCreate()</b>:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> public void onCreate(Bundle savedInstanceState) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> super.onCreate(savedInstanceState);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> setContentView(R.layout.main);</span><br />
<b><span style="font-family: 'Courier New', Courier, monospace;"> updateText();</span></b><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<br />
Apenas foi adicionada a linha a negrito. Esta linha apenas corrige uma questão estética, faz aparecer o 0 (zero) quando o botão ainda não foi clicado nenhuma vez.<br />
<br />
Se executarmos agora o código, não é apresentada nenhum erro, mas o programa não faz nada. Falta indicar que vai ser o método <b>processClick()</b> a processar o clicks no botão. Antes fizemos isso com o método <b>setOnClickListener()</b> do botão e tivemos de dizer que a atividade implementava a interface <b>OnClickListener</b>.<br />
Desta vez vamos apenas ao ficheiro <b>main.xml</b> (diretamente ao XML) e acrescentamos esta linha no botão:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> android:onClick="processClick"</span><br />
<br />
Esta linha indica que o método <b>processClick()</b> vai ser o responsável pelo processamento dos clicks neste botão. É claro que o nome do método pode ser outro qualquer, mas o método tem de ser <b>public</b>, não retornar valores (ou seja, ser <b>void</b>) e aceitar um parâmetro do tipo View.<br />
<br />
Podemos assim no Android usar o XML para definir o layout da atividade e também para definir o comportamento de alguns componentes ao reagir a determinados eventos (como neste caso o click num botão). Assim na parte de código só fazemos mesmo código. Não é preciso fazer meio metro de código só para criar textos e botões e definir o seu comportamento. O Android permite separar o layout e comportamento para o XML e liberta o ficheiro de código para conter código "útil".<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-587120524215461282012-04-22T23:16:00.000+01:002012-04-22T23:16:17.383+01:00Programar para Android - 06<br />
<br />
<i>Try04 - Um botão com ação.</i><br />
<br />
Vamos começar por criar um novo projeto <b>Try04</b>, em que retiramos a mensagem de "Hello World".<br />
Neste projeto vamos criar um botão com o id <b>btButton</b> que ocupe toda a área disponível do ecrã, ou seja, com <b>FILL_PARENT</b> na altura e na largura.<br />
Tal como antes, temos o layout concluído, mas o programa não faz nada.<br />
A ideia é que o botão apresente uma mensagem, quando for clicado mude para uma segunda mensagem e ao ser clicado de novo volte à primeira mensagem.<br />
Vamos então criar duas strings em <b>strings.xml</b>, uma com o id <b>btText</b> e valor <b>Clica-me</b> e outra com id <b>btTextClicked</b> e valor <b>Fui clicado</b>.<br />
Agora vamos ao código.<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">package pt.omeusite.try04;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.app.Activity;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.os.Bundle;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.view.View;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.view.View.OnClickListener;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.widget.Button;</span><br />
<br />
Os imports são feitos automaticamente pelo Eclipse, com o <b>Ctrl+Shift+O</b>.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">public class Try04Activity extends Activity implements OnClickListener {</span><br />
<br />
A atividade vai implementar a interface OnClickListener, para poder processar os clicks no botão. É possível definir uma nova classe ou uma subclasse para processar os clicks, mas é mais simples fazer que a atividade implemente o interface, pois apenas implica que tenha um método onClick().<br />
Vamos precisar de um objeto do tipo <b>Button</b> e de uma variável inteira, para guardar o estado do botão.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>Button btButton;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>int status = 0;</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="font-family: 'Courier New', Courier, monospace;"> </span></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/** Called when the activity is first created. */</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> @Override</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> public void onCreate(Bundle savedInstanceState) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> super.onCreate(savedInstanceState);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> setContentView(R.layout.main);</span><br />
<br />
Começamos o código "a sério" por definir o objeto <b>btButton</b>. O objeto já foi definido no layout em <b>main.xml</b>, por isso agora apenas dizemos para ir buscar o objeto com o id <b>btButton</b> aos recursos.<br />
De seguida definimos a própria atividade (<b>this</b>) como listener dos clicks.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> btButton = (Button) findViewById(R.id.btButton);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> btButton.setOnClickListener(this);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<br />
O método que processa os clicks é este. Apenas muda o estado e define o texto do botão de acordo com esse estado.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> public void onClick(View v) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>status = 1 - status;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>if (status==1)</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>btButton.setText(R.string.btTextClicked);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>else</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>btButton.setText(R.string.btText);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
E finalmente um programa que reage a alguma coisa.<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-17734492182919841042012-04-22T18:25:00.005+01:002012-04-22T18:33:37.180+01:00<h2>
Programar para Android - 05</h2>
<br />
<i>Try03 - Layout com código Java.</i><br />
<br />
Vamos agora tentar o mesmo layout, mas usando apenas Java.<br />
Vamos criar o projeto <b>Try03</b>, e abrimos o <b>Try03Activity.java</b>, <b>main.xml</b> e <b>strings.xml</b>.<br />
Primeiro vamos analisar o conteúdo.<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">package pt.omeusite.try03;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.app.Activity;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">import android.os.Bundle;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">public class Try03Activity extends Activity {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> /** Called when the activity is first created. */</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> @Override</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> public void onCreate(Bundle savedInstanceState) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> super.onCreate(savedInstanceState);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> setContentView(R.layout.main);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
A identificação do package e os imports são o normal do Java.<br />
Apenas está definida a classe <b>Try03Activity</b> que <b>extends</b> a classe <b>Activity</b>. Dentro da nossa classe apenas temos um método <b>onCreate()</b>, que faz o <b>override</b> do <b>onCreate()</b> da classe <b>Activity</b>. O método <b>onCreate()</b> é chamado cada vez que uma atividade é criada, por isso é o local ideal para colocar o código que constrói a atividade (é como se fosse o construtor do objeto). A primeira ação é chamar o <b>onCreate()</b> da classe pai, passando-lhe o <b>Bundle savedInstanceState</b>. Deixemos a explicação do que é este <b>Bundle</b> para mais tarde. Fiquemos só com a noção que precisa estar lá.<br />
<br />
A única outra instrução é um enigmático <b>setContentView(R.layout.main)</b>, O <b>setContentView()</b> define qual é a view desta atividade (uma View, recordemos é um widget ou um layout), ou seja define o que vai aparecer no écrã. Neste caso passamos-lhe o argumento <b>R.layout.main</b>. O objeto <b>R</b> refere-se à diretoria <b>res</b>, o <b>layout.main</b> é uma referência ao ficheiro <b>main.xml</b> na diretoria layout. Ou seja, vai ler o nosso velho amigo <b>main.xml</b>! Por isso é que quando editamos o <b>main.xml</b> as alterações aparecem no écrã!<br />
Percebido isto, vamos começar a apagar coisas:<br />
<br />
<ul>
<li>no <b>Try03Activity.java</b> apagamos exatamente a linha <b>setContentView(R.layout.main)</b>;</li>
<li>no <b>main.xml</b> apagamos a <b>TextView</b>;</li>
<li>no <b>strings.xml</b> apagamos a string <b>hello</b>.</li>
</ul>
<div>
Ficamos com uma aplicação que nada faz (semelhante ao que fizemos em <b>Try00</b>, mas agora há mais algum código no ficheiro .java).</div>
<div>
A partir de agora não mexemos mais nos ficheiros XML.</div>
<div>
O ficheiro .java fica assim:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">package pt.omeusite.try03;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">import android.app.Activity;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">import android.os.Bundle;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">import android.widget.Button;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">import android.widget.EditText;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">import android.widget.LinearLayout;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">import android.widget.LinearLayout.LayoutParams;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">import android.widget.TextView;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">public class Try03Activity extends Activity {</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // estas views vão ser necessárias</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> LinearLayout vLayout, hLayout;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> TextView tvTitle, tvName;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> EditText etEdit;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> Button btOk;</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/** Called when the activity is first created. */</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> @Override</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> public void onCreate(Bundle savedInstanceState) {</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> super.onCreate(savedInstanceState);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> </span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> /* estes layouts cumprem a mesma função do:</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> * android:layout_width="..."</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> * android:layout_height="..."</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> */</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> LinearLayout.LayoutParams lpFF = new LinearLayout.LayoutParams(</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> LayoutParams.FILL_PARENT,</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> LayoutParams.FILL_PARENT);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> LinearLayout.LayoutParams lpFW = new LinearLayout.LayoutParams(</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> LinearLayout.LayoutParams.FILL_PARENT,</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> LinearLayout.LayoutParams.WRAP_CONTENT);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // esta layout acrescenta o valor 1.0f, que é o peso relativo da view</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> LinearLayout.LayoutParams lpWW = new LinearLayout.LayoutParams(</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>LinearLayout.LayoutParams.WRAP_CONTENT,</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> </span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // criamos o layout vertical que será o topo da view</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> vLayout = new LinearLayout(this);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // definimos orientação como vertical</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> vLayout.setOrientation(LinearLayout.VERTICAL);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // definimos os parametros de layout como FILL_PARENT, FILL_PARENT</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> vLayout.setLayoutParams(lpFF);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // criamos uma nova TextView</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> tvTitle = new TextView(this);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // definimos o texto</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> tvTitle.setText("Try03Activity");</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // definimos os parâmetros de layout</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> tvTitle.setLayoutParams(lpFW);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // adicionamos esta View ao layout vertical</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> vLayout.addView(tvTitle);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // criamos um novo layout</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> hLayout = new LinearLayout(this);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // definimos layout horizontal</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> hLayout.setOrientation(LinearLayout.HORIZONTAL);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // definimos os parâmetros</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> hLayout.setLayoutParams(lpFW);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> </span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>// criamos uma nova TextView</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>tvName = new TextView(this);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>// definimos o texto</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>tvName.setText("Nome");</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>// definimos os parâmetros</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>tvName.setLayoutParams(lpWW);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>// adicionamos a View ao layout horizontal</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>hLayout.addView(tvName);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>// criamos uma nos caixa de texto</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>etEdit = new EditText(this);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>// definimos tamanho como 10 ems</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>etEdit.setEms(10);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>// definimos layout</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>etEdit.setLayoutParams(lpWW);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>// adicionamos ao layout horizontal</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>hLayout.addView(etEdit);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // adicionamos o layout horizontal ao vertical</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> vLayout.addView(hLayout);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> </span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // criamos um botão</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> btOk = new Button(this);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // definimos o texto</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> btOk.setText("Ok");</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // definimos os parâmetros</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> btOk.setLayoutParams(lpFW);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // adicionamos o botão ao layout vertical</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> vLayout.addView(btOk);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // definimos a vista ativa como sendo o layout vertical que acabámos de definir</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> // e o layout é mostrado no écrã</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> setContentView(vLayout);</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> }</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">}</span></div>
</div>
<div>
<br /></div>
<div>
Acho que não há melhor motivação para usar o editor gráfico ou o XML.</div>
<div>
O programa continua a não fazer absolutamente nada, mas foi preciso escrever uma quantidade considerável de código para isso. Mesmo com as ajudas do Eclipse (<b>Ctrl+Shift+O</b> para adicionar os imports automaticamente e <b>Ctrl+Space</b> para ajudar na conclusão das palavras) não é um exercício trivial.</div>
<div>
Por isso normalmente as interfaces gráficas não são criadas usando código. Há alturas em que é inevitável, como por exemplo preencher uma lista pendente (Spinner, na nomenclatura Android) com dados retirados de uma base de dados.</div>
<div>
<br /></div>
<div>
Apesar de funcionar, o programa tem um erro conceptual: as strings estão <i>hardcoded</i> na atividade, o que já tínhamos dito que não se deve fazer. Para usar os id das strings é preciso primeiro criá-las no ficheiro <b>strings.xml</b> (ou noutro ficheiro XML, não é obrigatório ser no <b>strings.xml</b>).</div>
<div>
Afinal sempre temos de editar o XML. Criamos então as seguintes strings no <b>strings.xml</b>, usando o editor ou diretamente no XML:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><string name="tvTitle">Try02Activity</string></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><string name="tvName">Nome</string></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><string name="btOk">Ok</string></span></div>
</div>
<div>
<br /></div>
<div>
Notar que para identificador de cada string foi usado o mesmo nome que para o objeto no código Java. Isto NÃO é obrigatório, mas ajuda a manter a sanidade do programador.</div>
<div>
<br /></div>
<div>
Agora precisamos alterar as linhas do código que se referem às strings:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">(...)</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">tvTitle.setText(getString(R.String.tvTitle));</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">(...)</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">tvName.setText(</span><span style="font-family: 'Courier New', Courier, monospace;">getString(</span><span style="font-family: 'Courier New', Courier, monospace;">R.string.tvName));</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">(...)</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">btOk.setText(</span><span style="font-family: 'Courier New', Courier, monospace;">getString(</span><span style="font-family: 'Courier New', Courier, monospace;">R.string.btOk));</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;">(...)</span></div>
</div>
<div>
<br /></div>
<div>
E pronto, um programa que não faz nada, mas arrumadinho.</div>
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8205744447244084096.post-34742745459074595202012-04-22T16:01:00.000+01:002012-04-22T18:33:09.668+01:00<h2>
Programar para Android - 04</h2>
<br />
<i>Try02 - Layout com XML.</i><br />
<br />
Vamos criar um layout exatamente idêntico ao criado no Try01, mas usando apenas os ficheiros XML diretamente.<br />
<br />
Começamos por criar um projeto Android chamado Try02.<br />
Por uma questão de criação de bons hábitos vamos abrir os ficheiros <b>Try02Activity.java</b>, <b>res/layout/main.xml</b> e <b>res/values/strings.xml</b>, mas na verdade nem sequer vamos mexer no .java.<br />
Mudamos o <b>main.xml</b> e <b>strings.xml</b> para a vista de XML.<br />
<br />
Ao contrário do modo de edição gráfico, em que vamos fazendo as coisas à medida que nos lembramos, do tipo "ah, preciso aqui duma string, click direito e adiciono-a", o modo XML exige que se pense um pouco antes de começar a editar.<br />
Neste caso já sabemos bem o que pretendemos, por isso podemos ir diretamente ao ficheiro strings.xml e adicionar as strings que precisamos, que são:<br />
<br />
<ul>
<li>uma string tvName com o valor "Nome", para aparecer como legenda de uma caixa de texto;</li>
<li>uma string btOk com o valor "Ok", para aparecer no botão.</li>
</ul>
<div>
A estrutura do strings.xml é bastante simples de perceber e para adicionar as duas strings basta acrescentar duas linhas dentro do resources ... /resources. Fica assim (as linhas adicionadas estão a negrito):</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><?xml version="1.0" encoding="utf-8"?></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><resources></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <string name="hello"><b>Try02Activity</b></string></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <string name="app_name">Try02</string></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> <string name="tvName">Nome</string></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> <string name="btOk">Ok</string></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"></resources></span></div>
</div>
<div>
<br /></div>
<div>
Também mudamo a mensagem de "Hello World" para aparecer apenas o nome da atividade.</div>
<div>
<br /></div>
<div>
O main.xml já dá mais um pouco de trabalho, mas nada de muito difícil.</div>
<div>
Temos de pensar primeiro na estrutura que queremos criar. No topo tem de existir sempre um layout, que no nosso caso é um LinearLayout vertical. Dentro dele vamos colocando os outros elementos e outros layouts. Assim:</div>
<div>
<ul>
<li>LinearLayout vertical</li>
<ul>
<li>TextView "Try02Activity"</li>
<li>LinearLayout horizontal</li>
<ul>
<li>TextView "Nome"</li>
<li>TextField editText1</li>
</ul>
<li>Botão "Ok"</li>
</ul>
</ul>
<div>
O main.xml criado pelo Eclipse já tem o layout vertical e a primeira TextView, só temos de acrescentar o resto, usando o que já lá está como guia (as linhas acrescentadas estão a negrito):</div>
</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><?xml version="1.0" encoding="utf-8"?></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="fill_parent"</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="fill_parent"</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> android:orientation="vertical" ></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <TextView</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_width="fill_parent"</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> android:layout_height="wrap_content"</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> android:text="@string/hello" /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> <b><LinearLayout</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_width="fill_parent"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_height="wrap_content" ></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b><br /></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> <TextView</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:id="@+id/textView1"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_width="wrap_content"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_height="wrap_content"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_weight="1"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:text="@string/tvName" /></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b><br /></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> <EditText</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:id="@+id/editText1"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_width="wrap_content"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_height="wrap_content"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_weight="1"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:ems="10" /></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b><br /></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> </LinearLayout></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b><br /></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> <Button</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:id="@+id/button1"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_width="fill_parent"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:layout_height="wrap_content"</b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><b> android:text="@string/btOk" /></b></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"></LinearLayout></span></div>
</div>
<div>
<br /></div>
<div>
Algumas coisas são óbvias, outras nem por isso.</div>
<div>
<br /></div>
<div>
Um elemento <b><LinearLayout></b> precisa sempre de um <b></LinearLayout></b> a fechar, porque um layout pode conter um número indeterminado de elementos, mas um elemento <b>TextView</b>, <b>EditText</b>, <b>Button</b>, etc não precisa da tag a fechar.</div>
<div>
<br /></div>
<div>
Todos os elementos (layouts ou não) precisam de pelo menos as propriedades <b>android:layout_width</b> e <b>android:layout_height</b> definidas. O valor <b>fill_parent</b> indica que o elemento deve estender-se para encher a área disponível no elemento "pai". O valor <b>wrap_content</b> indica que o elemento deve ocupar apenas o espaço necessário.</div>
<div>
<br /></div>
<div>
Os elementos gráficos precisam de um <b>android:id</b>. Observamos que todos os id aqui presentes começam com um <b>@</b> e que as views (é como são conhecidos os widgets no Android) têm um <b>@+</b>, enquanto que as strings têm um <b>@</b> sozinho.</div>
<div>
O <b>@</b> indica que não queremos que o que está escrito dentro das "" seja escrito literalmente, mas que seja procurada a referência nos recursos (ou seja algures em <b>res/</b>). No caso das strings o <b>@string/btOk</b> significa "<i>procura nas strings uma com o id <b>btOk</b></i>". No caso das views o <b>@+id/button1</b> significa "<i>cria um identificador para esta view chamado </i><b style="font-style: italic;">button1</b>". Ou seja o <b>+</b> é usado para criar um novo id. Se houver mais tarde uma nova referência a este botão bastaria usar <b>@id/button1</b>.</div>
<div>
Também é possível referenciar recursos disponibilizados pelo próprio Android com <b>@android:id/qq_coisa</b>, mas lá iremos.</div>
<div>
<br /></div>
<div>
Se os elementos tiverem algum conteúdo de texto este é definido com <b>android:text</b>. Podemos fazer uma pequena experiência que é acrescentar a linha <b>android:text="Escreva o seu nome"</b> ao EditText. Se corrermos agora a aplicação aparece o texto "<b>Escreva o seu nome</b>" na caixa de edição. Já sabemos que não é boa ideia ter strings <i>hardcoded</i> na aplicação, por isso se quisermos realmente que apareça uma mensagem devemos criar uma string no <b>strings.xml</b> e colocar aqui o seu id.</div>
<div>
<br /></div>
<div>
A propriedade <b>android:ems="10"</b> do <b>EditText</b> parece um pouco mais obscura. Define a largura mínima do campo, que neste caso é de <b>10 ems</b>. E o que é um "ems"? É a largura da letra mais larga, que é a letra "M", daí o nome. Ou seja, é o número de M's que cabem no campo.</div>
<div>
<br /></div>
<div>
E cá está, mais um programa que não faz nada, sem escrever uma única linha de código.</div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8205744447244084096.post-10395882331219590942012-04-22T14:09:00.002+01:002012-04-22T18:32:38.112+01:00<h2>
Programar para Android - 03</h2>
<br />
<i>Try01 - Layout com o editor gráfico.</i><br />
<br />
Vamos fazer mais uns TryXX até conseguirmos fazer um programa que realize algum trabalho útil (se bem que não muito) lá pelo <b>Try07</b>.<br />
<br />
Android usa intensamente o interface gráfico, por isso alguma forma haverá de definir o interface gráfico de uma atividade. Na verdade existem 3 formas: usando métodos Java, usando ficheiros XML e usando o editor de interface gráfica incluído no Eclipse. É claro que o editor do Eclipse é o mais fácil de usar, mas por vezes temos de usar um dos outros métodos. Se, por exemplo, a informação que queremos mostrar é obtida em runtime temos de usar o Java para definir os elementos gráficos.<br />
<br />
Neste try vamos começar por usar o editor do Eclipse. Criamos um novo projeto <b>Try01</b>. O Eclipse cria o Hello World do costume. Tipicamente há 3 ficheiros que vamos usar muito: o .java da atividade, o <b>res/value/strings.xml</b> e o <b>res/layout/main.xml</b>, por isso podemos começar por abrir os três.<br />
Já usámos estes três ficheiros no <b>Try00</b>, mas aí limitamo-nos a apagar coisas.<br />
<br />
No editor visual do main.xml, vemos uma grande quantidade de informação, o que ao princípio pode ser intimidante.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQNQ_CH5orAo5KkzgVehOzOraioJXRAVj7sqXMjJeC62RyBOMgJEmxFn9JySDZDqOlItDfGnd3pBruo6eMyt6fpLYYXUu86vBfF6Ate-l5iW_P0nkHbJ4Gp_CD535kpgFZimOmRl8MOKXF/s1600/try01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQNQ_CH5orAo5KkzgVehOzOraioJXRAVj7sqXMjJeC62RyBOMgJEmxFn9JySDZDqOlItDfGnd3pBruo6eMyt6fpLYYXUu86vBfF6Ate-l5iW_P0nkHbJ4Gp_CD535kpgFZimOmRl8MOKXF/s400/try01.png" width="400" /></a></div>
No lado direito temos uma janela "Outline", que apresenta todos os elementos gráficos, organizados em árvore. Cada elemento gráfico fica dentro de um "layout". O pré-definido é o layout linear vertical (<b>LinearLayout</b>, que é vertical vê-se porque o ícone ao lado apresenta umas caixas empilhadas verticalmente). Há vários (neste momento 8) tipos de layout, mas quase sempre se usam apenas o LinearLayout vertical e horizontal. É possível (e muito comum) colocar um layout dentro de outro layout.<br />
Na janela do <b>main.xml</b> propriamente dito temos dois separadores na base (estilo separadores do Excel) onde podemos ver o <b>Graphical Layout</b> ou XML do ficheiro. Neste try vamos ficar pelo graphical layout, mas podemos sempre dar uma olhadela ao XML, para ver como fica.<br />
Este try não faz nenhum trabalho útil, mas a ideia é criar um layout várias linhas, em que há:<br />
<br />
<ul>
<li>um texto na primeira linha (já lá está, é o hello world);</li>
<li>um texto e uma caixa de entrada na segunda linha (lado a lado);</li>
<li>um botão na terceira linha (o botão é suposto ocupar toda a largura do écrã).</li>
</ul>
<br />
<br />
Bem, o texto do hello world já está no sítio, por isso nem lhe mexemos por enquanto.<br />
Com o grupo "<b>Form widgets</b>" selecionado na <b>palete</b>, basta arrastar um <b>TextView</b> para a área do editor gráfico para criar a respetiva área de texto. Um <b>TextView</b> é o que noutros ambiente se chamaria uma <b>Label</b> (ou <b>JLabel</b>). É um texto estático, não interativo. A <b>palette</b> apresenta 4 <b>TextView</b>, a de tamanho normal (<b>TextView</b>), grande (<b>Large</b>), um pouco maior (<b>Medium</b>) e mais pequena (<b>Small</b>). Para este try escolhemos o que nos apetecer no momento. É claro que depois de introduzir a <b>TextView</b> lhe podemos mudar o tamanho (e mais uma tonelada de outras propriedades), mas vamos KISS e usar só o que está na <b>palette</b>.<br />
<br />
Agora adicionamos o campo de entrada de texto. Esses campos estão no grupos <b>Text Fields</b> da <b>palette</b>. Há muito tipos, para texto, números, datas, passwords, etc. Escolhemos logo o primeiro e arrastamos para o editor gráfico. O campo de texto fica por baixo (ou por cima, depende de onde o largarmos) do <b>TextView</b>, mas nós queremos que fique ao lado. Não vale a penas arrastar mais, estamos a colocar os elementos dentro de um layout vertical, por isso ficam sempre na vertical. Temos de adicionar um layout horizontal. Estão no grupo Layouts.<br />
Ao arrastar um <b>LinearLayout</b> horizontal, cria-se uma zona retangular vazia. Arrastamos agora o <b>TextView</b> e o <b>Text Field</b> para dentro deste retângulo. Por arrastamento é possível controlar qual fica à esquerda e à direita (prestar atenção às linhas amarelas que aparecem). O aspeto não fica muito bom (o texto deve ficar muito apertado), mas já vamos tratar disso a seguir.<br />
<br />
Pro fim arrastamos um botão (está nos <b>Form Widgets</b>, há botões normais e pequenos) para baixo do <b>LinearLayout</b> horizontal. Mas o botão não ocupa a largura toda do écrã. Logo acima da pré-visualização do aspeto gráfico da atividade há uma série de botões. Com o botão selecionado vemos os seguintes:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-YyDm5zUZ2AWdz5i4vVdeg37S9YZRnrGjLzySjHQiIhiPIiwVaLm1oiGpaRiRp-bBIsRb8lavKtIinqjVHX54clzSk3xsjafNiaMA_FSNAb1io7QnNnTgTlwBcqjLBfiyasaadu3ENZGn/s1600/try01-bt1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-YyDm5zUZ2AWdz5i4vVdeg37S9YZRnrGjLzySjHQiIhiPIiwVaLm1oiGpaRiRp-bBIsRb8lavKtIinqjVHX54clzSk3xsjafNiaMA_FSNAb1io7QnNnTgTlwBcqjLBfiyasaadu3ENZGn/s1600/try01-bt1.png" /></a></div>
Os dois primeiros controlam o tipo de layout (vertical ou horizontal) em que o elemento atual (neste caso o botão) está inserido. O terceiro e quarto controlam se o botão ocupa a largura/altura completa do écrã. Clicamos no terceiro. Os restantes botões controlam outras propriedades mais comuns do botão. Mais uma vez, estas propriedades podem ser alteradas na lista de propriedades do botão, esta barra de ferramentas é apenas um atalho para as propriedades mais comuns.<br />
<br />
O aspeto da segunda linha (a que tem a <b>TextView</b> e o <b>Text Field</b>) também se pode melhorar com este botão. Provavelmente o melhor é desligar esta opção nos dois widgets.<br />
<br />
Agora vamos tratar das strings.<br />
Vamos supor que o campo de texto é para escrever o nosso nome e que, portanto, a <b>TextView</b> à esquerda deve ter a string "Nome".<br />
Ao clicar nesta <b>TextView</b> vemos no <b>Outline</b> que é selecionado o "<b>textView1</b>". É o nome do objeto associada ao widget. Fazendo click direto sobre a <b>TextView</b> (ou sobre o seu identificador no <b>Outline</b>) aparece um menu de contexto. Precisamos da primeira opção, <b>Edit Text...</b><br />
Aparece uma caixa de diálogo com as strings definidas para a nossa aplicação. Por enquanto devem lá estar duas. Vamos criar uma terceira em <b>New String...</b> Em String colocamos o que queremos que apareça no écrã, neste caso "Nome" (sem aspas). Em <b>New R.string</b> colocamos o identificador que vai identificar este texto, por exemplo <b>tvName</b> (o tv é de <b>TextView</b>, mas é claro que se pode escolher outra coisa). Há mais uma série de propriedades que se podem editar, mas não lhes vamos mexer.<br />
Depois de clicar em <b>Ok</b>, se formos espreitar ao ficheiro <b>res/values/strings.xml</b>, já lá está a nossa string.<br />
Vamos agora editar o texto do botão. Click direito e <b>Edit Text...</b> Vamos criar uma nova string com o texto <b>Ok</b> e o id <b>btOk</b>.<br />
<br />
Se queremos mudar o texto do "Hello World...", temos de ir ao <b>strings.xml</b> e alterar lá o valor da string.<br />
Podemos agora correr o projeto.<br />
<br />
Não faz absolutamente nada, mas está mais bonito.Unknownnoreply@blogger.com0