Tutorial Android #25 – Fazendo Ligações (Chamadas)

Padrão

Olá pessoal! Tudo bem?

Sei que é triste a dor da partida, mas esse é o último tutorial dessa primeira série de tutoriais sobre Android. Mas como disse no último post, isso não significa que o tema não será mais abordado aqui no blog. Estou considerando seriamente a possibilidade de, em breve, voltar a falar de Android e as novidades que temos ao utilizar a versão 4.

Mas por enquanto, vamos fechar essa primeira série com chave de ouro. Como toda a série foi voltada para Android, um sistema utilizado massivamente em aparelhos celulares, vamos ver hoje como realizar chamadas.

Nesta última sessão de modificações em nosso aplicativo, vamos adicionar um campo chamado telefone aos nossos restaurantes e, a partir dele, vamos possibilitar que o usuário faça uma chamada diretamente do nosso aplicativo. Bacana, não?

Bom, começando, temos inicialmente que atualizar o nosso modelo de dados para que armazene o novo dado necessário (o número de telefone). Primeiramente, modifique o método onCreate() da classe GerenciadorRestaurantes para abrigar o novo campo:

@Override
public void onCreate(SQLiteDatabase db) {
	db.execSQL("CREATE TABLE restaurantes (_id INTEGER PRIMARY KEY AUTOINCREMENT," +
			" nome TEXT, endereco TEXT, tipo TEXT, anotacoes TEXT, twitter TEXT," +
			" latitude REAL, longitude REAL, telefone TEXT);");
}

Em seguida, altere o método onUpgrade() para atualizar o modelo de dados do banco, caso o usuário esteja vindo de uma versão anterior:

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
	if (oldVersion < 2) {
		db.execSQL("ALTER TABLE restaurantes ADD COLUMN twitter TEXT");
	}

	if (oldVersion < 3) {
		db.execSQL("ALTER TABLE restaurantes ADD COLUMN latitude REAL");
		db.execSQL("ALTER TABLE restaurantes ADD COLUMN longitude REAL");
	}

	if (oldVersion < 4) {
		db.execSQL("ALTER TABLE restaurantes ADD COLUMN telefone TEXT");
	}
}

Pronto. Agora, vamos procurar pelos métodos inserir(), atualizar(), obterTodos() e obterPorId() para adicionar o campo telefone a eles também.

public void inserir(String nome, String endereco, String tipo, String anotacoes, String twitter,
		String telefone) {
	ContentValues valores = new ContentValues();

	valores.put("nome", nome);
	valores.put("endereco", endereco);
	valores.put("tipo", tipo);
	valores.put("anotacoes", anotacoes);
	valores.put("twitter", twitter);
	valores.put("telefone", telefone);

	getWritableDatabase().insert("restaurantes", "nome", valores);
}

public void atualizar(String id, String nome, String endereco, String tipo, String anotacoes,
		String twitter, String telefone) {
	ContentValues valores = new ContentValues();
	String[] argumentos = {id};

	valores.put("nome", nome);
	valores.put("endereco", endereco);
	valores.put("tipo", tipo);
	valores.put("anotacoes", anotacoes);
	valores.put("twitter", twitter);
	valores.put("telefone", telefone);

	getWritableDatabase().update("restaurantes", valores, "_id=?", argumentos);
}

public Cursor obterTodos(String ordenacao) {
	return getReadableDatabase().rawQuery("select _id, nome, endereco, tipo, " +
			"anotacoes, twitter, latitude, longitude, telefone FROM restaurantes ORDER BY " +
			ordenacao, null);
}

public Cursor obterPorId(String id) {
	String[] argumentos = {id};

	return getReadableDatabase().rawQuery(
			"SELECT _id, nome, endereco, tipo, anotacoes, twitter, latitude," +
			" longitude, telefone FROM restaurantes WHERE _id = ?", argumentos);
}

Para concluir as alterações nesta classe, crie o método obterTelefone():

public String obterTelefone(Cursor c) {
	return c.getString(8);
}

Pronto. Com relação a persistência, já estamos aptos a prosseguir. Vamos agora adicionar o campo telefone aos nossos formulários. Como devem estar lembrados, temos 2 layouts, um para o modo retrato, outro para o modo paisagem. Primeiro no modo retrato, adicione o seguinte trecho logo após o campo de endereço, no arquivo res/layout/form_detalhes.xml.

<TableRow>
    <TextView android:text="@string/telefone"/>
    <EditText android:id="@+id/telefone"/>
</TableRow>

Agora no res/layout-land/form_detalhes.xml. Também, logo depois do trecho do campo de endereço.

<TableRow>
    <TextView android:text="@string/telefone"/>
    <EditText android:id="@+id/telefone"
    	android:layout_span="2" />
</TableRow>

Pronto. Nossas modificações agora serão na classe FormularioDetalhes. Primeiramente adicione o atributo telefone à classe:

EditText telefone = null;

Agora, precisamos atualizar os métodos onCreate(), salvar(), carregar(), onSaveInstanceState() e onRestoreInstanceState(). Pode parecer bastante coisa, mas são apenas ajustes leves para adicionar o novo campo.

@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.form_detalhes);

	locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
	gerenciador = new GerenciadorRestaurantes(this);

	nome = (EditText) findViewById(R.id.nome);
	endereco = (EditText) findViewById(R.id.end);
	telefone = (EditText) findViewById(R.id.telefone);
	anotacoes = (EditText) findViewById(R.id.anotacoes);
	twitter = (EditText) findViewById(R.id.twitter);
	tipos = (RadioGroup) findViewById(R.id.tipos);
	localizacao = (TextView) findViewById(R.id.localizacao);

	idRestaurante = getIntent().getStringExtra(ListaRestaurantes._ID);

	if (idRestaurante != null) {
		carregar();
	}
}

private void salvar() {
	String tipo = null;

	switch (tipos.getCheckedRadioButtonId()) {
	case R.id.rodizio:
		tipo = "rodizio";
		break;
	case R.id.fast_food:
		tipo = "fast_food";
		break;
	case R.id.a_domicilio:
		tipo = "a_domicilio";
		break;
	}

	if (tipo != null && endereco.getText().toString() != null &&
			nome.getText().toString() != null) {

		if (idRestaurante == null) {
			gerenciador.inserir(nome.getText().toString(),
					endereco.getText().toString(),
					tipo, anotacoes.getText().toString(),
					twitter.getText().toString(), telefone.getText().toString());
		} else {
			gerenciador.atualizar(idRestaurante,
					nome.getText().toString(),
					endereco.getText().toString(),
					tipo, anotacoes.getText().toString(),
					twitter.getText().toString(), telefone.getText().toString());
		}
	}

	finish();
}

private void carregar() {
	Cursor c = gerenciador.obterPorId(idRestaurante);

	c.moveToFirst();
	nome.setText(gerenciador.obterNome(c));
	endereco.setText(gerenciador.obterEndereco(c));
	telefone.setText(gerenciador.obterTelefone(c));
	anotacoes.setText(gerenciador.obterAnotacoes(c));
	twitter.setText(gerenciador.obterTwitter(c));

	if (gerenciador.obterTipo(c).equals("rodizio")) {
		tipos.check(R.id.rodizio);
	} else if (gerenciador.obterTipo(c).equals("fast_food")) {
		tipos.check(R.id.fast_food);
	} else {
		tipos.check(R.id.a_domicilio);
	}

	latitude = gerenciador.obterLatitude(c);
	longitude = gerenciador.obterLongitude(c);

	localizacao.setText(String.valueOf(gerenciador.obterLatitude(c)) +
			", " + String.valueOf(gerenciador.obterLongitude(c)));

	c.close();
}

@Override
public void onSaveInstanceState(Bundle outState) {
	super.onSaveInstanceState(outState);

	outState.putString("nome", nome.getText().toString());
	outState.putString("endereco", endereco.getText().toString());
	outState.putString("telefone", telefone.getText().toString());
	outState.putString("anotacoes", anotacoes.getText().toString());
	outState.putInt("tipo", tipos.getCheckedRadioButtonId());
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
	super.onRestoreInstanceState(savedInstanceState);

	nome.setText(savedInstanceState.getString("nome"));
	endereco.setText(savedInstanceState.getString("endereco"));
	telefone.setText(savedInstanceState.getString("telefone"));
	anotacoes.setText(savedInstanceState.getString("anotacoes"));
	tipos.check(savedInstanceState.getInt("tipo"));
}

