Intenção ACTION_IMAGE_CAPTURE Android

votos
148

Nós estamos tentando usar o aplicativo da câmera nativa que permite ao usuário tirar uma nova foto. Ele funciona muito bem se deixar de fora o EXTRA_OUTPUT extrae retorna a imagem Bitmap pequeno. No entanto, se putExtra(EXTRA_OUTPUT,...)na intenção antes de iniciá-lo, tudo funciona até que você tentar acertar o botão Ok no aplicativo da câmera. O botão Ok apenas não faz nada. O aplicativo da câmera permanece aberto e nada trava. Podemos cancelar fora dele, mas o arquivo não é escrita. O que exatamente é que temos de fazer para conseguir ACTION_IMAGE_CAPTUREescrever a foto tirada em um arquivo?

Edit: Isto é feito através da MediaStore.ACTION_IMAGE_CAPTUREintenção, só para ficar claro

Publicado 15/12/2009 em 22:41
fonte usuário
Em outras línguas...                            


14 respostas

votos
137

este é um bug bem documentado em algumas versões do Android. isto é, no google experiência versões do android, captura de imagem não funciona conforme documentado. o que eu tenho usado geralmente é algo como isto em uma classe 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 eu lançar captura de imagem, eu criar uma intenção que verifica a 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);

em seguida, em atividade que eu retornar, eu 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-lhe ter que escrever um novo aplicativo da câmera, mas este código não é grande também. os grandes problemas são

  1. você nunca obter imagens de tamanho completo dos dispositivos com o bug. você tem imagens que são 512px de largura, que são inseridos no provedor de conteúdo da imagem. em dispositivos sem o erro, tudo funciona como documento, você recebe uma imagem normal grande.

  2. você tem que manter a lista. como está escrito, é possível que os dispositivos sejam brilharam com uma versão do Android (dizem CyanogenMod da constrói ), que tem o bug corrigido. se isso acontecer, seu código irá falhar. a correção é usar toda a impressão digital dispositivo.

Respondeu 19/12/2009 em 08:35
fonte usuário

votos
50

Eu sei que isto tem sido respondida antes, mas eu conheço um monte de pessoas tropeçar sobre isso, então eu estou indo para adicionar um comentário.

Eu tinha exatamente o mesmo problema acontecer no meu Nexus One. Esta foi a partir do arquivo não existente no disco antes de o aplicativo da câmera começou. Portanto, tenho a certeza que o arquivo existente antes de iniciado o aplicativo da câmera. Aqui está um código de exemplo que eu usei:

String storageState = Environment.getExternalStorageState();
        if(storageState.equals(Environment.MEDIA_MOUNTED)) {

            String path = Environment.getExternalStorageDirectory().getName() + File.separatorChar + "Android/data/" + MainActivity.this.getPackageName() + "/files/" + md5(upc) + ".jpg";
            _photoFile = new File(path);
            try {
                if(_photoFile.exists() == false) {
                    _photoFile.getParentFile().mkdirs();
                    _photoFile.createNewFile();
                }

            } catch (IOException e) {
                Log.e(TAG, "Could not create file.", e);
            }
            Log.i(TAG, path);

            _fileUri = Uri.fromFile(_photoFile);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE );
            intent.putExtra( MediaStore.EXTRA_OUTPUT, _fileUri);
            startActivityForResult(intent, TAKE_PICTURE);
        }   else {
            new AlertDialog.Builder(MainActivity.this)
            .setMessage("External Storeage (SD Card) is required.\n\nCurrent state: " + storageState)
            .setCancelable(true).create().show();
        }

I primeiro criar uma (um pouco) nome de arquivo exclusivo utilizando um hash MD5 e colocá-lo para a pasta apropriada. Eu, então, verificar para ver se ele existe (não deveria, mas a sua boa prática para verificar de qualquer maneira). Se ele não existir, fico com a dir pai (a pasta) e criar a hierarquia de pastas até ele (portanto, se não existirem as pastas que levam até o local do arquivo, eles vão depois desta linha. Então, depois disso I criar o arquivo. Uma vez que o arquivo é criado recebo o Uri e passá-lo para a intenção e, em seguida, o botão OK funciona como esperado e tudo é de ouro.

Agora, quando o botão OK é pressionado sobre o aplicativo da câmera, o arquivo estará presente no local determinado. Neste exemplo seria /sdcard/Android/data/com.example.myapp/files/234asdioue23498ad.jpg

Não há necessidade de copiar o arquivo no "onActivityResult", como publicado anteriormente.

Respondeu 20/02/2011 em 02:17
fonte usuário

votos
31

Eu já passei por uma série de estratégias de captura de foto, e há sempre parece ser um caso, uma plataforma ou determinados dispositivos, onde algumas ou todas as estratégias acima irá falhar de forma inesperada. Eu era capaz de encontrar uma estratégia que utiliza o código de geração URI abaixo do qual parece funcionar na maioria, se não todos os casos.

mPhotoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
            new ContentValues());
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoUri);
startActivityForResult(intent,CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE_CONTENT_RESOLVER);

