Este é um bug bem documentado em algumas versões do Android. isto é, na experiência do Google com o Android, a captura de imagens não funciona conforme documentado. o que eu geralmente usei é algo assim em uma classe de utilitários.
public boolean hasImageCaptureBug() {
// list of known devices that have the bug
ArrayList<String> devices = new ArrayList<String>();
devices.add("android-devphone1/dream_devphone/dream");
devices.add("generic/sdk/generic");
devices.add("vodafone/vfpioneer/sapphire");
devices.add("tmobile/kila/dream");
devices.add("verizon/voles/sholes");
devices.add("google_ion/google_ion/sapphire");
return devices.contains(android.os.Build.BRAND + "/" + android.os.Build.PRODUCT + "/"
+ android.os.Build.DEVICE);
}
então, quando inicio a captura de imagem, crio uma intenção que verifica o bug.
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (hasImageCaptureBug()) {
i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/tmp")));
} else {
i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
startActivityForResult(i, mRequestCode);
depois, nas atividades em que retorno, faço coisas diferentes com base no dispositivo.
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch (requestCode) {
case GlobalConstants.IMAGE_CAPTURE:
Uri u;
if (hasImageCaptureBug()) {
File fi = new File("/sdcard/tmp");
try {
u = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), fi.getAbsolutePath(), null, null));
if (!fi.delete()) {
Log.i("logMarker", "Failed to delete " + fi);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
u = intent.getData();
}
}
isso poupa a necessidade de escrever um novo aplicativo de câmera, mas esse código também não é ótimo. os grandes problemas são
você nunca obtém imagens em tamanho real dos dispositivos com o bug. você obtém fotos com 512px de largura inseridas no provedor de conteúdo de imagens. em dispositivos sem o bug, tudo funciona como documento, você obtém uma imagem normal grande.
você tem que manter a lista. como está escrito, é possível que os dispositivos sejam atualizados com uma versão do android (digamos , compilações do cyanogenmod ) que tenha o bug corrigido. se isso acontecer, seu código falhará. a correção é usar toda a impressão digital do dispositivo.
Sei que isso já foi respondido antes, mas sei que muitas pessoas se incomodam com isso, então vou adicionar um comentário.
Eu tive exatamente o mesmo problema no meu Nexus One. Era do arquivo que não existia no disco antes do aplicativo da câmera ser iniciado. Portanto, verifiquei se o arquivo existente antes iniciava o aplicativo da câmera. Aqui está um código de exemplo que eu usei:
Primeiro, crio um nome de arquivo único (um pouco) usando um hash MD5 e o coloco na pasta apropriada. Depois, verifico se ele existe (não deveria, mas é uma boa prática verificar de qualquer maneira). Se ele não existir, eu obtenho o diretório pai (uma pasta) e crio a hierarquia de pastas até ele (portanto, se as pastas que antecedem o local do arquivo não existirem, elas seguirão esta linha. Eu crio o arquivo.Quando o arquivo é criado, pego o Uri e o passo para a intenção e, em seguida, o botão OK funciona como esperado e tudo fica dourado.
Agora, quando o botão OK for pressionado no aplicativo da câmera, o arquivo estará presente no local especificado. Neste exemplo, seria /sdcard/Android/data/com.example.myapp/files/234asdioue23498ad.jpg
Não há necessidade de copiar o arquivo no "onActivityResult", conforme publicado acima.
fonte
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
no seu manifesto se estiver usando o Android 1.5 mais recente - passei algumas horas depurando o material da câmera e isso não foi incluído, para que minhas proteções sempre falhem.Passei por várias estratégias de captura de fotos e sempre parece haver um caso, uma plataforma ou certos dispositivos, em que algumas ou todas as estratégias acima falham de maneiras inesperadas. Consegui encontrar uma estratégia que usa o código de geração de URI abaixo, que parece funcionar na maioria, se não em todos os casos.
Para contribuir ainda mais com a discussão e ajudar os recém-chegados, criei um aplicativo de amostra / teste que mostra várias estratégias diferentes para a implementação da captura de fotos. Contribuições de outras implementações são definitivamente encorajadas a adicionar à discussão.
https://github.com/deepwinter/AndroidCameraTester
fonte
onActivityResult
ou preciso mesmo me lembrar? Eu teria que persistantly salvá-lo para que meu aplicativo ainda se lembra-lo se ele é destruído, enquanto uma foto é tirada ...Eu tive o mesmo problema em que o botão OK no aplicativo da câmera não fez nada, tanto no emulador quanto no nexus one.
O problema foi resolvido após a especificação de um nome de arquivo seguro, sem espaços em branco, sem caracteres especiais, em
MediaStore.EXTRA_OUTPUT
Além disso, se você estiver especificando um arquivo que reside em um diretório que ainda não foi criado, será necessário criá-lo primeiro. O aplicativo da câmera não faz mkdir para você.fonte
mkdirs()
vez demkdir()
se o seu caminho tiver mais de um nível de diretório e desejar que todos eles sejam criados (mkdir
apenas cria o último, o diretório 'leaf'). Eu tive alguns problemas com isso, e essa resposta me ajudou.O fluxo de trabalho que você descreve deve funcionar como você o descreveu. Pode ajudar se você puder nos mostrar o código em torno da criação do Intent. Em geral, o padrão a seguir deve permitir que você faça o que está tentando.
Observe que é a Atividade da câmera que criará e salvará o arquivo e, na verdade, não faz parte do seu aplicativo, portanto, não haverá permissão de gravação na pasta do aplicativo. Para salvar um arquivo na pasta do aplicativo, crie um arquivo temporário no cartão SD e mova-o para a pasta do aplicativo no
onActivityResult
manipulador.fonte
Para acompanhar o comentário de Yenchi acima, o botão OK também não fará nada se o aplicativo da câmera não puder gravar no diretório em questão.
Isso significa que você não pode criar o arquivo em um local que possa ser gravado apenas pelo seu aplicativo (por exemplo, algo em
getCacheDir())
Algo sobgetExternalFilesDir()
deve funcionar, no entanto.Seria bom se o aplicativo da câmera imprimisse uma mensagem de erro nos logs se não pudesse gravar no
EXTRA_OUTPUT
caminho especificado , mas não encontrei uma.fonte
para que a câmera grave no sdcard, mas mantenha um novo álbum no aplicativo da galeria, eu uso o seguinte:
Observe que você sempre precisará gerar um nome de arquivo exclusivo e substituir o 1111.jpg que escrevi. Isso foi testado com o nexus one. o uri é declarado na classe privada, portanto, no resultado da atividade, sou capaz de carregar a imagem do uri no imageView para visualização, se necessário.
fonte
Eu tive o mesmo problema e o corrigi com o seguinte:
O problema é que, quando você especifica um arquivo ao qual somente seu aplicativo tem acesso (por exemplo, ligando
getFileStreamPath("file");
)É por isso que eu apenas certifiquei-me de que o arquivo fornecido realmente exista e que TODOS tenham acesso de gravação a ele.
Dessa forma, o aplicativo da câmera tem acesso de gravação ao Uri fornecido e o botão OK funciona bem :)
fonte
Eu recomendo que você siga o post de treinamento do Android para capturar uma foto. Eles mostram em um exemplo como tirar fotos pequenas e grandes. Você também pode baixar o código fonte aqui
fonte
Eu criei uma biblioteca simples que gerenciará a escolha de imagens de diferentes fontes (Galeria, Câmera), talvez salve-a em algum local (cartão SD ou memória interna) e retorne a imagem de volta, então fique à vontade para usá-la e melhorá-la - Android-ImageChooser .
fonte
O arquivo precisa ser gravável pela câmera, como Praveen apontou.
No meu uso, eu queria armazenar o arquivo no armazenamento interno. Eu fiz isso com:
Aqui
cacheFile
está um arquivo global usado para se referir ao arquivo que está gravado. Em seguida, no método de resultado, a intenção retornada é nula. Em seguida, o método para processar a intenção é semelhante a:Aqui
getImageFile()
está um método utilitário para nomear e criar o arquivo no qual a imagem deve ser armazenada ecopyFile()
é um método para copiar um arquivo.fonte
Você pode usar este código
fonte
É muito simples resolver este problema com o Código de Resultado da Atividade Simples, tente este método
fonte
fonte