Mostrar Activity De Chamada Com Tela Bloqueada No Android
E aí, pessoal! Tudo bem com vocês? Se você está desenvolvendo um app de vídeo e voz e precisa mostrar uma Activity de chamada mesmo quando o dispositivo Android está bloqueado e com a tela desligada, você veio ao lugar certo! Essa é uma situação comum em aplicativos de comunicação, e vamos explorar juntos como resolver esse desafio. Usando o Firebase Cloud Messaging (FCM) como ponto de partida, vamos mergulhar nas soluções e mostrar o passo a passo para você implementar essa funcionalidade de forma eficiente e elegante.
O Desafio de Exibir uma Activity com a Tela Bloqueada
Mostrar uma Activity de chamada com a tela bloqueada é um desafio interessante no desenvolvimento Android. Por padrão, o sistema operacional Android tem mecanismos de segurança que impedem que aplicativos iniciem Activities diretamente quando o dispositivo está bloqueado ou com a tela desligada. Isso é para evitar comportamentos indesejados e garantir a privacidade do usuário. No entanto, em apps de comunicação, como o seu de vídeo e voz, é crucial que a notificação de chamada seja exibida imediatamente, mesmo nessas condições.
Para contornar essa restrição, precisamos usar alguns recursos e técnicas específicas do Android. O objetivo é garantir que a Activity de chamada seja exibida assim que o usuário receber uma notificação de chamada, proporcionando uma experiência de usuário fluida e intuitiva. Vamos explorar as principais abordagens e os passos necessários para implementar essa funcionalidade no seu aplicativo.
Usando o Firebase Cloud Messaging (FCM)
O Firebase Cloud Messaging (FCM) é uma ferramenta poderosa para enviar notificações push para dispositivos Android. Se você já está utilizando o FCM no seu aplicativo, ótimo! Isso facilita bastante o processo. O FCM permite enviar mensagens para dispositivos específicos ou para grupos de dispositivos, o que é perfeito para notificações de chamadas.
A ideia é que, quando um usuário tenta ligar para outro, o servidor do seu aplicativo envie uma mensagem FCM para o dispositivo do destinatário. Essa mensagem irá conter informações sobre a chamada, como o ID do chamador, o tipo de chamada (vídeo ou voz) e outras informações relevantes. Ao receber essa mensagem, o aplicativo no dispositivo do destinatário irá exibir a Activity de chamada.
Configurando o FCM no seu Projeto
Se você ainda não configurou o FCM no seu projeto, não se preocupe! É um processo relativamente simples. Primeiro, você precisa criar um projeto no Firebase Console (https://console.firebase.google.com/) e adicionar seu aplicativo Android a esse projeto. O Firebase irá gerar um arquivo google-services.json
que você precisa adicionar à pasta app/
do seu projeto Android.
Em seguida, adicione as dependências do FCM ao seu arquivo build.gradle (Module: app)
:
implementation 'com.google.firebase:firebase-messaging:23.0.0'
(Lembre-se de verificar a versão mais recente no site do Firebase e substituir 23.0.0
pela versão atual.)
Após adicionar as dependências, você precisa sincronizar o Gradle para que as bibliotecas sejam baixadas e adicionadas ao seu projeto. Com o FCM configurado, podemos passar para a próxima etapa: criar o serviço de recebimento de mensagens.
Criando um Serviço para Receber Mensagens FCM
Para receber mensagens FCM, você precisa criar um serviço (um Service
do Android) que estenda a classe FirebaseMessagingService
. Esse serviço será responsável por lidar com as mensagens recebidas do FCM. Crie uma nova classe no seu projeto, por exemplo, MyFirebaseMessagingService
, e faça com que ela estenda FirebaseMessagingService
:
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Lógica para lidar com a mensagem recebida
}
@Override
public void onNewToken(String token) {
// Lógica para lidar com o novo token FCM
}
}
O método onMessageReceived
é chamado sempre que uma nova mensagem FCM é recebida. É aqui que você irá implementar a lógica para exibir a Activity de chamada. O método onNewToken
é chamado quando um novo token FCM é gerado para o dispositivo. Você pode usar esse token para enviar mensagens direcionadas a dispositivos específicos.
Implementando a Lógica para Exibir a Activity de Chamada
Dentro do método onMessageReceived
, você precisa extrair as informações da mensagem FCM e usar essas informações para exibir a Activity de chamada. Aqui está um exemplo de como você pode fazer isso:
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getData().size() > 0) {
String callerId = remoteMessage.getData().get("callerId");
String callType = remoteMessage.getData().get("callType");
// Lógica para exibir a Activity de chamada
showCallActivity(callerId, callType);
}
}
Neste exemplo, estamos extraindo o callerId
e o callType
da mensagem FCM. Esses são apenas exemplos, e você pode adicionar outros dados relevantes para a sua aplicação. Em seguida, chamamos o método showCallActivity
para exibir a Activity de chamada. Vamos implementar esse método agora.
Exibindo a Activity de Chamada com a Tela Bloqueada
Para exibir a Activity de chamada mesmo com a tela bloqueada, precisamos usar algumas flags específicas na Intent
que inicia a Activity. Aqui está um exemplo de como você pode implementar o método showCallActivity
:
private void showCallActivity(String callerId, String callType) {
Intent intent = new Intent(this, CallActivity.class);
intent.putExtra("callerId", callerId);
intent.putExtra("callType", callType);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_SINGLE_TOP |
Intent.FLAG_ACTIVITY_CLEAR_TOP |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "call_channel")
.setSmallIcon(R.drawable.ic_call)
.setContentTitle("Chamada Recebida")
.setContentText("Chamada de " + callerId)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setContentIntent(pendingIntent)
.setAutoCancel(true) // Dismiss the notification when the user taps it
.setFullScreenIntent(pendingIntent, true); // Show as heads-up notification
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("call_channel",
"Call Channel",
NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0, builder.build());
}
Vamos analisar o que está acontecendo neste código:
- Criamos uma Intent para a
CallActivity
e adicionamos as informações da chamada como extras. - Adicionamos flags importantes à Intent:
Intent.FLAG_ACTIVITY_NEW_TASK
: Inicia a Activity em uma nova tarefa.Intent.FLAG_ACTIVITY_SINGLE_TOP
: Se a Activity já estiver em execução no topo da pilha, ela não será reiniciada.Intent.FLAG_ACTIVITY_CLEAR_TOP
: Se a Activity já estiver em execução na pilha, todas as Activities acima dela serão removidas.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
: Permite que a Activity seja exibida mesmo com a tela bloqueada.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
: Dispensa o bloqueio de tela (se seguro) quando a Activity é exibida.
- Criamos um PendingIntent para iniciar a Activity quando a notificação for clicada.
- Criamos uma notificação usando
NotificationCompat.Builder
. Definimos o ícone, título, texto e prioridade da notificação. Também definimos a categoria comoNotificationCompat.CATEGORY_CALL
para que o sistema trate essa notificação como uma chamada. - Usamos
setFullScreenIntent
para exibir a notificação como uma heads-up notification, que aparece no topo da tela mesmo quando o dispositivo está bloqueado. - Criamos um NotificationChannel para dispositivos com Android Oreo (API nível 26) ou superior. Isso é necessário para exibir notificações corretamente nesses dispositivos.
- Finalmente, exibimos a notificação usando
NotificationManagerCompat.notify
.
Com esse código, a Activity de chamada será exibida assim que a notificação for recebida, mesmo com a tela bloqueada. O usuário poderá atender ou rejeitar a chamada diretamente da tela de bloqueio.
Registrando o Serviço no Manifest
Não se esqueça de registrar o serviço no seu arquivo AndroidManifest.xml
:
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
Certifique-se de que o atributo android:exported
está definido como false
, pois este serviço não precisa ser acessado por outros aplicativos. O filtro de intent com a action com.google.firebase.MESSAGING_EVENT
indica que este serviço irá lidar com mensagens FCM.
Lidando com Permissões
Para exibir a Activity de chamada e usar os recursos do sistema, você pode precisar solicitar algumas permissões no seu aplicativo. As permissões mais comuns são:
android.permission.WAKE_LOCK
: Permite que o aplicativo mantenha o dispositivo acordado.android.permission.DISABLE_KEYGUARD
: Permite que o aplicativo desabilite o bloqueio de tela.android.permission.USE_FULL_SCREEN_INTENT
: Necessária para exibir notificações heads-up.android.permission.CALL_PHONE
: Necessária para realizar chamadas telefônicas.
Você pode solicitar essas permissões em tempo de execução usando o ActivityCompat.requestPermissions
. Certifique-se de verificar se o usuário já concedeu a permissão antes de solicitá-la novamente. Aqui está um exemplo de como você pode solicitar a permissão WAKE_LOCK
:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WAKE_LOCK) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WAKE_LOCK}, WAKE_LOCK_PERMISSION_REQUEST_CODE);
}
Lembre-se de lidar com o resultado da solicitação de permissão no método onRequestPermissionsResult
:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == WAKE_LOCK_PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permissão concedida
} else {
// Permissão negada
}
}
}
É importante solicitar as permissões necessárias para garantir que seu aplicativo funcione corretamente e ofereça a melhor experiência de usuário.
Dicas Extras e Boas Práticas
- Teste em diferentes dispositivos: O comportamento das notificações e da exibição de Activities pode variar entre diferentes dispositivos e versões do Android. É importante testar seu aplicativo em uma variedade de dispositivos para garantir que ele funcione corretamente.
- Use um canal de notificação: Como mencionado anteriormente, é fundamental usar um canal de notificação para dispositivos com Android Oreo ou superior. Isso permite que o usuário controle as notificações do seu aplicativo e garante que as notificações de chamada sejam exibidas corretamente.
- Considere o estado do aplicativo: Antes de exibir a Activity de chamada, verifique se o aplicativo está em primeiro plano ou em segundo plano. Se o aplicativo estiver em primeiro plano, você pode exibir a Activity diretamente. Se estiver em segundo plano, você pode exibir uma notificação heads-up.
- Otimize a experiência do usuário: Certifique-se de que a Activity de chamada seja fácil de usar e intuitiva. O usuário deve ser capaz de atender ou rejeitar a chamada com facilidade.
Conclusão
E aí, pessoal! Chegamos ao fim do nosso guia sobre como mostrar uma Activity de chamada com a tela bloqueada no Android. Vimos como usar o Firebase Cloud Messaging (FCM) para enviar notificações de chamada, como criar um serviço para receber essas mensagens e como exibir a Activity de chamada mesmo quando o dispositivo está bloqueado. Também discutimos a importância de lidar com permissões e fornecemos algumas dicas extras para otimizar a experiência do usuário.
Espero que este guia tenha sido útil e que você consiga implementar essa funcionalidade no seu aplicativo de vídeo e voz. Se você tiver alguma dúvida ou precisar de ajuda, não hesite em perguntar! E lembre-se, o desenvolvimento Android pode ser desafiador, mas com as ferramentas e técnicas certas, você pode criar aplicativos incríveis.
Até a próxima e bons estudos! 😉