Escolar Documentos
Profissional Documentos
Cultura Documentos
AULA 5
Figura 1 – Activity
● LogActivity
package com.example.helloandroid
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
Saiba mais
Para mais detalhes sobre como criar propriedades em Kotlin, segue o link
oficial: <https://kotlinlang.org/docs/reference/properties.html>.
● MainActivity.kt
D/android: MainActivity.onCreate().
D/android: MainActivity.onStart().
D/android: MainActivity.onResume().
D/android: MainActivity.onPause().
D/android: MainActivity.onStop().
D/android: MainActivity.onDestroy().
D/android: MainActivity.onPause().
D/android: MainActivity.onStop().
D/android: MainActivity.onSaveInstanceState().
D/android: MainActivity.onCreate().
D/android: MainActivity.onStart().
D/android: MainActivity.onResume().
Figura 2 – Auto-rotate
Crédito: Khuruzero/Shutterstock.
MainActivity.onPause().
MainActivity.onStop().
MainActivity.onSaveInstanceState(). // Salva o estado
MainActivity.onDestroy(). // Destrói a activity
MainActivity.onCreate(). // Recria a activity e recupera o estado
MainActivity.onStart().
MainActivity.onResume().
MainActivity.onCreate().
Count: 0
MainActivity.onStart().
MainActivity.onResume().
MainActivity.onPause().
MainActivity.onStop().
MainActivity.onSaveInstanceState().
Salvando estado
MainActivity.onDestroy(). // Activity foi destruída.
MainActivity.onCreate(). // Activity recriada.
Recuperando estado
Count: 1
MainActivity.onStart().
MainActivity.onResume().
MainActivity.onPause().
CadastroActivity.onCreate().
CadastroActivity.onStart().
CadastroActivity.onResume().
MainActivity.onStop().
MainActivity.onSaveInstanceState().
CadastroActivity.onPause().
MainActivity.onRestart().
MainActivity.onStart().
MainActivity.onResume().
CadastroActivity.onStop().
CadastroActivity.onDestroy().
startActivity(Intent(this,HomeActivity::class.java))
class LoginService {
fun login(login:String, senha: String): Usuario? {
if(login == "ricardo" && senha == "123") {
return Usuario("Ricardo","a@a.com")
} else if(login == "teste" && senha == "123") {
return Usuario("Teste","b@b.com")
}
return null
}
}
Isso significa que ao logar com ricardo/123, um objeto Usuário será criado
e o nome será Ricardo. Crie a combinação que preferir para testar. No próximo
exemplo, nosso objetivo será mostrar o nome do usuário logado na tela da
Home, conforme mostra esta figura:
Crédito: Khuruzero/Shutterstock.
No código, veja que ao criar o objeto Bundle, foi dado o nome de args
para a variável:
package com.example.helloandroid
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_home.*
Destacamos em amarelo o import que deve ser feito do arquivo XML para
que o Kotlin Extensions encontre a variável tNome. Preste atenção e não erre
essa linha. Como é uma boa prática utilizar o mesmo id em diversos arquivos
XML, repare que o id tNome também existe no arquivo de layout XML do
cadastro. Um erro comum é importar o arquivo errado, o qual não está sendo
utilizado nesta tela.
Esse código é simples e está recuperando a mesma intent que é enviada
pela activity. Na segunda linha, a variável nome é lida dos parâmetros que foram
enviados. E na terceira linha, o texto do TextView é atualizado com o nome
enviado como parâmetro. Esperamos que esse exemplo tenha sido simples de
entender. Se você alterar o código da classe LoginService, poderá criar várias
combinações de login e senha para testar e brincar.
package com.example.helloandroid.domain
import java.io.Serializable
data class Usuario (
var nome: String,
var email: String
) : Serializable
Note que, como estamos usando uma Data Class, entre parênteses está
o construtor do objeto e lá ficam todos os atributos da classe. Depois dos
parênteses, foi colocada a sintaxe para implementar uma interface.
Com a classe Usuário pronta, o código agora está compilando
normalmente e já podemos alterar a classe HomeActivity para ler o objeto
enviado como parâmetro:
package com.example.helloandroid
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.helloandroid.domain.Usuario
import kotlinx.android.synthetic.main.activity_home.*
Observe que foi dado o id btTeste para o botão, assim, podemos usá-lo
para adicionar um evento e chamar as intents que vamos brincar.
package com.example.helloligacao
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
btTeste.setOnClickListener {
// Código aqui
}
}
}
A primeira intent que vamos estudar é uma chamada simples que vai abrir
o browser, basta fazer a seguinte alteração no código:
package com.example.helloligacao
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
btTeste.setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW,
Uri.parse("https://google.com"))
startActivity(intent)
}
}
}
Crédito: Khuruzero/Shutterstock.
Crédito: Khuruzero/Shutterstock.
Até o momento, estudamos dois exemplos de chamadas de intents que
abrem o browser e o mapa, e vimos o quão útil podem ser essas chamadas.
Saiba mais
Podemos ver pela mensagem que a permissão foi negada pelo sistema
(Permission Denial). Isso aconteceu porque uma ligação é restrita pelo fato de
que ela pode gerar custos para o usuário. Sendo assim, antes de fazer uma
ligação, precisamos pedir permissão para o usuário com um alerta com este:
Figura 6 – Alerta
Crédito: Khuruzero/Shutterstock.
Figura 7 – Permissões
Crédito: Khuruzero/Shutterstock.
Sendo assim, o que precisamos fazer é configurar o aplicativo para
solicitar esta permissão. A primeira tarefa a fazer é adicionar a tag <uses-
permission> no arquivo de manifesto. Essa tag define as permissões
necessárias para o aplicativo, ou seja, todos aqueles alertas que temos que
mostrar ao usuário para ele autorizar o uso de chamadas restritas. Tenha
atenção, pois a configuração fica antes da tag <application>.
● AndroidManifest.xml
<application . . .>
. . .
</application>
</manifest>
Crédito: Khuruzero/Shutterstock.
Para fazermos o primeiro teste e validar a intent que faz a ligação, clique
na permissão de telefone (Phone) e depois clique em Allow para aceitar essa
permissão.
Crédito: Khuruzero/Shutterstock.
Figura 10 – Ligação
Crédito: Khuruzero/Shutterstock.
4.3 Solicitando as permissões pelo código
Crédito: Khuruzero/Shutterstock.
package com.example.helloligacao
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
object PermissionUtils {
// Solicita uma permissão se ainda não foi concedida
fun request(activity: Activity, permissions: Array<String>) :
Boolean {
val ok = validate(activity, permissions)
if (!ok) {
ActivityCompat.requestPermissions(
activity,
permissions,
1
)
}
return ok
}
// Valida se as permissões foram concedidas
fun validate(context: Context, permissions: Array<String>):
Boolean {
for (permission in permissions) {
val result = ContextCompat.checkSelfPermission(context,
permission)
if (result != PackageManager.PERMISSION_GRANTED) {
return false
}
}
return true
}
}
Com o tempo, você vai estudar e aprender mais sobre o código contido
nessa classe. Por enquanto, vamos aprender a utilizá-la, sendo assim, faça as
seguintes alterações no código e leia os comentários com atenção, pois as
explicações estão no código.
package com.example.helloligacao
import android.Manifest
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
btTeste.setOnClickListener {
val intent = Intent(Intent.ACTION_CALL,
Uri.parse("tel:987654321"))
startActivity(intent)
}
if(!ok) {
// Se o usuário ainda não aceitou a permissão ou se ele
foi negada...
// Deixa o botão Invisível
btTeste.visibility = View.INVISIBLE
}
}
val ok = PermissionUtils.request(this,
arrayOf(Manifest.permission.CALL_PHONE))
btTeste.visibility = View.INVISIBLE
Figura 12 – Permissão
Crédito: Khuruzero/Shutterstock.
Quando o usuário responder, o método onRequestPermissionsResult()
é chamado para validar as permissões, algo que estamos fazendo com esta linha
de código:
btTeste.visibility = View.VISIBLE
Para finalizar nossos estudos sobre uma intent, vamos fechar com chave
de ouro e tirar uma foto com a câmera pelo aplicativo. Da mesma maneira que
abrimos o browser e o Google Maps e depois também fizemos uma ligação,
podemos usar uma intent para abrir o aplicativo da câmera. A diferença é que o
aplicativo da câmera vai nos retornar a foto que foi tirada pelo usuário, portanto,
temos que aguardar esse retorno.
Atenção: este exemplo é mais complexo e vai exigir mais de você. Nele,
vamos revisar quase tudo o que já aprendemos, portanto, leve o tempo que
precisar para estudar o código com calma.
Para esta brincadeira, vamos criar um novo projeto chamado
HelloCamera, da mesma forma que fizemos nos exemplos anteriores. Altere o
layout da activity para ter um botão na parte superior, e uma imagem logo abaixo.
O objetivo é clicar o botão para tirar a foto e depois mostrá-la no ImageView.
● activity_main.xml
<ImageButton
android:id="@+id/btAbrirCamera"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_menu_camera"
android:text="Abrir a Câmera" />
<ImageView
android:id="@+id/imgFoto"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="1" />
</LinearLayout>
package com.example.hellocamera
import android.Manifest
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File
btAbrirCamera.setOnClickListener {
onClickCamera()
}
if (savedInstanceState != null) {
// (*2*) Se girou a tela recupera o estado
file = savedInstanceState.getSerializable("file")
as File
showImage(file)
}
val ok = PermissionUtils.request(this,
arrayOf(Manifest.permission.CAMERA))
● AndroidManifest.xml
<application >
. . .
</application>
</manifest>
● ImageUtils.kt
package com.example.hellocamera
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import java.io.File
object ImageUtils {
// Faz o resize da imagem
fun resize(file: File, reqWidth: Int, reqHeight: Int):
Bitmap {
// Verifica as dimensões do arquivo
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(file.absolutePath, options)
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options,
reqWidth, reqHeight)
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false
return BitmapFactory.decodeFile(file.absolutePath,
options)
}
// Calcula o fator de escala
fun calculateInSampleSize(options: BitmapFactory.Options,
reqWidth: Int, reqHeight: Int):
Int {
// Raw height and width of image
val height = options.outHeight
val width = options.outWidth
var inSampleSize = 1
if (height > reqHeight || width > reqWidth) {
val halfHeight = height / 2
val halfWidth = width / 2
while
(halfHeight / inSampleSize >= reqHeight &&
halfWidth / inSampleSize >= reqWidth) {
inSampleSize *= 2
}
}
return inSampleSize
}
}
1
Disponível em: <https://developer.android.com/training/camera/photobasics>. Acesso em: 22
jan. 2021.
parâmetro o caminho de um arquivo para que a foto seja salva. Esse arquivo
ficará numa pasta privada do nosso aplicativo:
/storage/emulated/0/Android/data/com.example.hellocamera/files/Pictur
es/foto.jpg
● /res/xml/provider_paths.xml
Figura 13 – Pastas
<application . . . >
<activity android:name=".MainActivity" . . . >
</application>
</manifest>
Figura 14 – Permissão
Crédito: khuruzero/Shutterstock.
Essa parte do código é exatamente igual ao exemplo anterior que fizemos
e não iremos explicá-la, portanto, revise o código com atenção.
Ao clicar no botão para tirar uma foto, o método onClickCamera() é
chamado. Nele, veja que criamos o arquivo no qual queremos que a foto seja
salva. Logo depois, é criada uma intent com ação
MediaStore.ACTION_IMAGE_CAPTURE, que será interceptada pela câmera.
Você verá no código que ao criar a intente, é usado o parâmetro
MediaStore.EXTRA_OUTPUT para informar o caminho do arquivo que a
câmera vai receber como argumento.
Feito isso, a câmera será chamada e você poderá tirar uma foto, conforme
mostra a figura. Observação: o emulador possui um bug em que, na primeira
vez, a foto não funciona. Se isso acontecer, clique no botão voltar para fechar a
câmera e tente novamente.
Figura 15 – Câmera
Crédito: khuruzero/Shutterstock.
Figura 16 – Foto
Crédito: khuruzero/Shutterstock.
Crédito: khuruzero/Shutterstock.
FINALIZANDO