Ufa! Perceberam como as alterações foram mínimas? 😀

Prosseguindo, precisamos dizer ao Android que nossa aplicação deseja realizar chamadas. Para isso, adicione a seguinte linha às permissões no arquivo AndroidManifest.xml.

<uses-permission android:name="android.permission.CALL_PHONE"/>

Agora, vamos criar a opção ao menu para realizar as chamadas. Edite o arquivo res/menu/opcao_detalhes.xml para acomodar a nova opção (é… vai ficar meio espremido em telas pequenas…).

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
	<item android:id="@+id/twitter"
	    android:title="@string/timeline_twitter"
	    android:icon="@drawable/twitter"/>
	<item android:id="@+id/localizacao"
	    android:title="@string/salvar_localizacao"
	    android:icon="@drawable/gps"/>
	<item android:id="@+id/mapa"
	    android:title="@string/exibir_mapa"
	    android:icon="@drawable/mapa"/>
	<item android:id="@+id/chamar"
	    android:title="@string/chamar"
	    android:icon="@drawable/chamada"/>
</menu>

O arquivo de ícone utilizado foi o ic_menu_call.png encontrado na pasta de instalação do Android e devidamente renomeado para chamada.png.

Agora precisamos definir as novas strings utilizadas no formulário e no menu. Adicione-as ao arquivo res/values/strings.xml

<string name="telefone">Telefone:</string>
<string name="chamar">Telefonar</string>

… e no res/values-es/strings.xml.

Teléfono:
Llamar

Por fim, vamos fazer com que a opção de menu realize a chamada. Adicione o seguinte trecho aos encadeamentos de ifs no método onOptionsItemSelected().

} else if (item.getItemId() == R.id.chamar) {
	String numero = "tel:" + telefone.getText().toString();
	if (numero.length() > 4) {
		startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(numero)));
	}
}

Execute a aplicação para conferir as modificações.

Caso queira que a ligação seja realizada diretamente, sem exibir o discador, modifique, na linha 158 do trecho ali em cima, ACTION_DIAL por ACTION_CALL.

Bom pessoal, é isso! Como não podia deixar de ser, para baixar o projeto, basta clicar aqui.

Agradeço a todos que vem acompanhando o blog. Continuem sempre por aqui, pois sempre tem coisa nova! Comentem, critiquem, cliquem nos banners e enviem sugestões!

Até logo!!!

10 comentários sobre “Tutorial Android #25 – Fazendo Ligações (Chamadas)

    • Digitar o endereço? Na verdade, as coordenadas são obtidas a partir do GPS. No caso do mapa, você precisa gerar a sua própria chave para utilizar a API do Google Maps (já que ela tem que bater com a chave que você está utilizando no seu ambiente de desenvolvimento). No post sobre o uso do Google Maps, tem explicado como gerá-la.

  1. Wyllyam

    Pô Rafael valeu cara.. muito fino seus tutôs hehe aprendi d+ tava precisando de umas explicações assim! esta me ajudando e vai ajudar mais ainda no meu tcc em android.. uma pergunta.. nao sei se está explicando em seu blog.. mais tiop tem como eu enviar os dados salvos no banco de dados do smartphone para um servidor? tipo para ser visualizado depois saca? Mais uma vez muiiiiiiiitooooooo obrigado cara! Abração!

  2. Wyllyam

    so mais uma duvidazinha hehe, baixei seu projeto e ele nao roda na minha maquina o que pode ser? e outra,,, tem como igual estou inserindo no banco fazer a busca desses dados depois? e tambem ele salva no banco né tem algum programa que eu possa abrir esse arquivo para visualizacao? tipo ver no arquivo do banco todos os dados que eu inseri… vlw

  3. Jackson Santos

    Excelente série de tutoriais, cara!

    Nesse último, você só não explicitou que a variável “VERSAO_SCHEMA” da classe “GerenciadorRestaurante” tem de ser alterada para 4.

    Ua

Deixe uma resposta