Android: Как сделать снимок с помощью камеры и сохранить изображение в полном разрешении в режиме просмотра изображений?

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

Многие ответы, которые я просмотрел, предлагают использовать data.getExtra("data") с использованием намерения MediaStore и передачей в ACTION_CAMERA_CAPTURE. Это возвращает меньшее изображение, и изображение, которое я пытаюсь отобразить, является большим, поэтому при использовании этого метода изображение выглядит размытым.

Другой вариант - использовать этот же метод и передать в EXTRA_OUTPUT. Тем не менее, это требует помещения в хранилище, и каждый ответ, который я видел, говорит мне поместить в Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES). Однако, когда я пытаюсь сделать data.getData() в onActivityResult, я получаю нулевое значение. Как мне это сделать?

alert.setPositiveButton("Take Photo", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        profileFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "image_" +
                                String.valueOf(System.currentTimeMillis()) + ".jpg");

        profile = Uri.fromFile(profileFile);
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, profile);


        startActivityForResult(intent, 1);
    }
});


protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 1 && resultCode == RESULT_OK) {

        ImageView imageView = (ImageView) findViewById(R.id.ProfileImage);

        //This returns null. 
        //I am guessing that the Environment.getExternalSt...() method is getting a storage 
        //location that does not exist. 
        //I don't know what the correct storage location is and I have not 
        //been able to find it.
        Uri u = data.getData();

        File finalFile = new File(getRealPathFromURI(u));

        Picasso.with(this).load(finalFile).into(imageView);

    }
}

1 ответ

Я предполагаю, что метод Environment.getExternalSt...() получает местоположение хранилища, которое не существует.

Возможно нет. Тем не менее, вы предполагаете, что ваш EXTRA_OUTPUT значение возвращается вам приложением камеры. Там нет ничего в ACTION_IMAGE_CAPTURE документация, которая предполагает, что это происходит.

Я не знаю, каково правильное место хранения, и я не смог его найти.

Вы знаете, где изображение должно быть. Он должен быть в том месте, которое вы указали в EXTRA_OUTPUT, Итак, посмотрите там, чтобы увидеть, если изображение там. Тем не менее, убедитесь, что вы кладете profileImage в сохраненном состоянии экземпляра Bundle, поскольку нет никакой гарантии, что ваш процесс будет продолжать работать, пока приложение камеры находится на переднем плане. Также имейте ввиду, что там много глючных ACTION_IMAGE_CAPTURE реализации, поэтому нет гарантии, что изображение будет там, где вы просили, хотя оно и должно быть.

Например, вот действие, которое использует ACTION_IMAGE_CAPTURE сделать снимок в полном разрешении, а затем использует ACTION_VIEW чтобы какой-то просмотрщик изображений отобразил результат:

/***
 Copyright (c) 2008-2016 CommonsWare, LLC
 Licensed under the Apache License, Version 2.0 (the "License"); you may not
 use this file except in compliance with the License. You may obtain a copy
 of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
 by applicable law or agreed to in writing, software distributed under the
 License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
 OF ANY KIND, either express or implied. See the License for the specific
 language governing permissions and limitations under the License.

 From _The Busy Coder's Guide to Android Development_
 https://commonsware.com/Android
 */

package com.commonsware.android.camcon;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import java.io.File;

public class CameraContentDemoActivity extends Activity {
  private static final String EXTRA_FILENAME=
    "com.commonsware.android.camcon.EXTRA_FILENAME";
  private static final String FILENAME="CameraContentDemo.jpeg";
  private static final int CONTENT_REQUEST=1337;
  private File output=null;

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

    Intent i=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    if (savedInstanceState==null) {
      File dir=
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);

      dir.mkdirs();
      output=new File(dir, FILENAME);
    }
    else {
      output=(File)savedInstanceState.getSerializable(EXTRA_FILENAME);
    }

    if (output.exists()) {
      output.delete();
    }

    i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(output));

    startActivityForResult(i, CONTENT_REQUEST);
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putSerializable(EXTRA_FILENAME, output);
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode,
                                  Intent data) {
    if (requestCode == CONTENT_REQUEST) {
      if (resultCode == RESULT_OK) {
        Intent i=new Intent(Intent.ACTION_VIEW);

        i.setDataAndType(Uri.fromFile(output), "image/jpeg");
        startActivity(i);
        finish();
      }
    }
  }
}

(из этого примера приложения)

В долгосрочной перспективе это не очень хорошее решение, так как fileUri ценности уходят Официальную страницу обучения и обновленную версию моего примера приложения можно увидеть, используя FileProvider вместо.

Другие вопросы по тегам