Обратный вызов от cwac-камеры

Пытаюсь реализовать замечательную библиотеку cwac-camera. Я не могу понять, как реализовать обратный вызов для изображения и как установить путь для изображения.

Это мой открытый класс CustomCameraFragment. CustomCameraFragment extends CameraFragment { private static final String KEY_USE_FFC = "com.commonsware.cwac.camera.demo.USE_FFC";

public static CustomCameraFragment newInstance(boolean useFFC) {
    CustomCameraFragment f = new CustomCameraFragment();
    Bundle args = new Bundle();

    args.putBoolean(KEY_USE_FFC, useFFC);
    f.setArguments(args);
    return (f);
}

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

    SimpleCameraHost.Builder builder =
            new SimpleCameraHost.Builder(new DemoCameraHost(getActivity()));
    builder.useFullBleedPreview(true);
    setHost(builder.build());
    //setHost(builder.useFullBleedPreview(true).build());
}

public class DemoCameraHost extends SimpleCameraHost {
    public DemoCameraHost(Context _ctxt) {
        super(_ctxt);
    }

    @Override
    public boolean useFrontFacingCamera() {
        if (getArguments() == null) {
            return (false);
        }

        return (getArguments().getBoolean(KEY_USE_FFC));
    }

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

    @Override
    public void onCameraFail(CameraHost.FailureReason reason) {
        super.onCameraFail(reason);

        Toast.makeText(getActivity(),
                "Sorry, but you cannot use the camera now!",
                Toast.LENGTH_LONG).show();
    }

    @Override
    public void saveImage(PictureTransaction xact, Bitmap bitmap) {
        super.saveImage(xact, bitmap);
    }
}

}

Я использую его в макете кадра в другом фрагменте, но не могу понять правильную реализацию обратного вызова.

Фрагмент, где я использую CustomCameraFragment: у меня есть кнопка, чтобы сделать снимок: @OnClick(R.id.btnTakePicture) public void takePicture(View view) {

    try {
        CustomCameraFragment.DemoCameraHost demoCameraHost = customCameraFragment.demoCameraHost;
        PictureTransaction pictureTransaction = new PictureTransaction(demoCameraHost);
        pictureTransaction.needBitmap(true);
        customCameraFragment.takePicture(pictureTransaction);

    } catch (Exception e) {
        e.printStackTrace();
    }

    showCameraPreview(false);

}

Но в этом фрагменте мне нужно: - Обратный вызов, чтобы узнать, когда был сделан снимок - Когда срабатывает обратный вызов, мне нужно отобразить растровое изображение вместо предварительного просмотра - Мне нужно установить путь и имя файла, где сохранить изображение

Эти 3 вещи мне непонятны.


person TomCB    schedule 02.04.2015    source источник
comment
Я сейчас в дороге, но сегодня я укажу вам на нужные разделы документации.   -  person CommonsWare    schedule 02.04.2015
comment
Все хорошо, спасибо! На данный момент я исправляю обратный вызов с помощью otto eventbus :)   -  person TomCB    schedule 02.04.2015


Ответы (2)


Вы должны переопределить функцию saveImage(PictureTransaction, byte[]), см. здесь для получения дополнительной информации:

https://github.com/commonsguy/cwac-camera#overriding-photo-saving

person Evripidis Drakos    schedule 02.04.2015
comment
В DemoCameraHost я пробовал: @Override public void saveImage (PictureTransaction xact, Bitmap bitmap) { Logger.d (TAG, saveImage); super.saveImage (точное, растровое изображение); } Но он не вызывается, когда я вызываю takePicture для своего фрагмента. - person TomCB; 02.04.2015
comment
это потому, что в ссылке, которую я разместил, упоминается: по умолчанию будет вызываться saveImage (PictureTransaction, byte []), а не saveImage (PictureTransaction, Bitmap). Чтобы изменить это, вызовите needBitmap(boolean) и/или needByteArray(boolean) в PictureTransaction, передав эту PictureTransaction в takePicture(). - person Evripidis Drakos; 02.04.2015
comment
Это действительно работает, что является большим шагом вперед. Тем не менее я не очень понимаю связь между этим CameraFragment и parentFragment, где мне нужен обратный вызов? - person TomCB; 02.04.2015
comment
я не понимаю что ты имеешь в виду - person Evripidis Drakos; 02.04.2015

Обратный вызов, чтобы узнать, когда была сделана фотография

