com.codename1.capture.Capture Maven / Gradle / Ivy
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codename1.capture;
import com.codename1.io.FileSystemStorage;
import com.codename1.io.Log;
import com.codename1.io.Util;
import com.codename1.media.MediaRecorderBuilder;
import com.codename1.ui.Display;
import com.codename1.ui.events.ActionEvent;
import com.codename1.ui.events.ActionListener;
import com.codename1.ui.util.ImageIO;
import com.codename1.util.StringUtil;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* {@code Capture} can "capture" media files from the device e.g. record audio, video and snap photos.
* Notice that files returned by this class are potentially temporary files and might be
* deleted by the OS in the future.
* The code below demonstrates the capturing of a photo thru this API:
*
*
*
* The code below demonstrates capturing and playing back audio files using this API:
*
*
*
*
* @author Chen
*/
public class Capture {
/**
* Returns true if the device has camera false otherwise.
* @return true if the device has a camera
*/
public static boolean hasCamera(){
return Display.getInstance().hasCamera();
}
/**
* This method tries to invoke the device native camera to capture images.
* The method returns immediately and the response will be sent asynchronously
* to the given ActionListener Object
* The image is saved as a jpeg to a file on the device.
*
* use this in the actionPerformed to retrieve the file path
* String path = (String) evt.getSource();
*
* if evt returns null the image capture was canceled by the user.
*
* @param response a callback Object to retrieve the file path
* @throws RuntimeException if this feature failed or unsupported on the platform
*/
public static void capturePhoto(ActionListener response){
Display.getInstance().capturePhoto(response);
}
/**
* Invokes the camera and takes a photo synchronously while blocking the EDT
* @return the photo file location or null if the user canceled
*/
public static String capturePhoto() {
return capturePhoto(-1, -1);
}
/**
* Capture the audio, blocking version that holds the EDT; alternatively you can use the Media API.
* @return the audio file location or null if the user canceled
*/
public static String captureAudio() {
CallBack c = new CallBack();
captureAudio(c);
Display.getInstance().invokeAndBlock(c);
return c.url;
}
/**
* Capture the audio, blocking version that holds the EDT; alternatively you can use the Media API.
* @return the audio file location or null if the user canceled
* @since 7.0
*/
public static String captureAudio(MediaRecorderBuilder recordingOptions) {
CallBack c = new CallBack();
captureAudio(recordingOptions, c);
Display.getInstance().invokeAndBlock(c);
return c.url;
}
/**
* Same as captureVideo only a blocking version that holds the EDT
* @return the photo file location or null if the user canceled
*/
public static String captureVideo() {
CallBack c = new CallBack();
captureVideo(c);
Display.getInstance().invokeAndBlock(c);
return c.url;
}
/**
* Same as {@link #captureVideo(com.codename1.capture.VideoCaptureConstraints, com.codename1.ui.events.ActionListener) } only a
* blocking version that holds the EDT.
* @param constraints
* @return A video file location or null if the user canceled.
* @since 7.0
*/
public static String captureVideo(VideoCaptureConstraints constraints) {
CallBack c = new CallBack();
captureVideo(constraints, c);
Display.getInstance().invokeAndBlock(c);
return c.url;
}
/**
* Invokes the camera and takes a photo synchronously while blocking the EDT, the sample below
* demonstrates a simple usage and applying a mask to the result
*
*
*
* @param width the target width for the image if possible, some platforms don't support scaling. To maintain aspect ratio set to -1
* @param height the target height for the image if possible, some platforms don't support scaling. To maintain aspect ratio set to -1
* @return the photo file location or null if the user canceled
*/
public static String capturePhoto(int width, int height) {
CallBack c = new CallBack();
if("ios".equals(Display.getInstance().getPlatformName()) && (width != -1 || height != -1)) {
// workaround for threading issues in iOS https://github.com/codenameone/CodenameOne/issues/2246
capturePhoto(c);
Display.getInstance().invokeAndBlock(c);
if(c.url == null) {
return null;
}
ImageIO scale = Display.getInstance().getImageIO();
if(scale != null) {
try {
String path = c.url.substring(0, c.url.indexOf(".")) + "s" + c.url.substring(c.url.indexOf("."));
OutputStream os = FileSystemStorage.getInstance().openOutputStream(path);
scale.save(c.url, os, ImageIO.FORMAT_JPEG, width, height, 1);
Util.cleanup(os);
FileSystemStorage.getInstance().delete(c.url);
return path;
} catch (IOException ex) {
Log.e(ex);
}
}
} else {
c.targetWidth = width;
c.targetHeight = height;
capturePhoto(c);
Display.getInstance().invokeAndBlock(c);
}
return c.url;
}
/**
* This method tries to invoke the device native hardware to capture audio.
* The method returns immediately and the response will be sent asynchronously
* to the given ActionListener Object
* The audio is saved to a file on the device.
*
* use this in the actionPerformed to retrieve the file path
* String path = (String) evt.getSource();
*
* @param response a callback Object to retrieve the file path
* @throws RuntimeException if this feature failed or unsupported on the platform
*/
public static void captureAudio(ActionListener response){
Display.getInstance().captureAudio(response);
}
/**
* This method tries to invoke the device native hardware to capture audio.
* The method returns immediately and the response will be sent asynchronously
* to the given ActionListener Object
* The audio record settings are specified in the recorderOptions parameter.
*
* use this in the actionPerformed to retrieve the file path.
* String path = (String) evt.getSource();
*
*
* @param response a callback Object to retrieve the file path
* @throws RuntimeException if this feature failed or unsupported on the platform
* @since 7.0
*/
public static void captureAudio(MediaRecorderBuilder recorderOptions, ActionListener response){
Display.getInstance().captureAudio(recorderOptions, response);
}
/**
* Captures video with some constraints, like width, height, and max length. Video constraints
* may not be supported on all platforms. Use {@link VideoCaptureConstraints#isSupported() } and {@link VideoCaptureConstraints#isSizeSupported() }
* to check whether constraints are supported on the current platform. If constraints are not supported, then, in the worst case, this will fall
* back to just use {@link #captureVideo(com.codename1.ui.events.ActionListener) }, i.e. capture with no constraints.
* @param constraints The constraints to use for the video capture.
* @param response a callback Object to retrieve the file path
* @since 7.0
*/
public static void captureVideo(VideoCaptureConstraints constraints, ActionListener response) {
Display.getInstance().captureVideo(constraints, response);
}
/**
* This method tries to invoke the device native camera to capture video.
* The method returns immediately and the response will be sent asynchronously
* to the given ActionListener Object
* The video is saved to a file on the device.
*
* use this in the actionPerformed to retrieve the file path
* String path = (String) evt.getSource();
*
* @param response a callback Object to retrieve the file path
* @throws RuntimeException if this feature failed or unsupported on the platform
* @see #captureVideo(com.codename1.capture.VideoCaptureConstraints, com.codename1.ui.events.ActionListener)
*/
public static void captureVideo(ActionListener response){
Display.getInstance().captureVideo(response);
}
static class CallBack implements ActionListener, Runnable {
String url;
private boolean completed;
private int targetWidth = -1;
private int targetHeight = -1;
public void actionPerformed(ActionEvent evt) {
if(evt == null) {
url = null;
} else {
url = (String)evt.getSource();
}
completed = true;
synchronized(this) {
this.notify();
}
}
public void run() {
while(!completed) {
synchronized(this) {
try {
this.wait();
} catch (InterruptedException ex) {
}
}
}
if(url == null) {
return;
}
if(targetWidth > 0 || targetHeight > 0) {
ImageIO scale = Display.getInstance().getImageIO();
if(scale != null) {
try {
String path = url.substring(0, url.lastIndexOf(".")) + "s" + url.substring(url.lastIndexOf("."));
OutputStream os = FileSystemStorage.getInstance().openOutputStream(path);
scale.save(url, os, ImageIO.FORMAT_JPEG, targetWidth, targetHeight, 1);
Util.cleanup(os);
FileSystemStorage.getInstance().delete(url);
url = path;
} catch (IOException ex) {
Log.e(ex);
}
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy