Android
Programação para Dispositivos Móveis
Parte 7 – Gráficos e outros recursos
Prof. Manuel F. Paradela Ledón, 2011.
Universidade Cruzeiro do Sul
Gráficos e outros recursos
Neste material introduziremos, com exemplos, a utilização de
alguns recursos interessantes do Android.
 Elaborar gráficos, desenhar, mostrar figuras. Uma tela de um programa
Android poderá mostrar simultaneamente textos, figuras, botões, desenhos
etc. (também, poderíamos utilizar uma tela gráfica única). Por exemplo,
uma tela poderia ter dois botões para ações, duas caixas para entrada de
texto e uma área para mostrar um gráfico.
 Sensores. Talvez uma das características que diferenciam PCs e
notebooks tradicionais de um smartphone atual seja a utilização de
sensores (de orientação, de giro, de aceleração, temperatura, luz,
humidade etc.). Programas Android que utilizem estes recursos poderão
ser mais interativos e motivadores.
 Outras mídias. Android permite mostrar vídeos ou tocar sons. Efeitos
sonoros e músicas de fundo são também elementos importantes.
Telas gráficas.
Desenhar e mostrar figuras.
Exemplo 1
 Neste primeiro exemplo mostramos
um programa com uma única tela
gráfica (classe derivada de View).
 Como não existirão outros
elementos na tela, não
precisaremos utilizar um arquivo
.xml de layout.
 Não carregaremos figuras prontas,
apenas desenharemos na tela.
 Atenderemos os eventos onClick e
onLongClick.
A classe ActGraficos, derivada de Activity
package com.testegraficosimples;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.*;
public class ActGraficos extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final MinhaView mv = new MinhaView(this); //classe derivada de View
setContentView(mv);
mv.setOnClickListener (new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(ActGraficos.this,
"nLegal! Evento click normal atendido...n", Toast.LENGTH_LONG).show();
mv.setTipoPaint(1);
}
});
}
}
Observe que o visual estará definido por uma View (ver nos próximos slides).
A classe MinhaView, derivada de View - parte 1
package com.testegraficosimples;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.shapes.OvalShape;
import android.graphics.drawable.shapes.RectShape;
import android.view.View;
import android.widget.Toast;
class MinhaView extends View {
private int tipopaint=1;
public MinhaView(Context cx) {
super(cx);
final Context viewContext = cx;
setOnLongClickListener (new View.OnLongClickListener() {
public boolean onLongClick(View v) {
Toast.makeText(viewContext,
"nnVamos limpar a tela, sem pintar nada.nn", Toast.LENGTH_LONG).show();
setTipoPaint(2);
return true;
}
});
}
public void setTipoPaint(int i) {
tipopaint = i;
invalidate(); //Importante: este método invalida a tela e provoca uma chamada ao método onDraw
}
Alguns métodos da classe Canvas (“tela para pintar”)
Fonte: Classe Canvas (em: http://developer.android.com/reference/android/graphics/Canvas.html)
int getHeight()
Returns the height of the current drawing layer
int getWidth()
Returns the width of the current drawing layer
void drawRect(float left, float top, float right, float bottom, Paint paint)
Draw the specified Rect using the specified paint.
void drawText(String text, float x, float y, Paint paint)
Draw the text, with origin at (x,y), using the specified paint.
void drawPicture(Picture picture, Rect dst)
Draw the picture, stretched to fit into the dst rectangle.
void drawPoint(float x, float y, Paint paint)
Helper for drawPoints() for drawing a single point.
void drawPoints(float[] pts, int offset, int count, Paint paint)
Draw a series of points.
void drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
Draw a line segment with the specified start and stop x,y coordinates, using the specified paint.
void drawLines(float[] pts, Paint paint)
void drawCircle(float cx, float cy, float radius, Paint paint)
Draw the specified circle using the specified paint.
void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
Draw the specified arc, which will be scaled to fit inside the specified oval.
A classe MinhaView, derivada de View - parte 2
@Override protected void onDraw(Canvas c) {
Paint p = new Paint();
p.setAntiAlias(true); //para suavizar as bordas (não o interior) do que será pintado
switch (tipopaint) {
case 1:
//Pintamos uma figura em forma de retângulo
ShapeDrawable fig1 = new ShapeDrawable(new RectShape());
fig1.getPaint().setColor(0xFFFFFF00); //retângulo amarelo
//Obs.: setBounds(int left, int top, int right, int bottom)
//setColor: os primeiros dois números são o componente
//alpha (a opacidade). FF será 100% opaco. Resumindo: 0xAARRGGBB
fig1.setBounds(0,0,35,70);
fig1.draw(c);
p.setColor(0xFFFFFFFF); //retângulo branco
c.drawRect(35,75,c.getWidth()-30, c.getHeight()-110,p);
p.setColor(0xFF0000FF); //círculo azul
c.drawCircle(c.getWidth()/2, c.getHeight()/2, c.getHeight()/4, p);
p.setColor(0xFF00FF00); //círculo verde
c.drawCircle(c.getWidth()/2, c.getHeight()/2, c.getHeight()/8, p);
p.setColor(0xFFFFFFFF); //linha branca
c.drawLine(0,0, getWidth()()/2, c.getHeight()/2,p);
A classe MinhaView, derivada de View - parte 3
//Pintamos uma figura em forma de oval
OvalShape ov;
ov = new OvalShape();
ShapeDrawable fig2 = new ShapeDrawable(ov);
//Ou resumindo seria: ShapeDrawable fig2 = new ShapeDrawable(new OvalShape());
fig2.getPaint().setColor(0x88FF0000); //certa transparência com 88
fig2.setBounds(10,10,getWidth()/2,getHeight()/2 + 20);
//getWidth() e getHeight() são valores relativos à área da View gráfica
fig2.draw(c);
p.setColor(0xFFFFFFFF); //para textos brancos
c.drawText("Observe a transparência do oval vermelho.", 2, getHeight()-25, p);
c.drawText("Experimente touch e touch longo na tela.", 2, getHeight()-10, p);
break;
case 2:
c.drawText("Experimente agora touch simples na tela.", 2, getHeight()-10, p);
break; //não pintamos nada neste caso
}//switch
}//método onDraw
}//classe MinhaView
Exemplo 2
 Neste segundo exemplo mostramos
um programa Android com uma tela
com diferentes elementos, incluindo
um objeto de uma classe derivada de
View (veja na parte superior da
figura).
 Utilizaremos um arquivo main.xml
para definir este layout.
 Observe que na tela temos dois
objetos TextView, dois Button, um
EditText e uma View.
 Atenderemos os eventos onClick e
onLongClick.
O layout da tela no arquivo main.xml 1/2
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal" >
<exemplos.exemplograficos2.MinhaView
android:id="@+id/minha_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin ="3dp"
android:layout_weight="5" /> peso => quanto espaço ocupará esta view na tela
<TextView
android:id="@+id/digite_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="Digite um valor de 1 a 5:" />
<EditText
android:id="@+id/edita_text"
android:layout_width="58dp"
android:layout_height="40dp"
android:gravity="center_horizontal"
android:inputType="number"
android:textSize="16sp" />
O layout da tela no arquivo main.xml 2/2
<Button
android:id="@+id/graf_botao"
android:layout_width="115dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:text="Gráfico" />
<TextView
android:id="@+id/info_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="Experimente click e click longo nna área do gráfico..." />
<Button
android:id="@+id/outro_botao"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:text="Outro botão" />
</LinearLayout>
A classe ActGraficos (extends Activity) - parte 1
package com.testegraficos;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.*;
public class ActGraficos extends Activity {
private MinhaView mView;
private EditText editatipo;
private Button botao,outrobotao;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
setContentView(R.layout.main);
mView = (MinhaView) findViewById(R.id.minha_view);
mView.setFocusable(true); //para que a View receba o foco em modo touch
editatipo = (EditText) findViewById(R.id.edita_text);
grafbotao = (Button) findViewById(R.id.graf_botao);
outrobotao = (Button) findViewById(R.id.outro_botao);
}
catch(Exception e){
Toast.makeText(ActGraficos.this,
"nErro.n" + e.getMessage() + "n" , Toast.LENGTH_LONG).show();
}
A classe ActGraficos (extends Activity) - parte 2
...
grafbotao.setOnClickListener (new View.OnClickListener() {
public void onClick(View v) {
int tipo = 1;
try {
tipo = Integer.parseInt(editatipo.getText().toString());
} catch(Exception ew1){}
mView.setTipoPaint(tipo);
mView.invalidate();
}
});
outrobotao.setOnClickListener (new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(ActGraficos.this,
"nLegal! Evento click normal atendido...n",
Toast.LENGTH_LONG).show();
}
});
}
}
A classe MinhaView (extends View) - parte 1
package com.testegraficos;
import android.content.Context;
class MinhaView extends View {
private int tipopaint=3;
public MinhaView(Context cx, AttributeSet attrs) {
super(cx, attrs);
requestFocus();
final Context viewContext = cx;
setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(viewContext,
"nnVamos invalidar a tela, estado inicial.nn", Toast.LENGTH_LONG).show();
tipopaint = 1;
invalidate();
}
});
setOnLongClickListener (new View.OnLongClickListener() {
public boolean onLongClick(View v) {
Toast.makeText(viewContext,
"nnVamos limpar a tela, sem pintar nada.nn", Toast.LENGTH_LONG).show();
tipopaint = 2;
invalidate();
return true;
}
});
}
A classe MinhaView (extends View) - parte 2
public void setTipoPaintv02(int i) {
tipopaint=i;
}
@Override protected void onDraw(Canvas c) {
Paint p = new Paint();
p.setAntiAlias(true); //para suavizar as bordas
switch (tipopaint) {
case 1:
ShapeDrawable fig1 = new ShapeDrawable(new RectShape());
fig1.getPaint().setColor(0xFFDDFF00);
//Obs.: setBounds(int left, int top, int right, int bottom)
fig1.setBounds(0,0,30,50);
OvalShape ov;
ov = new OvalShape();
ShapeDrawable fig2 = new ShapeDrawable(ov);
fig2.getPaint().setColor(0x44DD44FF);
//Obs.: getWidth() e getHeight() são valores relativos à área da View gráfica
fig2.setBounds(0,60,getWidth(),getHeight());
fig1.draw(c);
fig2.draw(c);
break;
A classe MinhaView (extends View) - parte 3
case 2:
p.setColor(0xFFCCCCCC); //cinza
c.drawRect(3,3,getWidth()-6, getWidth(), p);
p.setColor(0xFF0000FF); //azul
c.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2.6f-getWidth()/10, p);
p.setColor(0xFFFF0000); //vermelho
c.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2.6f-getWidth()/8, p);
p.setColor(0xFF00FF00); //verde
c.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2.6f-getWidth()/6, p);
p.setColor(0xFFFFFF00); //amarelo
c.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2.6f-getWidth()/4, p);
break;
case 3:
...
break;
case 4:
...
break;
case 5:
...
break;
} //switch
}
}
Exemplo 3
 Neste terceiro exemplo mostramos um
programa com dois elementos na tela:
um objeto de uma classe derivada de
View e um TextView (texto na parte
superior da tela).
 Utilizaremos um arquivo main.xml para
definir este layout.
 Neste programa quase não
desenharemos, porque utilizaremos
figuras prontas em arquivos .png.
 Atenderemos os eventos onKeyDown
e onTouchEvent, para permitir o
movimento do avião como resposta à
ação do usuário.
O layout da tela no arquivo main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Viajando en avión por el mundo..."
android:height="40px"
android:gravity="center" />
<com.pckaviao.AviaoView
android:id="@+id/idaviao"
android:layout_width="wrap_content" android:layout_height="wrap_content"
/>
</LinearLayout>
A classe AviaoView é derivada de View, para trabalhar em modo gráfico.
Os arquivos utilizados neste exemplo
A classe Aviao (extends Activity)
package com.pckaviao;
import android.app.Activity;
import android.os.Bundle;
public class Aviao extends Activity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
}
}
Observe que esta classe só define o layout da tela (descrito em main.xml).
A classe AviaoView (extends View) - Construtor
package com.pckaviao;
+import android.content.Context;
public class AviaoView extends View {
private Drawable imgAviao;
private Drawable bandeira;
private float x, y, xband, yband; //x,y:centro do avião; xband,yband: pos. da bandeira
private int passo = 20;
private int larg, alt, largband, altband; //larg,alt do avião; larband,altband da band.
private boolean pressionado = false;
private Context ctx;
public AviaoView(Context context, AttributeSet atts) {
super(context, atts);
ctx = context;
// Colocamos a imagem de fundo da view:
setBackgroundResource(R.drawable.mundo);
// Pegamos uma referência à imagem do avião e de uma bandeira:
imgAviao = context.getResources().getDrawable(R.drawable.aviao);
bandeira = context.getResources().getDrawable(R.drawable.italia);
// Recuperamos a largura e altura das imagens (avião e bandeiras):
larg = imgAviao.getIntrinsicWidth();
alt = imgAviao.getIntrinsicHeight();
largband = bandeira.getIntrinsicWidth();
altband = bandeira.getIntrinsicHeight();
x = 15; y = 120; xband = -100; yband = -100; //posição inicial
// Permitimos que esta View receba o foco e trate eventos de teclado:
setFocusable(true);
}
A classe AviaoView - O método onDraw (ver a lógica no próximo slide!)
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint();
canvas.drawCircle(xband, yband, 8, p);
p.setColor(0xFF00FF00); //usar p.setStyle(Style.STROKE); para apenas pintar a borda
canvas.drawCircle(xband, yband, 10, p); //círculo verde
if(Math.abs(xband/this.getWidth()-0.366)<=0.09
&& Math.abs(yband/this.getHeight()-0.861)<=0.09) { //Brasil
bandeira = getResources().getDrawable(R.drawable.brasil);
}
if(Math.abs(xband/this.getWidth()-0.742)<=0.03
&& Math.abs(yband/this.getHeight()-0.414)<=0.03) { //Itália
bandeira = getResources().getDrawable(R.drawable.italia);
}
if(Math.abs(xband/this.getWidth()-0.1598)<=0.03
&& Math.abs(yband/this.getHeight()-0.506)<=0.03) { //Cuba
bandeira = getResources().getDrawable(R.drawable.cuba);
}
if(Math.abs(xband/this.getWidth()-0.667)<=0.03
&& Math.abs(yband/this.getHeight()-0.434)<=0.03) { //Espanha
bandeira = getResources().getDrawable(R.drawable.espana);
}
if(Math.abs(xband/this.getWidth()-0.188)<=0.09
&& Math.abs(yband/this.getHeight()-0.406)<=0.09) { //USA
bandeira = getResources().getDrawable(R.drawable.usa);
}
//colocamos a bandeira na posição xband,yband e o avião na posição x,y:
bandeira.setBounds((int)(xband + largband/2),
(int)(yband-altband),(int)(xband + largband + largband/2), (int)yband);
bandeira.draw(canvas);
imgAviao.setBounds((int)x, (int)(y - alt), (int)(x + larg), (int)y );
imgAviao.draw(canvas);
}
Identificando coordenadas (pontos) na tela,
independente da resolução do aparelho
@Override
public boolean onTouchEvent(MotionEvent event) {
// Para mover o avião por operação de tipo drag and drop
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Toast.makeText(ctx, "x/this.getWidth(): " + x/this.getWidth()
+ ", y/this.getHeight(): " + y/this.getHeight() + "nnn",
Toast.LENGTH_LONG).show();
...
Por exemplo, se as coordenadas, divididas pela largura ou altura da
tela, ao clicar no centro aproximado do Brasil são 0.366 e 0.861 (sendo
0.09 uma folga com relação a esses pontos), então no método onDraw:
if(Math.abs(xband/this.getWidth()- 0.366)<= 0.09
&& Math.abs(yband/this.getHeight()- 0.861)<= 0.09) {
//pintar a bandeira do Brasil
}
A classe AviaoView - O método onKeyDown
@Override
public boolean onKeyDown(int codigoTecla, KeyEvent evento) {
//Para mover o avião por teclas de cursor, caso exista um teclado físico ou virtual
boolean repintar = true;
switch (codigoTecla) {
case KeyEvent.KEYCODE_DPAD_UP:
y -= passo;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
y += passo;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
x -= passo;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
x += passo;
break;
default:
repintar = false;
}
if (repintar) {
invalidate();
return true;
}
return super.onKeyDown(codigoTecla, evento);
}
A classe AviaoView - O método onTouchEvent– Parte 1
@Override
public boolean onTouchEvent(MotionEvent event) {
// Para mover o avião por operação de tipo drag and drop
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Inicia o movimento se pressionou a imagem:
pressionado = imgAviao.copyBounds().contains((int) x, (int) y);
/*
Para identificar pontos no mapa, saber suas posições relativas,
independente das resoluções e tamanhos de telas dos diferentes aparelhos:
Toast.makeText(ctx, "x/this.getWidth(): " + x/this.getWidth()
+ ", y/this.getHeight(): " + y/this.getHeight()
+ "nnn", Toast.LENGTH_LONG).show();
*/
break;
A classe AviaoView - O método onTouchEvent – Parte 2
case MotionEvent.ACTION_MOVE:
// Arrastamos o avião:
if (pressionado) {
this.x = (int) x - (larg / 2);
this.y = (int) y - (alt / 4);
this.xband = (int) x - largband/2;
this.yband = (int) y - 2*altband;
}
break;
case MotionEvent.ACTION_UP:
// Terminamos o movimento:
if(pressionado) {
Context ctx = getContext();
AudioManager som =
(AudioManager)ctx.getSystemService(Context.AUDIO_SERVICE);
som.playSoundEffect(SoundEffectConstants.CLICK);
}
pressionado = false;
break;
}
invalidate(); //lembre que chamar este método provocará executar onDraw
return true;
}
}
Sensores em Android
Constants
int TYPE_ACCELEROMETER A constant describing an accelerometer sensor type.
int TYPE_ALL A constant describing all sensor types.
int TYPE_GRAVITY A constant describing a gravity sensor type.
int TYPE_GYROSCOPE A constant describing a gyroscope sensor type
int TYPE_LIGHT A constant describing an light sensor type.
int TYPE_LINEAR_ACCELERATION A constant describing a linear acceleration sensor type.
int TYPE_MAGNETIC_FIELD A constant describing a magnetic field sensor type.
int TYPE_ORIENTATION This constant is deprecated. use SensorManager.getOrientation() instead.
int TYPE_PRESSURE A constant describing a pressure sensor type
int TYPE_PROXIMITY A constant describing an proximity sensor type.
int TYPE_ROTATION_VECTOR A constant describing a rotation vector sensor type.
int TYPE_TEMPERATURE A constant describing a temperature sensor type
Fonte: Classe Sensor (em http://developer.android.com/reference/android/hardware/Sensor.html)
http://developer.android.com/reference/android/hardware/SensorEvent.html#values
Obs.: Consulte com o fabricante do aparelho os sensores disponíveis.
Exemplo 4 Obs.: o simulador não permite testar sensores...
 Neste quarto exemplo mostramos um
programa com um elemento na tela:
um objeto da classe ImageView.
 Utilizaremos um arquivo main.xml para
definir este layout.
 Neste programa não desenharemos,
porque utilizaremos figuras prontas em
arquivos .png. Também, utilizaremos
sons preparados em arquivos .wav.
 Atenderemos os eventos onResume,
onPause e onSensorChanged, para
trocar a figura e tocar um som como
resposta à inclinação do aparelho.
O layout da tela no arquivo main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/foto1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
Os arquivos utilizados neste exemplo
Sugestão: Consulte os detalhes da classe MediaPlayer em http://developer.android.com/reference/android/media/MediaPlayer.html e
os tipos de mídia permitidos por Android em: http://developer.android.com/guide/appendix/media-formats.html.
A classe SensoresPerro (extends Activity) - Parte 1
package com.pcksensoresperro;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.Toast;
public class SensoresPerro extends Activity implements SensorEventListener {
private SensorManager sensorManager; //manipulador de sensores
private Sensor sensor1,sensor2,sensor3; //sensores
private float magnetic_values[] = null, accelerometer_values [] = null;
private boolean deitado=false,empe=false;
private MediaPlayer late=null, dorme = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
late = MediaPlayer.create(this, R.raw.latindo);
dorme = MediaPlayer.create(this, R.raw.dormindo);
} catch (Exception e) {
Toast.makeText(SensoresPerro.this, "nErro:n" + e.getMessage() + "n", Toast.LENGTH_LONG).show();
}
// Para manipular os sensores:
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensor1 = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
sensor2 = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensor3 = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
Dois objetos da classe
MediaPlayer (late e dorme) são
criados, utilizando os arquivos de
áudio latindo.wav e
dormindo.wav, que se
encontram na pasta raw.
Foram preparados sensores de
orientação, de acelerómetro e
de campo magnético.
A classe SensoresPerro (extends Activity) - Parte 2
// Ativamos a atualização dos sensores quando a Activity é retomada
@Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this , sensor1, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this , sensor2, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this , sensor3, SensorManager.SENSOR_DELAY_NORMAL);
}
// Paramos a atualização dos sensores quando a Activity fique em pausa
@Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this, sensor1);
sensorManager.unregisterListener(this, sensor2);
sensorManager.unregisterListener(this, sensor3);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
A classe SensoresPerro (extends Activity) - Parte 3
@Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_MAGNETIC_FIELD:
this.magnetic_values = event.values.clone(); //preencher vetor
break;
case Sensor.TYPE_ACCELEROMETER:
this.accelerometer_values = event.values.clone(); //preencher vetor
break;
case Sensor.TYPE_ORIENTATION:
if (this.magnitude_values != null && this.accelerometer_values != null) {
float[] Rm = new float[9];
float[] In = new float[9];
SensorManager.getRotationMatrix(Rm, In, this.accelerometer_values,
this.magnetic_values); //gera Rm
float[] actual_orientation = new float[3];
SensorManager.getOrientation(Rm, actual_orientation); //gera actual_orientation
//actual_orientation[0]: azimuth, rotation around the Z axis.
//actual_orientation[1]:
// pitch, rotation around the X axis  posição “vertical”
//actual_orientation[2]: roll, rotation around the Y axis.
Obs.: o método getRotationMatrix necessita dos valores dos vetores do acelerómetro e do sensor magnético para gerar a
matriz de rotação. O método getOrientation necessita a matriz de rotação para poder gerar os valores do vetor de orientação.
Sistema de coordenadas utilizado
Fonte: http://developer.android.com/reference/android/hardware/SensorManager.html
A classe SensoresPerro (extends Activity) - Parte 4
Continuação do evento onSensorChanged e do caso case Sensor.TYPE_ORIENTATION:
ImageView foto1 = (ImageView) findViewById(R.id.foto1);
if( Math.abs(Math.abs(actual_orientation[1])-1.57)<=0.35 ||
Math.abs(Math.abs(actual_orientation[2])-1.57)<=0.40 ) {
foto1.setImageResource(R.drawable.dog1);
if(!empe) {
empe = true;
deitado = false;
try{
late.start();
} catch (Exception e) {}
}
}
else {
foto1.setImageResource(R.drawable.dog2);
if(!deitado) {
deitado = true;
empe = false;
try{
dorme.start();
} catch (Exception e) {}
}
}
} //fim do if (this.magnitude_values != null && this.accelerometer_values != null)
break;
}//switch
} //método onSensorChanged
} // classe SensoresPerro
Comparamos com π/2 (1.57, que são
90º). Se estiver próximo do ângulo
1.57, então o cachorro deverá ser
mostrado em pé, figura dog1.png.
Caso contrário, mostraremos o
cachorro deitado, figura dog2.png.
Um som específico será tocado em
cada caso, com o método start().
Exemplo 5 - Rotação de figuras
 Neste quinto exemplo modificamos o
Exemplo 4. Agora sem áudio, o
cachorro dará voltas na tela com a
ativação dos sensores de orientação.
 Utilizaremos um arquivo main.xml para
definir este layout.
 Neste programa não desenharemos,
porque utilizaremos figuras prontas em
arquivos .png.
 Atenderemos os eventos onResume,
onPause e onSensorChanged.
O método onSensorChanged modificado
@Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_MAGNETIC_FIELD:
this.magnitude_values = event.values.clone();
break;
case Sensor.TYPE_ACCELEROMETER:
this.accelerometer_values = event.values.clone();
break;
case Sensor.TYPE_ORIENTATION:
if (this.magnitude_values != null && this.accelerometer_values != null) {
... //aqui os comandos para obter a matriz de rotação etc., igual que no método anterior
if( Math.abs(Math.abs(actual_orientation[1])-1.57)<=0.35
|| Math.abs(Math.abs(actual_orientation[2])-1.57)<=0.40 ) {
if(!empe) {
empe = true; //empe e deitado são variáveis globais
deitado = false;
}
}
else {
if(!deitado) {
deitado = true;
empe = false;
}
}
}
rodarCachorro();
break; //fim do case Sensor.TYPE_ORIENTATION:
}//switch
}
O método rodarCachorro
public void rodarCachorro () {
Bitmap bitmap = null;
ImageView foto1 = (ImageView) findViewById(R.id.foto1);
//Criamos um bitmap utilizando a figura em dog1.png ou dog2.png:
if (empe) //se o cachoro estiver em pé:
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dog1);
else //se o cachoro estiver durmindo:
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dog2);
int largura = bitmap.getWidth();
int altura = bitmap.getHeight();
int novaLargura = 150;
int novaAltura = 150;
//Calculamos a escala:
float escalaLargura = ((float) novaLargura) / largura;
float escalaAltura = ((float) novaAltura) / altura;
//Criamos uma matriz de transformação para manipulação da figura,
//com a escala e o ângulo de rotação (em graus) desejados:
Matrix matrix = new Matrix();
matrix.postScale(escalaLargura, escalaAltura); //redimensionará a figura
angulo += 10; //incremento de 10º no ângulo do cachorro que será mostrado (variável global)
matrix.postRotate(angulo); //para rotar a figura
//Criamos um novoBitmap usando o bitmap inicial e a matriz de transformação antes preparada:
Bitmap novoBitmap = Bitmap.createBitmap(bitmap, 0, 0, largura, altura, matrix, true);
//Finalmente, criamos um bitmap "desenhável", que será utilizado para alterar a imagem na tela:
BitmapDrawable bitmapPintavel = new BitmapDrawable(novoBitmap);
foto1.setImageDrawable(bitmapPintavel);
}
Aplicativos para testes de sensores
Para verificar os sensores do seu aparelho você poderá instalar, por exemplo, o app
Android Sensor Box, Sensors ou AndroSensor, todos disponíveis gratuitamente na
Google Play (fonte: https://play.google.com/store/apps).
Mostrando um vídeo com a classe VideoView
A seguir um exemplo muito simples, uma Activity que demonstra como
utilizar a classe VideoView para mostrar um vídeo m.3gp, armazenado
no cartão de memória, na pasta dcim.
import android.widget.MediaController;
import android.widget.VideoView;
...
public class ExemploVideoView extends Activity {
@Override
public void onCreate(Bundle b) {
super.onCreate(b);
VideoView v = new VideoView(this);
setContentView(v);
v.setVideoPath("/sdcard/dcim/m.3gp");
v.setMediaController(new MediaController(this));
v.requestFocus();
}
}
Bibliografia sugerida
Bibliografia sugerida sobre Android
ANDROID. Android Developers.
Disponível em http://developer.android.com.
LECHETA, RICARDO R. Google Android, Aprenda a criar aplicações
para dispositivos móveis com o Android SDK.
São Paulo: Novatec, 2010.
MEDNIEKS, Z. et. al. Desenvolvimento de Aplicações Android.
São Paulo: Novatec, 2009.

Android - Parte 7

  • 1.
    Android Programação para DispositivosMóveis Parte 7 – Gráficos e outros recursos Prof. Manuel F. Paradela Ledón, 2011. Universidade Cruzeiro do Sul
  • 2.
    Gráficos e outrosrecursos Neste material introduziremos, com exemplos, a utilização de alguns recursos interessantes do Android.  Elaborar gráficos, desenhar, mostrar figuras. Uma tela de um programa Android poderá mostrar simultaneamente textos, figuras, botões, desenhos etc. (também, poderíamos utilizar uma tela gráfica única). Por exemplo, uma tela poderia ter dois botões para ações, duas caixas para entrada de texto e uma área para mostrar um gráfico.  Sensores. Talvez uma das características que diferenciam PCs e notebooks tradicionais de um smartphone atual seja a utilização de sensores (de orientação, de giro, de aceleração, temperatura, luz, humidade etc.). Programas Android que utilizem estes recursos poderão ser mais interativos e motivadores.  Outras mídias. Android permite mostrar vídeos ou tocar sons. Efeitos sonoros e músicas de fundo são também elementos importantes.
  • 3.
  • 4.
    Exemplo 1  Nesteprimeiro exemplo mostramos um programa com uma única tela gráfica (classe derivada de View).  Como não existirão outros elementos na tela, não precisaremos utilizar um arquivo .xml de layout.  Não carregaremos figuras prontas, apenas desenharemos na tela.  Atenderemos os eventos onClick e onLongClick.
  • 5.
    A classe ActGraficos,derivada de Activity package com.testegraficosimples; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.*; public class ActGraficos extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final MinhaView mv = new MinhaView(this); //classe derivada de View setContentView(mv); mv.setOnClickListener (new View.OnClickListener() { public void onClick(View v) { Toast.makeText(ActGraficos.this, "nLegal! Evento click normal atendido...n", Toast.LENGTH_LONG).show(); mv.setTipoPaint(1); } }); } } Observe que o visual estará definido por uma View (ver nos próximos slides).
  • 6.
    A classe MinhaView,derivada de View - parte 1 package com.testegraficosimples; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.shapes.OvalShape; import android.graphics.drawable.shapes.RectShape; import android.view.View; import android.widget.Toast; class MinhaView extends View { private int tipopaint=1; public MinhaView(Context cx) { super(cx); final Context viewContext = cx; setOnLongClickListener (new View.OnLongClickListener() { public boolean onLongClick(View v) { Toast.makeText(viewContext, "nnVamos limpar a tela, sem pintar nada.nn", Toast.LENGTH_LONG).show(); setTipoPaint(2); return true; } }); } public void setTipoPaint(int i) { tipopaint = i; invalidate(); //Importante: este método invalida a tela e provoca uma chamada ao método onDraw }
  • 7.
    Alguns métodos daclasse Canvas (“tela para pintar”) Fonte: Classe Canvas (em: http://developer.android.com/reference/android/graphics/Canvas.html) int getHeight() Returns the height of the current drawing layer int getWidth() Returns the width of the current drawing layer void drawRect(float left, float top, float right, float bottom, Paint paint) Draw the specified Rect using the specified paint. void drawText(String text, float x, float y, Paint paint) Draw the text, with origin at (x,y), using the specified paint. void drawPicture(Picture picture, Rect dst) Draw the picture, stretched to fit into the dst rectangle. void drawPoint(float x, float y, Paint paint) Helper for drawPoints() for drawing a single point. void drawPoints(float[] pts, int offset, int count, Paint paint) Draw a series of points. void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) Draw a line segment with the specified start and stop x,y coordinates, using the specified paint. void drawLines(float[] pts, Paint paint) void drawCircle(float cx, float cy, float radius, Paint paint) Draw the specified circle using the specified paint. void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) Draw the specified arc, which will be scaled to fit inside the specified oval.
  • 8.
    A classe MinhaView,derivada de View - parte 2 @Override protected void onDraw(Canvas c) { Paint p = new Paint(); p.setAntiAlias(true); //para suavizar as bordas (não o interior) do que será pintado switch (tipopaint) { case 1: //Pintamos uma figura em forma de retângulo ShapeDrawable fig1 = new ShapeDrawable(new RectShape()); fig1.getPaint().setColor(0xFFFFFF00); //retângulo amarelo //Obs.: setBounds(int left, int top, int right, int bottom) //setColor: os primeiros dois números são o componente //alpha (a opacidade). FF será 100% opaco. Resumindo: 0xAARRGGBB fig1.setBounds(0,0,35,70); fig1.draw(c); p.setColor(0xFFFFFFFF); //retângulo branco c.drawRect(35,75,c.getWidth()-30, c.getHeight()-110,p); p.setColor(0xFF0000FF); //círculo azul c.drawCircle(c.getWidth()/2, c.getHeight()/2, c.getHeight()/4, p); p.setColor(0xFF00FF00); //círculo verde c.drawCircle(c.getWidth()/2, c.getHeight()/2, c.getHeight()/8, p); p.setColor(0xFFFFFFFF); //linha branca c.drawLine(0,0, getWidth()()/2, c.getHeight()/2,p);
  • 9.
    A classe MinhaView,derivada de View - parte 3 //Pintamos uma figura em forma de oval OvalShape ov; ov = new OvalShape(); ShapeDrawable fig2 = new ShapeDrawable(ov); //Ou resumindo seria: ShapeDrawable fig2 = new ShapeDrawable(new OvalShape()); fig2.getPaint().setColor(0x88FF0000); //certa transparência com 88 fig2.setBounds(10,10,getWidth()/2,getHeight()/2 + 20); //getWidth() e getHeight() são valores relativos à área da View gráfica fig2.draw(c); p.setColor(0xFFFFFFFF); //para textos brancos c.drawText("Observe a transparência do oval vermelho.", 2, getHeight()-25, p); c.drawText("Experimente touch e touch longo na tela.", 2, getHeight()-10, p); break; case 2: c.drawText("Experimente agora touch simples na tela.", 2, getHeight()-10, p); break; //não pintamos nada neste caso }//switch }//método onDraw }//classe MinhaView
  • 10.
    Exemplo 2  Nestesegundo exemplo mostramos um programa Android com uma tela com diferentes elementos, incluindo um objeto de uma classe derivada de View (veja na parte superior da figura).  Utilizaremos um arquivo main.xml para definir este layout.  Observe que na tela temos dois objetos TextView, dois Button, um EditText e uma View.  Atenderemos os eventos onClick e onLongClick.
  • 11.
    O layout datela no arquivo main.xml 1/2 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_horizontal" > <exemplos.exemplograficos2.MinhaView android:id="@+id/minha_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin ="3dp" android:layout_weight="5" /> peso => quanto espaço ocupará esta view na tela <TextView android:id="@+id/digite_text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="Digite um valor de 1 a 5:" /> <EditText android:id="@+id/edita_text" android:layout_width="58dp" android:layout_height="40dp" android:gravity="center_horizontal" android:inputType="number" android:textSize="16sp" />
  • 12.
    O layout datela no arquivo main.xml 2/2 <Button android:id="@+id/graf_botao" android:layout_width="115dp" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:text="Gráfico" /> <TextView android:id="@+id/info_text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="Experimente click e click longo nna área do gráfico..." /> <Button android:id="@+id/outro_botao" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:text="Outro botão" /> </LinearLayout>
  • 13.
    A classe ActGraficos(extends Activity) - parte 1 package com.testegraficos; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.*; public class ActGraficos extends Activity { private MinhaView mView; private EditText editatipo; private Button botao,outrobotao; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); try { setContentView(R.layout.main); mView = (MinhaView) findViewById(R.id.minha_view); mView.setFocusable(true); //para que a View receba o foco em modo touch editatipo = (EditText) findViewById(R.id.edita_text); grafbotao = (Button) findViewById(R.id.graf_botao); outrobotao = (Button) findViewById(R.id.outro_botao); } catch(Exception e){ Toast.makeText(ActGraficos.this, "nErro.n" + e.getMessage() + "n" , Toast.LENGTH_LONG).show(); }
  • 14.
    A classe ActGraficos(extends Activity) - parte 2 ... grafbotao.setOnClickListener (new View.OnClickListener() { public void onClick(View v) { int tipo = 1; try { tipo = Integer.parseInt(editatipo.getText().toString()); } catch(Exception ew1){} mView.setTipoPaint(tipo); mView.invalidate(); } }); outrobotao.setOnClickListener (new View.OnClickListener() { public void onClick(View v) { Toast.makeText(ActGraficos.this, "nLegal! Evento click normal atendido...n", Toast.LENGTH_LONG).show(); } }); } }
  • 15.
    A classe MinhaView(extends View) - parte 1 package com.testegraficos; import android.content.Context; class MinhaView extends View { private int tipopaint=3; public MinhaView(Context cx, AttributeSet attrs) { super(cx, attrs); requestFocus(); final Context viewContext = cx; setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Toast.makeText(viewContext, "nnVamos invalidar a tela, estado inicial.nn", Toast.LENGTH_LONG).show(); tipopaint = 1; invalidate(); } }); setOnLongClickListener (new View.OnLongClickListener() { public boolean onLongClick(View v) { Toast.makeText(viewContext, "nnVamos limpar a tela, sem pintar nada.nn", Toast.LENGTH_LONG).show(); tipopaint = 2; invalidate(); return true; } }); }
  • 16.
    A classe MinhaView(extends View) - parte 2 public void setTipoPaintv02(int i) { tipopaint=i; } @Override protected void onDraw(Canvas c) { Paint p = new Paint(); p.setAntiAlias(true); //para suavizar as bordas switch (tipopaint) { case 1: ShapeDrawable fig1 = new ShapeDrawable(new RectShape()); fig1.getPaint().setColor(0xFFDDFF00); //Obs.: setBounds(int left, int top, int right, int bottom) fig1.setBounds(0,0,30,50); OvalShape ov; ov = new OvalShape(); ShapeDrawable fig2 = new ShapeDrawable(ov); fig2.getPaint().setColor(0x44DD44FF); //Obs.: getWidth() e getHeight() são valores relativos à área da View gráfica fig2.setBounds(0,60,getWidth(),getHeight()); fig1.draw(c); fig2.draw(c); break;
  • 17.
    A classe MinhaView(extends View) - parte 3 case 2: p.setColor(0xFFCCCCCC); //cinza c.drawRect(3,3,getWidth()-6, getWidth(), p); p.setColor(0xFF0000FF); //azul c.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2.6f-getWidth()/10, p); p.setColor(0xFFFF0000); //vermelho c.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2.6f-getWidth()/8, p); p.setColor(0xFF00FF00); //verde c.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2.6f-getWidth()/6, p); p.setColor(0xFFFFFF00); //amarelo c.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2.6f-getWidth()/4, p); break; case 3: ... break; case 4: ... break; case 5: ... break; } //switch } }
  • 18.
    Exemplo 3  Nesteterceiro exemplo mostramos um programa com dois elementos na tela: um objeto de uma classe derivada de View e um TextView (texto na parte superior da tela).  Utilizaremos um arquivo main.xml para definir este layout.  Neste programa quase não desenharemos, porque utilizaremos figuras prontas em arquivos .png.  Atenderemos os eventos onKeyDown e onTouchEvent, para permitir o movimento do avião como resposta à ação do usuário.
  • 19.
    O layout datela no arquivo main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Viajando en avión por el mundo..." android:height="40px" android:gravity="center" /> <com.pckaviao.AviaoView android:id="@+id/idaviao" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> A classe AviaoView é derivada de View, para trabalhar em modo gráfico.
  • 20.
  • 21.
    A classe Aviao(extends Activity) package com.pckaviao; import android.app.Activity; import android.os.Bundle; public class Aviao extends Activity { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); } } Observe que esta classe só define o layout da tela (descrito em main.xml).
  • 22.
    A classe AviaoView(extends View) - Construtor package com.pckaviao; +import android.content.Context; public class AviaoView extends View { private Drawable imgAviao; private Drawable bandeira; private float x, y, xband, yband; //x,y:centro do avião; xband,yband: pos. da bandeira private int passo = 20; private int larg, alt, largband, altband; //larg,alt do avião; larband,altband da band. private boolean pressionado = false; private Context ctx; public AviaoView(Context context, AttributeSet atts) { super(context, atts); ctx = context; // Colocamos a imagem de fundo da view: setBackgroundResource(R.drawable.mundo); // Pegamos uma referência à imagem do avião e de uma bandeira: imgAviao = context.getResources().getDrawable(R.drawable.aviao); bandeira = context.getResources().getDrawable(R.drawable.italia); // Recuperamos a largura e altura das imagens (avião e bandeiras): larg = imgAviao.getIntrinsicWidth(); alt = imgAviao.getIntrinsicHeight(); largband = bandeira.getIntrinsicWidth(); altband = bandeira.getIntrinsicHeight(); x = 15; y = 120; xband = -100; yband = -100; //posição inicial // Permitimos que esta View receba o foco e trate eventos de teclado: setFocusable(true); }
  • 23.
    A classe AviaoView- O método onDraw (ver a lógica no próximo slide!) public void onDraw(Canvas canvas) { super.onDraw(canvas); Paint p = new Paint(); canvas.drawCircle(xband, yband, 8, p); p.setColor(0xFF00FF00); //usar p.setStyle(Style.STROKE); para apenas pintar a borda canvas.drawCircle(xband, yband, 10, p); //círculo verde if(Math.abs(xband/this.getWidth()-0.366)<=0.09 && Math.abs(yband/this.getHeight()-0.861)<=0.09) { //Brasil bandeira = getResources().getDrawable(R.drawable.brasil); } if(Math.abs(xband/this.getWidth()-0.742)<=0.03 && Math.abs(yband/this.getHeight()-0.414)<=0.03) { //Itália bandeira = getResources().getDrawable(R.drawable.italia); } if(Math.abs(xband/this.getWidth()-0.1598)<=0.03 && Math.abs(yband/this.getHeight()-0.506)<=0.03) { //Cuba bandeira = getResources().getDrawable(R.drawable.cuba); } if(Math.abs(xband/this.getWidth()-0.667)<=0.03 && Math.abs(yband/this.getHeight()-0.434)<=0.03) { //Espanha bandeira = getResources().getDrawable(R.drawable.espana); } if(Math.abs(xband/this.getWidth()-0.188)<=0.09 && Math.abs(yband/this.getHeight()-0.406)<=0.09) { //USA bandeira = getResources().getDrawable(R.drawable.usa); } //colocamos a bandeira na posição xband,yband e o avião na posição x,y: bandeira.setBounds((int)(xband + largband/2), (int)(yband-altband),(int)(xband + largband + largband/2), (int)yband); bandeira.draw(canvas); imgAviao.setBounds((int)x, (int)(y - alt), (int)(x + larg), (int)y ); imgAviao.draw(canvas); }
  • 24.
    Identificando coordenadas (pontos)na tela, independente da resolução do aparelho @Override public boolean onTouchEvent(MotionEvent event) { // Para mover o avião por operação de tipo drag and drop float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Toast.makeText(ctx, "x/this.getWidth(): " + x/this.getWidth() + ", y/this.getHeight(): " + y/this.getHeight() + "nnn", Toast.LENGTH_LONG).show(); ... Por exemplo, se as coordenadas, divididas pela largura ou altura da tela, ao clicar no centro aproximado do Brasil são 0.366 e 0.861 (sendo 0.09 uma folga com relação a esses pontos), então no método onDraw: if(Math.abs(xband/this.getWidth()- 0.366)<= 0.09 && Math.abs(yband/this.getHeight()- 0.861)<= 0.09) { //pintar a bandeira do Brasil }
  • 25.
    A classe AviaoView- O método onKeyDown @Override public boolean onKeyDown(int codigoTecla, KeyEvent evento) { //Para mover o avião por teclas de cursor, caso exista um teclado físico ou virtual boolean repintar = true; switch (codigoTecla) { case KeyEvent.KEYCODE_DPAD_UP: y -= passo; break; case KeyEvent.KEYCODE_DPAD_DOWN: y += passo; break; case KeyEvent.KEYCODE_DPAD_LEFT: x -= passo; break; case KeyEvent.KEYCODE_DPAD_RIGHT: x += passo; break; default: repintar = false; } if (repintar) { invalidate(); return true; } return super.onKeyDown(codigoTecla, evento); }
  • 26.
    A classe AviaoView- O método onTouchEvent– Parte 1 @Override public boolean onTouchEvent(MotionEvent event) { // Para mover o avião por operação de tipo drag and drop float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // Inicia o movimento se pressionou a imagem: pressionado = imgAviao.copyBounds().contains((int) x, (int) y); /* Para identificar pontos no mapa, saber suas posições relativas, independente das resoluções e tamanhos de telas dos diferentes aparelhos: Toast.makeText(ctx, "x/this.getWidth(): " + x/this.getWidth() + ", y/this.getHeight(): " + y/this.getHeight() + "nnn", Toast.LENGTH_LONG).show(); */ break;
  • 27.
    A classe AviaoView- O método onTouchEvent – Parte 2 case MotionEvent.ACTION_MOVE: // Arrastamos o avião: if (pressionado) { this.x = (int) x - (larg / 2); this.y = (int) y - (alt / 4); this.xband = (int) x - largband/2; this.yband = (int) y - 2*altband; } break; case MotionEvent.ACTION_UP: // Terminamos o movimento: if(pressionado) { Context ctx = getContext(); AudioManager som = (AudioManager)ctx.getSystemService(Context.AUDIO_SERVICE); som.playSoundEffect(SoundEffectConstants.CLICK); } pressionado = false; break; } invalidate(); //lembre que chamar este método provocará executar onDraw return true; } }
  • 28.
    Sensores em Android Constants intTYPE_ACCELEROMETER A constant describing an accelerometer sensor type. int TYPE_ALL A constant describing all sensor types. int TYPE_GRAVITY A constant describing a gravity sensor type. int TYPE_GYROSCOPE A constant describing a gyroscope sensor type int TYPE_LIGHT A constant describing an light sensor type. int TYPE_LINEAR_ACCELERATION A constant describing a linear acceleration sensor type. int TYPE_MAGNETIC_FIELD A constant describing a magnetic field sensor type. int TYPE_ORIENTATION This constant is deprecated. use SensorManager.getOrientation() instead. int TYPE_PRESSURE A constant describing a pressure sensor type int TYPE_PROXIMITY A constant describing an proximity sensor type. int TYPE_ROTATION_VECTOR A constant describing a rotation vector sensor type. int TYPE_TEMPERATURE A constant describing a temperature sensor type Fonte: Classe Sensor (em http://developer.android.com/reference/android/hardware/Sensor.html) http://developer.android.com/reference/android/hardware/SensorEvent.html#values Obs.: Consulte com o fabricante do aparelho os sensores disponíveis.
  • 29.
    Exemplo 4 Obs.:o simulador não permite testar sensores...  Neste quarto exemplo mostramos um programa com um elemento na tela: um objeto da classe ImageView.  Utilizaremos um arquivo main.xml para definir este layout.  Neste programa não desenharemos, porque utilizaremos figuras prontas em arquivos .png. Também, utilizaremos sons preparados em arquivos .wav.  Atenderemos os eventos onResume, onPause e onSensorChanged, para trocar a figura e tocar um som como resposta à inclinação do aparelho.
  • 30.
    O layout datela no arquivo main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+id/foto1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" /> </LinearLayout>
  • 31.
    Os arquivos utilizadosneste exemplo Sugestão: Consulte os detalhes da classe MediaPlayer em http://developer.android.com/reference/android/media/MediaPlayer.html e os tipos de mídia permitidos por Android em: http://developer.android.com/guide/appendix/media-formats.html.
  • 32.
    A classe SensoresPerro(extends Activity) - Parte 1 package com.pcksensoresperro; import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.media.MediaPlayer; import android.os.Bundle; import android.widget.ImageView; import android.widget.Toast; public class SensoresPerro extends Activity implements SensorEventListener { private SensorManager sensorManager; //manipulador de sensores private Sensor sensor1,sensor2,sensor3; //sensores private float magnetic_values[] = null, accelerometer_values [] = null; private boolean deitado=false,empe=false; private MediaPlayer late=null, dorme = null; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { late = MediaPlayer.create(this, R.raw.latindo); dorme = MediaPlayer.create(this, R.raw.dormindo); } catch (Exception e) { Toast.makeText(SensoresPerro.this, "nErro:n" + e.getMessage() + "n", Toast.LENGTH_LONG).show(); } // Para manipular os sensores: sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); sensor1 = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); sensor2 = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); sensor3 = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); } Dois objetos da classe MediaPlayer (late e dorme) são criados, utilizando os arquivos de áudio latindo.wav e dormindo.wav, que se encontram na pasta raw. Foram preparados sensores de orientação, de acelerómetro e de campo magnético.
  • 33.
    A classe SensoresPerro(extends Activity) - Parte 2 // Ativamos a atualização dos sensores quando a Activity é retomada @Override protected void onResume() { super.onResume(); sensorManager.registerListener(this , sensor1, SensorManager.SENSOR_DELAY_NORMAL); sensorManager.registerListener(this , sensor2, SensorManager.SENSOR_DELAY_NORMAL); sensorManager.registerListener(this , sensor3, SensorManager.SENSOR_DELAY_NORMAL); } // Paramos a atualização dos sensores quando a Activity fique em pausa @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener(this, sensor1); sensorManager.unregisterListener(this, sensor2); sensorManager.unregisterListener(this, sensor3); } public void onAccuracyChanged(Sensor sensor, int accuracy) { }
  • 34.
    A classe SensoresPerro(extends Activity) - Parte 3 @Override public void onSensorChanged(SensorEvent event) { switch (event.sensor.getType()) { case Sensor.TYPE_MAGNETIC_FIELD: this.magnetic_values = event.values.clone(); //preencher vetor break; case Sensor.TYPE_ACCELEROMETER: this.accelerometer_values = event.values.clone(); //preencher vetor break; case Sensor.TYPE_ORIENTATION: if (this.magnitude_values != null && this.accelerometer_values != null) { float[] Rm = new float[9]; float[] In = new float[9]; SensorManager.getRotationMatrix(Rm, In, this.accelerometer_values, this.magnetic_values); //gera Rm float[] actual_orientation = new float[3]; SensorManager.getOrientation(Rm, actual_orientation); //gera actual_orientation //actual_orientation[0]: azimuth, rotation around the Z axis. //actual_orientation[1]: // pitch, rotation around the X axis  posição “vertical” //actual_orientation[2]: roll, rotation around the Y axis. Obs.: o método getRotationMatrix necessita dos valores dos vetores do acelerómetro e do sensor magnético para gerar a matriz de rotação. O método getOrientation necessita a matriz de rotação para poder gerar os valores do vetor de orientação.
  • 35.
    Sistema de coordenadasutilizado Fonte: http://developer.android.com/reference/android/hardware/SensorManager.html
  • 36.
    A classe SensoresPerro(extends Activity) - Parte 4 Continuação do evento onSensorChanged e do caso case Sensor.TYPE_ORIENTATION: ImageView foto1 = (ImageView) findViewById(R.id.foto1); if( Math.abs(Math.abs(actual_orientation[1])-1.57)<=0.35 || Math.abs(Math.abs(actual_orientation[2])-1.57)<=0.40 ) { foto1.setImageResource(R.drawable.dog1); if(!empe) { empe = true; deitado = false; try{ late.start(); } catch (Exception e) {} } } else { foto1.setImageResource(R.drawable.dog2); if(!deitado) { deitado = true; empe = false; try{ dorme.start(); } catch (Exception e) {} } } } //fim do if (this.magnitude_values != null && this.accelerometer_values != null) break; }//switch } //método onSensorChanged } // classe SensoresPerro Comparamos com π/2 (1.57, que são 90º). Se estiver próximo do ângulo 1.57, então o cachorro deverá ser mostrado em pé, figura dog1.png. Caso contrário, mostraremos o cachorro deitado, figura dog2.png. Um som específico será tocado em cada caso, com o método start().
  • 37.
    Exemplo 5 -Rotação de figuras  Neste quinto exemplo modificamos o Exemplo 4. Agora sem áudio, o cachorro dará voltas na tela com a ativação dos sensores de orientação.  Utilizaremos um arquivo main.xml para definir este layout.  Neste programa não desenharemos, porque utilizaremos figuras prontas em arquivos .png.  Atenderemos os eventos onResume, onPause e onSensorChanged.
  • 38.
    O método onSensorChangedmodificado @Override public void onSensorChanged(SensorEvent event) { switch (event.sensor.getType()) { case Sensor.TYPE_MAGNETIC_FIELD: this.magnitude_values = event.values.clone(); break; case Sensor.TYPE_ACCELEROMETER: this.accelerometer_values = event.values.clone(); break; case Sensor.TYPE_ORIENTATION: if (this.magnitude_values != null && this.accelerometer_values != null) { ... //aqui os comandos para obter a matriz de rotação etc., igual que no método anterior if( Math.abs(Math.abs(actual_orientation[1])-1.57)<=0.35 || Math.abs(Math.abs(actual_orientation[2])-1.57)<=0.40 ) { if(!empe) { empe = true; //empe e deitado são variáveis globais deitado = false; } } else { if(!deitado) { deitado = true; empe = false; } } } rodarCachorro(); break; //fim do case Sensor.TYPE_ORIENTATION: }//switch }
  • 39.
    O método rodarCachorro publicvoid rodarCachorro () { Bitmap bitmap = null; ImageView foto1 = (ImageView) findViewById(R.id.foto1); //Criamos um bitmap utilizando a figura em dog1.png ou dog2.png: if (empe) //se o cachoro estiver em pé: bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dog1); else //se o cachoro estiver durmindo: bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dog2); int largura = bitmap.getWidth(); int altura = bitmap.getHeight(); int novaLargura = 150; int novaAltura = 150; //Calculamos a escala: float escalaLargura = ((float) novaLargura) / largura; float escalaAltura = ((float) novaAltura) / altura; //Criamos uma matriz de transformação para manipulação da figura, //com a escala e o ângulo de rotação (em graus) desejados: Matrix matrix = new Matrix(); matrix.postScale(escalaLargura, escalaAltura); //redimensionará a figura angulo += 10; //incremento de 10º no ângulo do cachorro que será mostrado (variável global) matrix.postRotate(angulo); //para rotar a figura //Criamos um novoBitmap usando o bitmap inicial e a matriz de transformação antes preparada: Bitmap novoBitmap = Bitmap.createBitmap(bitmap, 0, 0, largura, altura, matrix, true); //Finalmente, criamos um bitmap "desenhável", que será utilizado para alterar a imagem na tela: BitmapDrawable bitmapPintavel = new BitmapDrawable(novoBitmap); foto1.setImageDrawable(bitmapPintavel); }
  • 40.
    Aplicativos para testesde sensores Para verificar os sensores do seu aparelho você poderá instalar, por exemplo, o app Android Sensor Box, Sensors ou AndroSensor, todos disponíveis gratuitamente na Google Play (fonte: https://play.google.com/store/apps).
  • 41.
    Mostrando um vídeocom a classe VideoView A seguir um exemplo muito simples, uma Activity que demonstra como utilizar a classe VideoView para mostrar um vídeo m.3gp, armazenado no cartão de memória, na pasta dcim. import android.widget.MediaController; import android.widget.VideoView; ... public class ExemploVideoView extends Activity { @Override public void onCreate(Bundle b) { super.onCreate(b); VideoView v = new VideoView(this); setContentView(v); v.setVideoPath("/sdcard/dcim/m.3gp"); v.setMediaController(new MediaController(this)); v.requestFocus(); } }
  • 42.
    Bibliografia sugerida Bibliografia sugeridasobre Android ANDROID. Android Developers. Disponível em http://developer.android.com. LECHETA, RICARDO R. Google Android, Aprenda a criar aplicações para dispositivos móveis com o Android SDK. São Paulo: Novatec, 2010. MEDNIEKS, Z. et. al. Desenvolvimento de Aplicações Android. São Paulo: Novatec, 2009.