Цитирование документации:

Логика SimpleCameraHost по умолчанию для сохранения фотографий использует метод getPhotoPath() и связанные с ним методы, описанные выше. На самом деле сохранение фотографии выполняется в saveImage(PictureTransaction, byte[]), вызываемом на вашем CameraHost, где SimpleCameraHost имеет реализацию saveImage(PictureTransaction, byte[]), которая записывает предоставленный byte[] в нужное место.

Вы можете переопределить saveImage(PictureTransaction, byte[]) и сделать что-то еще с byte[], например отправить его через Интернет. saveImage(PictureTransaction, byte[]) вызывается в фоновом потоке, поэтому вам не нужно выполнять собственную асинхронную работу.

Другое использование для этого - узнать, когда сохранение будет завершено, чтобы вы могли использовать полученное изображение. Просто переопределите saveImage(PictureTransaction, byte[]), привяжите к реализации суперкласса, и когда он вернется, изображение будет готово к использованию.


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

Цитирование документации:

По умолчанию результатом съемки является возврат CameraFragment в режим предварительного просмотра, готовый сделать следующий снимок. Если вместо этого вам нужно только одно изображение или вы хотите сначала отправить пользователя к какой-то другой части пользовательского интерфейса и не хотите, чтобы предварительный просмотр запускался снова сразу, переопределите useSingleShotMode() в вашем CameraHost, чтобы вернуть значение true. Или вызовите useSingleShotMode() на SimpleCameraHost.Builder, передав логическое значение для использования по умолчанию. Или вызовите useSingleShotMode() в PictureTransaction, чтобы управлять этим для отдельного изображения.

Затем вы, вероятно, захотите использовать свою собственную реализацию saveImage() в вашем CameraHost, чтобы делать все, что вы хотите, вместо перезапуска предварительного просмотра. Например, вы можете запустить другое действие, чтобы что-то сделать с изображением. Однако имейте в виду, что намерение ограничено ~ 1 МБ, поэтому передача изображения другому действию через дополнительное намерение, вероятно, будет ненадежным. Вам нужно будет сделать что-то еще, например (осторожно) использовать статический элемент данных.

Режим предварительного просмотра будет повторно включен автоматически после цикла onPause()/onResume() вашего CameraFragment, или вы можете вызвать restartPreview() на вашем CameraFragment (или CameraView).


Мне нужно иметь возможность установить путь и имя файла, где сохранить изображение

Это описано в документации к тому же, в чем-то достаточно длинном, чтобы мне не хотелось его здесь цитировать. :-)

person CommonsWare    schedule 02.04.2015
comment
Большое спасибо за информацию! Я думаю, что моя большая проблема заключается в том, что я использую customCameraFragment в качестве представления в своем родительском фрагменте. Из-за этого я не мог установить связь между этими двумя фрагментами (как родительский фрагмент узнает о saveImage() в customCameraFragment? Что мне нужно сделать, так это использовать customCameraFragment как мой фактический фрагмент :) - person TomCB; 03.04.2015
comment
@TomCB: как родительский фрагмент узнает о saveImage() в customCameraFragment? -- пользовательский фрагмент камеры вызовет метод своего родителя. - person CommonsWare; 03.04.2015
comment
Но тогда CustomCameraFragment не будет общим? Я не вижу CustomCameraFragment как представление, которое я могу использовать везде, где мне нужен предварительный просмотр камеры? - person TomCB; 06.04.2015
comment
@TomCB: я понятия не имею, зачем вам нужно более одного места в вашем приложении для CustomCameraFragment. Конечно, библиотека не ожидает, что у вас будет много фрагментов камеры, используемых во многих местах. При этом тот факт, что фрагмент вызывает метод для действия хостинга, не означает, что фрагмент не является универсальным. Иметь интерфейс CustomCameraFragment.Contract, который необходимо реализовать для всех операций хостинга, и заставить фрагмент вызывать метод для этого Contract. Затем фрагмент может размещаться в любом количестве действий. - person CommonsWare; 06.04.2015
comment
Отличный ввод, я исправил это, найдя свой фрагмент, где мне нужно было вызвать метод для использования моего изображения, это сработало. Теперь я использую интерфейс, как вы предложили, который работает как шарм и является более универсальным! Я думаю, что говорю от лица всего сообщества, когда говорю: Спасибо! :) - person TomCB; 07.04.2015