Para contribuir ainda mais para a discussão e ajudar os recém-chegados Eu criei um aplicativo de exemplo / teste que mostra várias estratégias diferentes para implementação de captura de foto. Contribuições de outras implementações são definitivamente encorajados a acrescentar à discussão.

https://github.com/deepwinter/AndroidCameraTester

Respondeu 08/05/2013 em 07:14
fonte usuário

votos
29

Eu tive o mesmo problema onde o botão OK no aplicativo da câmera não fez nada, tanto no emulador e no Nexus One.

O problema foi embora depois de especificar um nome de arquivo seguro, que é, sem espaços em branco, sem caracteres especiais, em MediaStore.EXTRA_OUTPUT Além disso, se você está especificando um arquivo que reside em um diretório que ainda não foi criado, você tem que criá-lo primeiro. Aplicativo da câmera não faz mkdir para você.

Respondeu 06/10/2010 em 06:39
fonte usuário

votos
28

O fluxo de trabalho que você descreve deve funcionar como você descreveu. Pode ajudar se você poderia nos mostrar o código em torno da criação da Intenção. Em geral, o seguinte padrão deve deixá-lo fazer o que você está tentando.

private void saveFullImage() {
  Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  File file = new File(Environment.getExternalStorageDirectory(), "test.jpg");
  outputFileUri = Uri.fromFile(file);
  intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
  startActivityForResult(intent, TAKE_PICTURE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if ((requestCode == TAKE_PICTURE) && (resultCode == Activity.RESULT_OK)) {
    // Check if the result includes a thumbnail Bitmap
    if (data == null) {    
      // TODO Do something with the full image stored
      // in outputFileUri. Perhaps copying it to the app folder
    }
  }
}

Note que é a Câmara Atividade que será criar e salvar o arquivo, e não é realmente parte da sua aplicação, por isso não vai ter permissão de gravação para a pasta de aplicativos. Para salvar um arquivo para a pasta de aplicativo, criar um arquivo temporário no cartão SD e movê-lo para a pasta de aplicativo no onActivityResultmanipulador.

Respondeu 15/12/2009 em 22:56
fonte usuário

votos
7

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 pode escrever para o diretório em questão.

Isso significa que você não pode criar o arquivo em um lugar que só gravável pelo seu aplicativo (por exemplo, algo sob getCacheDir())Algo sob getExternalFilesDir()deve trabalhar, no entanto.

Seria bom se o aplicativo da câmera impressa uma mensagem de erro para os logs, se não pôde gravar no especificado EXTRA_OUTPUTcaminho, mas eu não encontrar um.

Respondeu 14/12/2010 em 18:45
fonte usuário

votos
4

para ter a gravação da câmera para sdcard mas tenha em um novo álbum na galeria aplicativo eu uso este:

 File imageDirectory = new File("/sdcard/signifio");
          String path = imageDirectory.toString().toLowerCase();
           String name = imageDirectory.getName().toLowerCase();


            ContentValues values = new ContentValues(); 
            values.put(Media.TITLE, "Image"); 
            values.put(Images.Media.BUCKET_ID, path.hashCode());
            values.put(Images.Media.BUCKET_DISPLAY_NAME,name);

            values.put(Images.Media.MIME_TYPE, "image/jpeg");
            values.put(Media.DESCRIPTION, "Image capture by camera");
           values.put("_data", "/sdcard/signifio/1111.jpg");
         uri = getContentResolver().insert( Media.EXTERNAL_CONTENT_URI , values);
            Intent i = new Intent("android.media.action.IMAGE_CAPTURE"); 

            i.putExtra(MediaStore.EXTRA_OUTPUT, uri);

            startActivityForResult(i, 0); 

Por favor, note que você vai precisar para gerar um nome de arquivo exclusivo de cada vez e substituir teh 1111.jpg que eu escrevi. Isto foi testado com um nexo. o URI é declarado na classe privada, etc. resultado de atividade eu sou capaz de carregar a imagem do uri para imageView para visualização, se necessário.

Respondeu 29/06/2010 em 09:01
fonte usuário

votos
2

Eu recomendo que você siga o post trainning android para capturar uma foto. Eles mostram em um exemplo de como tirar pequenas e grandes fotos. Você também pode baixar o código fonte a partir daqui

Respondeu 27/06/2012 em 09:53
fonte usuário

votos
1

É muito simples de resolver este problema com o resultado de atividade Código Simples tentar este método

if (reqCode == RECORD_VIDEO) {
   if(resCode == RESULT_OK) {
       if (uri != null) {
           compress();
       }
    } else if(resCode == RESULT_CANCELED && data!=null){
       Toast.makeText(MainActivity.this,"No Video Recorded",Toast.LENGTH_SHORT).show();
   }
}
Respondeu 01/05/2016 em 13:51
fonte usuário

votos
1

Eu tive o mesmo problema e eu fixa-lo com o seguinte:

O problema é que quando você especificar um arquivo que só o seu aplicativo tem acesso a (por exemplo, chamando getFileStreamPath("file");)

É por isso que eu só a certeza que o arquivo dado realmente existe e que todos tenham acesso de escrita a ele.

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File outFile = getFileStreamPath(Config.IMAGE_FILENAME);
outFile.createNewFile();
outFile.setWritable(true, false);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT,Uri.fromFile(outFile));
startActivityForResult(intent, 2);

Desta forma, o aplicativo da câmera tem acesso de gravação para um determinado Uri eo botão OK funciona bem :)

Respondeu 28/03/2011 em 17:08
fonte usuário

votos
0
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_CANCELED)
    {
        //do not process data, I use return; to resume activity calling camera intent
        enter code here
    }
}
Respondeu 20/06/2017 em 09:44
fonte usuário

votos
0

Você pode usar este código

private Intent getCameraIntent() {

    PackageManager packageManager = mContext.getPackageManager();
    List<ApplicationInfo> list = packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
    Intent main = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    List<ResolveInfo> launchables = packageManager.queryIntentActivities(main, 0);
    if (launchables.size() == 1)
        return packageManager.getLaunchIntentForPackage(launchables.get(0).activityInfo.packageName);
    else
        for (int n = 0; n < list.size(); n++) {
            if ((list.get(n).flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
                Log.d("TAG", "Installed Applications  : " + list.get(n).loadLabel(packageManager).toString());
                Log.d("TAG", "package name  : " + list.get(n).packageName);
                String defaultCameraPackage = list.get(n).packageName;


                if (launchables.size() > 1)
                    for (int i = 0; i < launchables.size(); i++) {
                        if (defaultCameraPackage.equals(launchables.get(i).activityInfo.packageName)) {
                            return packageManager.getLaunchIntentForPackage(defaultCameraPackage);
                        }
                    }
            }
        }
    return null;
}
Respondeu 21/10/2015 em 04:18
fonte usuário

votos
0

As necessidades de arquivo ser gravável pela câmara, como Praveen apontou.

Em meu uso eu queria armazenar o arquivo no armazenamento interno. Eu fiz isso com:

Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (i.resolveActivity(getPackageManager()!=null)){
    try{
        cacheFile = createTempFile("img",".jpg",getCacheDir());
        cacheFile.setWritavle(true,false);
    }catch(IOException e){}
    if(cacheFile != null){
        i.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(cacheFile));
        startActivityForResult(i,REQUEST_IMAGE_CAPTURE);
    }
}

Aqui cacheFileé um arquivo global usada para se referir ao arquivo que está escrito. Em seguida, no método resultado a intenção retornado é nulo. Em seguida, o método para processar a intenção parece:

protected void onActivityResult(int requestCode,int resultCode,Intent data){
    if(requestCode != RESULT_OK){
        return;
    }
    if(requestCode == REQUEST_IMAGE_CAPTURE){
        try{
            File output = getImageFile();
            if(output != null && cacheFile != null){
                copyFile(cacheFile,output);

                //Process image file stored at output

                cacheFile.delete();
                cacheFile=null;
            }
        }catch(IOException e){}
    }
}

Aqui getImageFile()é um método de utilitário para nomear e criar o arquivo em que a imagem deve ser armazenado, e copyFile()é um método para copiar um arquivo.

Respondeu 16/06/2014 em 16:37
fonte usuário

votos
0

Eu criei biblioteca simples que irá gerir a escolha de imagens de diferentes fontes (galeria, na câmara), talvez salvá-lo para algum local (SD-Card ou na memória interna) e retornar a imagem de volta por favor livre usá-lo e melhorá-lo - Android-ImageChooser .

Respondeu 24/11/2012 em 20:20
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more