Как получить результат камеры как URI в папке данных?

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

Я открываю камеру используяandroid.provider.MediaStore.ACTION_IMAGE_CAPTURE намеренное действие, и я передаю Uri файла в качестве параметраEXTRA_OUTPUT чтобы вернуть изображение в файл. Это работает отлично, и я могу получить захваченное изображение, если я используюexternal storage uri какEXTRA_OUTPUT но если я использую папку данных URI, она не работает, и камера не закрывается, и все ее кнопки не работают.

Вот мой код для получения результата в каталоге внешнего хранилища

<code>Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = Environment.getExternalStorageDirectory();
out = new File(out, imagename);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);
</code>

И этот код для получения изображения в папке данных

<code>Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = getFilesDir();
out = new File(out, MyPharmacyOptions.PRESCRIPTION_IMAGE_NAME);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);
</code>

Я знал, чтоdata folder is not accessible to third application возможно, это вызывает проблему, поэтому я должен создать один поставщик контента для общего доступа к файлу.

Вот мой контент предоставит класс

<code>public class MyContentProvider extends ContentProvider {
    private static final String Tag = RingtonContentProvider.class.getName();
    public static final Uri CONTENT_URI = Uri
            .parse("content://x.y.z/");
    private static final HashMap<String, String> MIME_TYPES = new HashMap<String, String>();

    static {
        MIME_TYPES.put(".mp3", "audio/mp3");
        MIME_TYPES.put(".wav", "audio/mp3");
        MIME_TYPES.put(".jpg", "image/jpeg");
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public String getType(Uri uri) {
        String path = uri.toString();

        for (String extension : MIME_TYPES.keySet()) {
            if (path.endsWith(extension)) {
                return (MIME_TYPES.get(extension));
            }
        }

        return (null);
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
            throws FileNotFoundException {
        File f = new File(getContext().getFilesDir(), uri.getPath());

        if (f.exists()) {
            return (ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY));
        }

        throw new FileNotFoundException(uri.getPath());
    }

    @Override
    public Cursor query(Uri url, String[] projection, String selection,
            String[] selectionArgs, String sort) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public Uri insert(Uri uri, ContentValues initialValues) {
        File file = new File(getContext().getFilesDir(), uri.getPath());
        if(file.exists()) file.delete();
        try {
            file.createNewFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return Uri.fromFile(file);
    }

    @Override
    public int update(Uri uri, ContentValues values, String where,
            String[] whereArgs) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public int delete(Uri uri, String where, String[] whereArgs) {
        File f = new File(getContext().getFilesDir(), "image1.jpg");
        if(f.exists()) f.delete();
        f = new File(getContext().getFilesDir(), "image2.jpg");
        if(f.exists()) f.delete();

        getContext().getContentResolver().notifyChange(CONTENT_URI, null);

    }
}
</code>

Таким образом, чтобы использовать этот контент, я использую следующий код, чтобы передать URI для активности камеры

<code>Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = MyContentProvider.CONTENT_URI;
uri = Uri.withAppendedPath(uri, imagename);
getContentResolver().insert(uri, null);
getContentResolver().notifyChange(RingtonContentProvider.CONTENT_URI, null);
Log.d(Tag, uri.toString());
i.putExtra(MediaStore.EXTRA_OUTPUT, uri);

startActivityForResult(i, CAMERA_RESULT);
</code>

Теперь, если я передаю URL-адрес, отличный от каталога внешнего хранилища, камера открывается, но не закрывается в эмуляторе, а в устройстве камера закрывается, но я не получаю результат.

Я объявил, что это содержание предоставить в файле манифеста

<code><provider
android:name=".contentproviders.MyContentProvider"
android:authorities="x.y.z" />
</code>

Также я дал разрешение наwrite the external storage а также дляuse the camera.

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

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

If we not provide the extras with the camera intent it will return the image as a byte[] in the activity result as a data extra but this is for the purpose of the thumbnail so I can't get the high resolution image using this way.

 George24 июл. 2013 г., 03:34
Что является возвращаемым значением дляpublic int delete(Uri uri, String where, String[] whereArgs)

Ответы на вопрос(6)

Решение Вопроса

Есть два способа решить эту проблему.

1. Save bitmap which you received from onActivityResult method

Вы можете запустить камеру через намерение сделать снимок, используя код ниже

Intent cameraIntent=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);

После захвата фото вы получите растровое изображение в методе onActivityResult

if (requestCode == CAMERA_REQUEST) {  
    Bitmap photo = (Bitmap) data.getExtras().get("data"); 
 }

Теперь вы можете просто сохранить это растровое изображение во внутреннем хранилище

Note: Here bitmap object consists of thumb image, it will not have a full resolution image

2. Save bitmap directly to internal storage using content provider

Здесь мы создадим класс провайдера контента, чтобы разрешить разрешение локального каталога хранения на активность камеры

Пример провайдера, как показано ниже

public class MyFileContentProvider extends ContentProvider {
    public static final Uri CONTENT_URI = Uri.parse
                                    ("content://com.example.camerademo/");
    private static final HashMap<String, String> MIME_TYPES = 
                                     new HashMap<String, String>();

    static {
        MIME_TYPES.put(".jpg", "image/jpeg");
        MIME_TYPES.put(".jpeg", "image/jpeg");
    }

    @Override
    public boolean onCreate() {

        try {
            File mFile = new File(getContext().getFilesDir(), "newImage.jpg");
            if(!mFile.exists()) {
                mFile.createNewFile();
            }
            getContext().getContentResolver().notifyChange(CONTENT_URI, null);
            return (true);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    @Override
    public String getType(Uri uri) {
        String path = uri.toString();

        for (String extension : MIME_TYPES.keySet()) {
            if (path.endsWith(extension)) {
                return (MIME_TYPES.get(extension));
            }
        }
        return (null);
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
    throws FileNotFoundException {

        File f = new File(getContext().getFilesDir(), "newImage.jpg");
        if (f.exists()) {
            return (ParcelFileDescriptor.open(f,
                    ParcelFileDescriptor.MODE_READ_WRITE));
        }
        throw new FileNotFoundException(uri.getPath());
    }
}

После этого вы можете просто использовать URI для перехода к активности камеры с помощью приведенного ниже кода

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
startActivityForResult(i, CAMERA_RESULT);

Если вы не хотите создавать собственного провайдера, вы можете использоватьFileProvider из support-library-v4. Для получения подробной помощи вы можете посмотреть вэта почта

 Dharmendra01 нояб. 2012 г., 14:10
скопировать имя файла в глобальную переменную, а затем использовать эту переменную в методе onActivityResult ()
 16 окт. 2012 г., 14:13
Мне нравится простота первого решения и я реализовал его в своем приложении. Однако, это только получает версию изображения низкого разрешения ...
 02 нояб. 2012 г., 08:10
@ Дармандра СПАСИБО. наконец то работает :)
 01 нояб. 2012 г., 11:45
@Dharmendra я пытаюсь получить изображение в реальном размере и получить нулевое намерение onActivityResult (); Вот мой код: final String timeString = new SimpleDateFormat (& quot; HH_mm_ss_SSS & quot;). Format (cal.getTime ()); image = новый файл (imagesFolder, "ec_" + timeString + ".jpg"); Uri uriSavedImage = Uri.fromFile (изображение); intent = new Intent (android.provider.MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra (MediaStore.EXTRA_OUTPUT, uriSavedImage); startActivityForResult (намерение, CAMERA_RESULT); Есть идеи, почему я получаю нулевое значение намерения?
 Dharmendra16 окт. 2012 г., 15:40
@ DiscoS2 Это даст вам изображение с низким разрешением. чтобы получить фактический размер изображения, создайте один файл во внешнем хранилище, а затем передайте файл uri с намерением камеры, чтобы после завершения захвата камера записала изображение в ваш файл с исходным разрешением.

Вы также можете сделать это без необходимости в поставщике контента, поскольку вам все равно понадобится SD-карта, чтобы открыть намерение захвата изображения с камеры. Конечно, вы можете взломать наличие SD-карты, но не с помощью захвата камеры намеренно ... Итак, вы проверяете внешнее хранилище, но вам это нужно на данный момент ... кадрирование изображения вместо использования native, поскольку оно не очень хорошо поддерживается на разных устройствах.

File mediaStorageDir;
String photoFileName = "photo.jpg";


    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // page = getArguments().getInt("someInt", 0);
    // title = getArguments().getString("someTitle");
    // Get safe storage directory for photos
        mediaStorageDir = new File(
                Environment                          .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                APP_TAG);
        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) {
            Log.d(APP_TAG, "Directory exists: " + mediaStorageDir.isDirectory());
            Log.d(APP_TAG, "Directory exists: " + mediaStorageDir.getPath());
            Log.d(APP_TAG,
                    "Directory exists: "
                            + Environment.getExternalStorageState());
            Log.d(APP_TAG, "failed to create directory");
        }

}

в вашем 'возьмите рис & a; код:

            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, getPhotoFileUri(photoFileName));

...

public Uri getPhotoFileUri(String fileName) {

    return Uri.fromFile(new File(mediaStorageDir.getPath() + File.separator
            + fileName));
}

Лучшее решение, которое я нашел: FileProvider (нужна поддержка-library-v4) Он использует внутреннюю память! https://developer.android.com/reference/android/support/v4/content/FileProvider.html

Define your FileProvider in Manifest in Application element:

<provider
      android:name="android.support.v4.content.FileProvider"
      android:authorities="your.package.name.fileprovider"
      android:exported="false"
      android:grantUriPermissions="true" >
      <meta-data
                 android:name="android.support.FILE_PROVIDER_PATHS"
                 android:resource="@xml/image_path" />
</provider>

Add permissions in manifest root element:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />

Define your image paths in for example res/xml/image_path.xml:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="captured_image" path="your/path/"/>
</paths>

Java:

private static final int IMAGE_REQUEST_CODE = 1;
// your authority, must be the same as in your manifest file 
private static final String CAPTURE_IMAGE_FILE_PROVIDER = "your.package.name.fileprovider";

4.1 намерение захвата:

    File path = new File(activity.getFilesDir(), "your/path");
    if (!path.exists()) path.mkdirs();
    File image = new File(path, "image.jpg");
    Uri imageUri = FileProvider.getUriForFile(activity, CAPTURE_IMAGE_FILE_PROVIDER, image);
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    startActivityForResult(intent, IMAGE_REQUEST_CODE);

4.2 onActivityResult ():

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (requestCode == IMAGE_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                File path = new File(getFilesDir(), "your/path");
                if (!path.exists()) path.mkdirs();
                File imageFile = new File(path, "image.jpg");
                // use imageFile to open your image
            }
        }
        super.onActivityResult(requestCode, resultCode, intent);
    }
 17 дек. 2014 г., 09:47
// ваши полномочия должны быть такими же, как в вашем файле манифеста: частная статическая конечная строка CAPTURE_IMAGE_FILE_PROVIDER = & quot; your.package.name.fileprovider & quot ;;
 15 дек. 2014 г., 16:45
А кто такой CAPTURE_IMAGE_PROVIDER?
 06 мая 2016 г., 07:20
@Harry android: members = & quot; your.package.name.fileprovider & quot; Какой это путь, можете ли вы немного рассказать о fileprovider?

Сначала сохраните полученное фото на внешнем накопителе и попробуйте -

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);
   this.imageView = (ImageView)this.findViewById(R.id.imageView1);
   Button photoButton = (Button) this.findViewById(R.id.button1);
   photoButton.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
        startActivityForResult(cameraIntent, CAMERA_REQUEST); 
    }
});
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
   if (requestCode == CAMERA_REQUEST) {  
        Bitmap bmp = intent.getExtras().get("data");
        ByteArrayOutputStream stream = new ByteArrayOutputStream();

         bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
         byte[] byteArray = stream.toByteArray(); // convert camera photo to byte array

         // save it in your external storage.
        FileOutputStream fo = new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/_camera.png"));

        fo.write(byteArray);
        fo.flush();
        fo.close();
   }  
} 

Следующая цель -

File cameraFile = new File(Environment.getExternalStorageDirectory() + "/_camera.png");                 
startActivityForResult(Intent.createChooser(new Intent(Intent.ACTION_SEND)
        .setType("image/jpg")
        .putExtra(Intent.EXTRA_SUBJECT, "Subject")
        .putExtra(Intent.EXTRA_STREAM, Uri.fromFile(cameraFile))
        .putExtra(Intent.EXTRA_TEXT, textBody), "Send your message using"), Constant.EMAIL);
 Dharmendra06 апр. 2012 г., 13:54
Спасибо за быстрый ответ. Это один из возможных способов сохранить изображение в папке данных, но это изображение предназначено для миниатюр, поэтому качество этого изображения очень низкое, и поэтому я не могу использовать это изображение.
 Dharmendra06 апр. 2012 г., 13:56
Я должен использовать изображение для рецепта, и поэтому я не могу использовать это уменьшенное изображение
 06 апр. 2012 г., 13:44
сохраните изображение, используя этот путь - & lt; / data / data / & lt; имя вашего пакета & gt; /camera.png>
 06 апр. 2012 г., 13:57
bmp.compress (Bitmap.CompressFormat.PNG, 100, stream); это сохранение качества. Таким образом, вы можете изменить его. Используйте 50 или 40 вместо 100% сжатия.
 Dharmendra06 апр. 2012 г., 13:40
