Android – Как сделать снимок с камеры или галереи

Я хотел бы попросить пользователя сделать снимок либо с камеры, либо с существующих изображений в устройстве (галерея или что-то еще). Как я могу это сделать?

Я выполнил нижеприведенное решение, которое, кажется, работает нормально, но документация довольно запутанна, поэтому я хотел бы знать, есть ли лучшие решения.

Кроме того, ознакомьтесь с этой связанной записью. Там вы увидите, как получить путь к изображению или растровое изображение: получить / выбрать изображение из встроенного приложения Gallery от Google

Таким образом, в моем решении вы создали бы объект TakePictureHelper и выполните следующее.

Предположим, вы показываете диалог, в котором пользователь может выбрать «камеру» или «другую». Когда пользователь выбирает опцию, вы вызываете либо takeFromCamera() либо takeFromOther() . Когда снимок сделан (или нет), onActivityResult() метод onActivityResult() . Там вы можете вызвать retrievePicture , который вернет Uri изображения или null, если изображение не было снято.

Пожалуйста, дайте мне знать, что вы думаете, поделитесь идеями или спросите меня, если я не буду ясно.

Большое спасибо!

 import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; public class TakePictureHelper { public final static int REQUEST_CAMERA = 1; public final static int REQUEST_OTHER = 2; private Uri cameraImageUri; /** * Request picture from camera using the given title */ public void takeFromCamera(Activity activity, String title) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File cameraImageOutputFile = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), createCameraImageFileName()); cameraImageUri = Uri.fromFile(cameraImageOutputFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri); activity.startActivityForResult(Intent.createChooser(intent, title), REQUEST_CAMERA); } /** * Request picture from any app (gallery or whatever) using the given title */ public void takeFromOther(Activity activity, String title) { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); activity.startActivityForResult(Intent.createChooser(intent, title), REQUEST_OTHER); } /** * Retrieve the picture, taken from camera or gallery. * * @return the picture Uri, or null if no picture was taken. */ public Uri retrievePicture(Activity activity, int requestCode, int resultCode, Intent data) { Uri result = null; if (resultCode == Activity.RESULT_OK) { if (requestCode == REQUEST_OTHER) { result = data.getData(); } else if (requestCode == REQUEST_CAMERA) { result = cameraImageUri; } } return result; } private String createCameraImageFileName() { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); return timeStamp + ".jpg"; } } 

Основанный на ответе @ yurezcv, вот что я придумал (самое главное, как получить изображение в onActivityResult):

 private List<File> cameraImageFiles; private void popImageChooser(){ // Camera. final List<Intent> cameraIntents = new ArrayList<Intent>(); final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); final PackageManager packageManager = getPackageManager(); final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0); cameraImageFiles = new ArrayList<File>(); int i=0; for(ResolveInfo res : listCam) { final String packageName = res.activityInfo.packageName; final Intent intent = new Intent(captureIntent); intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name)); intent.setPackage(packageName); intent.putExtra(MediaStore.MEDIA_IGNORE_FILENAME, ".nomedia"); File cameraImageOutputFile = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), createCameraImageFileName()); cameraImageFiles.add(cameraImageOutputFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraImageFiles.get(i))); i++; cameraIntents.add(intent); } // Filesystem. final Intent galleryIntent = new Intent(); galleryIntent.setType("image/*"); galleryIntent.setAction(Intent.ACTION_GET_CONTENT); // Chooser of filesystem options. final Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.attach_images_title)); // Add the camera options. chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{})); startActivityForResult(chooserIntent, ACTIVITY_REQUEST_CODE_IMAGE); } protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { super.onActivityResult(requestCode, resultCode, imageReturnedIntent); switch(requestCode) { case ACTIVITY_REQUEST_CODE_IMAGE: if(resultCode == RESULT_OK){ Uri uri = null; if(imageReturnedIntent == null){ //since we used EXTRA_OUTPUT for camera, so it will be null for(int i=0;i<cameraImageFiles.size();i++){ if(cameraImageFiles.get(i).exists()){ uri = Uri.fromFile(cameraImageFiles.get(i)); break; } } Log.d("attachimage", "from camera: "+uri); } else { // from gallery uri = imageReturnedIntent.getData(); Log.d("attachimage", "from gallery: "+uri.toString()); } if(uri != null){ attachImage(uri); } } } } 

Это решение работает для меня:

 private void addPhoto() { // Camera. final List<Intent> cameraIntents = new ArrayList<Intent>(); final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); final PackageManager packageManager = getPackageManager(); final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0); for(ResolveInfo res : listCam) { final String packageName = res.activityInfo.packageName; final Intent intent = new Intent(captureIntent); intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name)); intent.setPackage(packageName); intent.putExtra(MediaStore.MEDIA_IGNORE_FILENAME, ".nomedia"); cameraIntents.add(intent); } // Filesystem. final Intent galleryIntent = new Intent(); galleryIntent.setType("image/*"); galleryIntent.setAction(Intent.ACTION_GET_CONTENT); // Chooser of filesystem options. final Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.add_new)); // Add the camera options. chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{})); startActivityForResult(chooserIntent, YOUR_REQUEST_CODE); } 

Он создает один диалог цели со всеми возможными вариантами для выбора изображения с камеры, файловой системы и т. Д.

Hay un detalle que no se ha dicho y es que actualmente el tema de la orientación de la cámara es un desastre cuando lo que se hace es guardar la captura y luego leerla de disco para mostrarla. Esto es así porque los fabricantes, como HTC, Samsung и т. Д., Не имеют аналогов в мире. En este caso, puede (y depende del depitivo), ser necesario corrgir la imagen usando la información EXIF ​​de la misma para que no se muestre rotada por ejemplo, en un ImageView.

Si la imagen de la cámara no la guardamos sino que en la vuelta leemos del Bundle los datos guardados en la key "data", la imagen se mostrará bien.

Otra cosa que yo haría si guardamos la foto en disco, es hacer que esta se vea en la galería para que el usuario la pueda ver y borrar directamente (ver MediaScannerConnectionClient)

Yo lo he hecho tal como se ve en el código que pongo abajo. Разрешающ hacerlo bien por la galería ó, tomando una captura con la cámara. ( Para algunas tareas he usado la librería pública en GitHub https://github.com/javocsoft/javocsoft-toolbox/ )

 package com.example.getpicture; import java.io.File; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import es.javocsoft.android.lib.toolbox.ToolBox; import es.javocsoft.android.lib.toolbox.media.MediaScannerNotifier; public class MainActivity extends Activity { private final int PICTURE_TAKEN_FROM_CAMERA = 1; private final int PICTURE_TAKEN_FROM_GALLERY = 2; private Button btncamera = null; private Button btngallery = null; private ImageView pictureZone = null; private boolean storeImage = false; private File outFile = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pictureZone = (ImageView)findViewById(R.id.pictureZone); btncamera = (Button)findViewById(R.id.btncamera); btngallery = (Button)findViewById(R.id.btngallery); addEvents(); } private void addEvents(){ btncamera.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { getPictureFromCamera(); } }); btngallery.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { getPictureFromGallery(); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Bitmap takenPictureData = null; switch(requestCode){ case PICTURE_TAKEN_FROM_CAMERA: if(resultCode==Activity.RESULT_OK) { takenPictureData = handleResultFromCamera(data); } break; case PICTURE_TAKEN_FROM_GALLERY: if(resultCode==Activity.RESULT_OK) { takenPictureData = handleResultFromChooser(data); } break; } //And show the result in the image view. if(takenPictureData!=null){ pictureZone.setImageBitmap(takenPictureData); } } //AUXILIAR private Bitmap handleResultFromChooser(Intent data){ Bitmap takenPictureData = null; Uri photoUri = data.getData(); if (photoUri != null){ try { //We get the file path from the media info returned by the content resolver String[] filePathColumn = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(photoUri, filePathColumn, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String filePath = cursor.getString(columnIndex); cursor.close(); takenPictureData = ToolBox.media_getBitmapFromFile(new File(filePath)); }catch(Exception e){ ToolBox.dialog_showToastAlert(this, "Error getting selected image.", false); } } return takenPictureData; } private Bitmap handleResultFromCamera(Intent data){ Bitmap takenPictureData = null; if(data!=null){ //Android sets the picture in extra data. Bundle extras = data.getExtras(); if(extras!=null && extras.get("data")!=null){ takenPictureData = (Bitmap) extras.get("data"); } }else{ //If we used EXTRA_OUTPUT we do not have the data so we get the image //from the output. try{ takenPictureData = ToolBox.media_getBitmapFromFile(outFile); takenPictureData = ToolBox.media_correctImageOrientation(outFile.getAbsolutePath()); }catch(Exception e){ ToolBox.dialog_showToastAlert(this, "Error getting saved taken picture.", false); } } if(storeImage){ //We add the taken picture file to the gallery so user can see the image directly new MediaScannerNotifier(this,outFile.getAbsolutePath(),"image/*", false); } return takenPictureData; } private void getPictureFromCamera(){ boolean cameraAvailable = ToolBox.device_isHardwareFeatureAvailable(this, PackageManager.FEATURE_CAMERA); if(cameraAvailable && ToolBox.system_isIntentAvailable(this, MediaStore.ACTION_IMAGE_CAPTURE)){ Intent takePicIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //We prepare the intent to store the taken picture try{ File outputDir = ToolBox.storage_getExternalPublicFolder(Environment.DIRECTORY_PICTURES, "testApp", true); outFile = ToolBox.storage_createUniqueFileName("cameraPic", ".jpg", outputDir); takePicIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outFile)); storeImage = true; }catch(Exception e){ ToolBox.dialog_showToastAlert(this, "Error setting output destination.", false); } startActivityForResult(takePicIntent, PICTURE_TAKEN_FROM_CAMERA); }else{ if(cameraAvailable){ ToolBox.dialog_showToastAlert(this, "No application that can receive the intent camera.", false); }else{ ToolBox.dialog_showToastAlert(this, "No camera present!!", false); } } } private void getPictureFromGallery(){ /* //This allows to select the application to use when selecting an image. Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.setType("image/*"); startActivityForResult(Intent.createChooser(i, "Escoge una foto"), PICTURE_TAKEN_FROM_GALLERY); */ //This takes images directly from gallery Intent gallerypickerIntent = new Intent(Intent.ACTION_PICK); gallerypickerIntent.setType("image/*"); startActivityForResult(gallerypickerIntent, PICTURE_TAKEN_FROM_GALLERY); } 

}

El layout es:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:background="#f2f2f2" tools:context=".MainActivity" > <ImageView android:id="@+id/pictureZone" android:layout_width="280dp" android:layout_height="280dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:src="@drawable/ic_launcher" /> <Button android:id="@+id/btncamera" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="36dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:text="Camera" /> <Button android:id="@+id/btngallery" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:text="Pick it" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/btngallery" android:layout_centerHorizontal="true" android:text="Choose an option" android:textStyle="bold" android:textAppearance="?android:attr/textAppearanceMedium" /> 

Y por último en el manifest hace falta como no, los permisos adecuados:

 <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

Un saludo.

Я нашел лучший и простой способ сделать снимок с камеры или галереи, используя эту библиотеку https://android-arsenal.com/details/1/3623

Вы можете перейти по ссылке выше или выполнить следующие действия:

Шаги по использованию этой библиотеки в вашем проекте:

  1. Добавить зависимость от Gradle:

    Compile 'com.frosquivel: magicalcamera: 4.4'

  2. Код реализации:

    PermissionGranted permissionGranted = new PermissionGranted (this); MagicalCamera magicalCamera = новая MagicalCamera (это, разрешениеGranted); // Параметр this, является текущим действием // разрешением для фотосъемки, неверно, если пользователь проверяет запрет на разрешениеGranted.checkCameraPermission (); // для поиска и записи фотоснимка во внутренней памяти устройства // нормальное или разрешение памяти SDGranted.checkReadExternalPermission (); permissionGranted.checkWriteExternalPermission ();

  3. Позвоните, чтобы снять фото с камеры:

    magicalCamera.takePhoto ();

  4. Вызов для выбора фотографии из галереи:

    magicalCamera.selectedPicture ( "my_header_name");

  5. Переопределить OnActivityResult (); Метод для получения битмапа и пути:

     public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); magicalCamera.resultPhoto(requestCode, resultCode, data);//with this form you obtain the bitmap Bitmap bitmap = magicalCamera.getPhoto(); imageView.setImageBitmap(bitmap); //if you need path of bitmap use this code String path = magicalCamera.savePhotoInMemoryDevice(magicalCamera.getPhoto(),"myPhotoName","myDirectoryName", MagicalCamera.JPEG, true); 

    If (path! = Null) {Toast.makeText (MainActivity.this, «Фотография сохраняется на устройстве, проверьте этот путь:« + путь, Toast.LENGTH_SHORT) .show (); } Else {Toast.makeText (MainActivity.this, «Извините, что ваша фотография не написана в разделе, пожалуйста, свяжитесь с fabian7593 @ gmail и скажите эту ошибку», Toast.LENGTH_SHORT) .show (); }}

Для получения дополнительной информации см. Ссылку выше

  1. Создайте в своем макете кнопку (нажав на эту кнопку, откроется диалог, в котором вы можете выбрать, выбирать ли камеру или галерею).

  2. Теперь инициализирует кнопку в своем классе:

    – Перед onCreate:

    Button btu;

    – Внутри onCreate:

    btu = (Button) findViewById(R.id.BtUp);

  3. Методы вызова камеры и галереи

– Перед загрузкой onCreate

 int CAMERA_REQUEST = 1; 

– Способ вызова камеры

 public void callCamera() { Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); cameraIntent.putExtra("crop", "true"); cameraIntent.putExtra("aspectX", 0); cameraIntent.putExtra("aspectY", 0); cameraIntent.putExtra("outputX", 200); cameraIntent.putExtra("outputY", 150); startActivityForResult(cameraIntent, CAMERA_REQUEST); } 

– Галерея вызовов метода

 public void callGallery() { Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent,0); } 
  1. Создайте метод отображения AlertDialog, который, как представляется, выбирает:

     public void showAlertDialog(Context context) { this.context = context; final String items[] = {getString(R.string.TextTakeCam), getString(R.string.TextTakeGal)}; AlertDialog.Builder ab = new AlertDialog.Builder(MainActivity.this); ab.setTitle(getString(R.string.TextTitleDia)); AlertDialog.Builder builder = ab.setItems(items, new DialogInterface.OnClickListener() { public void onClick(DialogInterface d, int choice) { if (choice == 0) { callCamera(); } else if (choice == 1) { image.setVisibility(View.INVISIBLE); callGallery(); } }}); ab.show(); 

    }

  2. Вызов AlertDialog в кнопке

     btu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String title = getString(R.string.TextUp); String msg = getString(R.string.TextUp2); showAlertDialog2(MainActivity.this,title,msg,true); //maneger.UpdateC(edname.getText().toString(),edfoto.getText().toString(),ednum. getText().toString()); } }); 

Внутри AndroidManifest.xml

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />