Como evito que o Android faça uma captura de tela quando meu aplicativo entra em segundo plano?

146

No momento, o aplicativo que estou construindo tem o requisito de impedir que o sistema operacional faça uma captura de tela do aplicativo ao ser colocado em segundo plano por motivos de segurança. Dessa forma, não será possível ver a última tela ativa ao alternar entre aplicativos.

Estou planejando colocar essa funcionalidade no método onPause da classe de aplicativo, mas primeiro preciso descobrir como posso obter essa funcionalidade.

Então, existe alguém lá fora, que tem uma pista de como consertar isso?

StingRay5
fonte

Respostas:

264

Tente FLAG_SECURE:

public class FlagSecureTestActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
                         WindowManager.LayoutParams.FLAG_SECURE);

    setContentView(R.layout.main);
  }
}

Isso definitivamente protege contra capturas de tela manuais e capturas de tela automáticas do histórico de tarefas recentes do ICS. Também protege contra gravação de tela (por exemplo, aplicativos que usam as APIs de projeção de mídia).

UPDATE : também protege contra o Now On Tap ou outros assistentes no Android 6.0; eles não terão acesso aos detalhes de widgets e contêineres na sua interface do usuário se o usuário chamar o assistente.

ATUALIZAÇÃO # 2 : no entanto, nem tudo na atividade será protegido. Todas as janelas pop-up - Dialog, Spinner, AutoCompleteTextView, ação bar estouro, etc. - vai ser inseguro. Você pode corrigir o Dialogproblema chamando getWindow()-o e definindo FLAG_SECURE. O resto ... fica complicado. Veja esta postagem do blog para obter mais informações.

CommonsWare
fonte
6
@ Dany's: Na verdade, tem tudo a ver com a questão. Acabei de o testar no Nexus S (4.0.3) e funciona como esperado - a captura de tela de tarefas recentes é suprimida. Você ainda vê o nome e o ícone do aplicativo, mas a captura de tela é preta. Você pode experimentá-lo no hardware do ICS.
CommonsWare
2
@ StingRay5: FLAG_SECUREexiste desde o início - só tinha um significado limitado até recentemente.
CommonsWare
1
Interessante notar que existe um método chamado onCreateThumbnail no ciclo de vida da atividade, mas nunca é usado.
Snicolas 8/08/12
2
@PankajKumar: Se o "código para captura de tela" que você escreveu é o truque clássico "pegue o framebuffer como root", FLAG_SECUREnão se defenderá disso, pois é um nível muito baixo. Da mesma forma, se você adotou sua própria hierarquia de widgets e a Bitmapchamou para um back - back Canvas, FLAG_SECUREprovavelmente não se defenderá disso, pois você está fazendo suas próprias capturas de tela de seus widgets e, portanto, presumivelmente queria as "seguras" lá. FLAG_SECUREé para capturas de tela do sistema , como as miniaturas de tarefas recentes.
CommonsWare
2
Resposta maravilhosa e simples! Gostaria de saber por que aplicativos como o snapchat não usam isso para impedir que alguém tire uma captura de tela das imagens enviadas.
Shobhit Puri
78

Cuidado ao usar o WindowManager.LayoutParams.FLAG_SECURE, em alguns dispositivos (verificado no Samsung Galaxy ACE, por exemplo, GT-S5830), isso fará com que a exibição seja embaralhada. Parece um bug específico da Samsung. Eu recomendo o seguinte:

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}

É assim que uma tela embaralhada se parece:

Imagem de Tela Mexida

Porém, ele está funcionando corretamente nos telefones ICS Samsung, então estou assumindo que o problema está isolado nos dispositivos Gingerbread (ou mais antigos).

Gardarh
fonte
8
Você está totalmente certo, nos deparamos com esse problema e certamente era necessário verificar o nível da API. Na verdade, esqueci de postar isso, então obrigado por trazê-lo novamente. :)
StingRay5
Também ocorre no Samsung Gio (Gingerbread), mas em Froyo sua ok - por isso ocorre apenas em 2.3
pixel de
Percebemos esse problema também. Você pode verificar no emulador em dispositivos Gingerbread.
Twaddington
Também posso confirmar que esse problema aparece nos dispositivos Samsung Gingerbread.
Ernir Erlingsson
7
Mesmo nas versões mais recentes do Android FLAG_SECURE pode ser problemático: no Android 4.3 FLAG_SECURE causa problemas de animação na animação de rotação da tela, consulte code.google.com/p/android/issues/detail?id=58632 - isso foi corrigido no Android 4.4
Oliver
13

A solução fornecida pelo CommonsWare continua válida também no Lollipop.

Apenas uma observação, se você quiser continuar a não ver instantâneos na lista recente de todo o aplicativo, TODAS as atividades implementadas devem especificar no onCreate()método o sinalizador getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); antessetContentView();

Caso contrário, um instantâneo na lista recente mostrará a primeira atividade sem o sinalizador se o usuário navegar nele.

Davideas
fonte
1
No meu aplicativo, tenho a funcionalidade de definir / limpar FLAG_SECURE com base na preferência do usuário. Funcionou bem até que KITKAT e tela preta podem ser vistos no alternador de tarefas. No Lollipop, a Visão geral exibe o último instantâneo do meu aplicativo, o horário em que FLAG_SECURE não foi definido (limpo).
precisa saber é o seguinte
@ r.bhardwaj acho que não podemos fazer muito nesse caso, mas você pode aconselhar o usuário que, a alteração precisa que o App seja reiniciado para entrar em vigor ;-) e pronto.
Davideas 17/10/2015
1
Alguém encontrou uma maneira de aumentar uma exibição personalizada antes de tirar o instantâneo, para que não seja apenas uma tela preta? Tentei aumentar a exibição do gerenciador de janelas no onPause, mas parece que é tarde demais.
user1064249
Olá @ user1064249 Encontrou alguma solução? Eu quero inflar o Ver Lançador antes do OS tomar captura de tela
Alexiscanny
1

Aqui está uma solução para ocultar o conteúdo de um aplicativo, cobrindo-o com uma tela inicial quando o aplicativo é colocado em segundo plano. Isso não está usando a técnica FLAG_SECURE, simplesmente substituo os métodos onPause e onResume das telas e modifico a visualização para mostrar uma que cubra tudo na parte de trás.

https://stackoverflow.com/a/52976001/6686912

D. Maul
fonte
0
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
            WindowManager.LayoutParams.FLAG_SECURE);

isso funcionou para mim, impede a captura de tela e também qualquer aplicativo de gravação embutido ou de terceiros na tela de gravação.

Harsh Barnwal
fonte
0

Isso é um trabalho para mim depois de adicionar essas linhas ao onCreate antes de setContentView de cada atividade.

getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,     
WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.activity_notification);
Arun Prajapati
fonte