Я могу захватить изображение с помощью внешнего хранилища, но я хочу сохранить изображение в каталоге данных вместо внешнего хранилища, потому что, если внешнее хранилище недоступно, я хочу захватить изображение и отправить почту. Если я создаю контент, то могу также поделиться своим изображением с приложением электронной почты.

После изучения этой ошибки в течение некоторого времени я заметил, что действие, которое вызывало намерение камеры, перезапускается только тогда, когда в телефоне заканчивается память. поэтому, поскольку действие перезапускается, объект, содержащий путь или Uri к захваченному изображению, обновляется (обнуляется)

поэтому я бы предложил вам перехватить / обнаружить нулевой объект в onActivityResult и предложить пользователю освободить место на своем устройстве или перезапустить телефон для быстрого временного исправления.

Намерение позвонить, чтобы сделать снимок,

Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);  
startActivityForResult(cameraIntent, CAMERA_REQUEST);  

Затем возьмите растровое изображение вActivityResult

 if (requestCode == CAMERA_REQUEST) {   
            Bitmap photo = (Bitmap) data.getExtras().get("data");  
 }   

Затем запишите это во внутреннюю память,видеть это

// The openfileOutput() method creates a file on the phone/internal storage in the context of your application  
final FileOutputStream fos = openFileOutput("my_new_image.jpg", Context.MODE_PRIVATE); 

// Use the compress method on the BitMap object to write image to the OutputStream 
bm.compress(CompressFormat.JPEG, 90, fos); 

Затем в следующий раз, чтобы прочитать этот файл,

Bitmap bitmap = BitmapFactory.decodeFile(file); 
 30 авг. 2013 г., 09:28
Это хорошо, но таким образом я получаю уменьшенное изображение, я хочу получить исходное изображение, как ??

Ваш ответ на вопрос