Я работаю над приложением дополненной реальности, в котором у меня есть экран предварительного просмотра камеры, на котором я рисую некоторые маркеры, которые перемещаются относительно движения устройства.
Когда я lock and unlock
устройство, маркеры замерзают и не двигаются дальше. Я не могу найти причину, по которой это происходит. Есть ли в этом возможности для этого? Любая помощь будет принята с благодарностью.
Мой класс SurfaceView:
public class CameraSurface extends SurfaceView implements SurfaceHolder.Callback
{
private static SurfaceHolder holder = null;
public static Camera camera = null;
Activity ctx;
public CameraSurface(Activity context) {
super(context);
ctx=context;
try {
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public CameraSurface(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CameraSurface(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (camera != null) {
try {
camera.stopPreview();
} catch (Exception ex) {
ex.printStackTrace();
}
try {
camera.release();
} catch (Exception ex) {
ex.printStackTrace();
}
camera = null;
}
camera = Camera.open();
setCamFocusMode();
camera.setPreviewDisplay(holder);
} catch (Exception ex) {
try {
if (camera != null) {
try {
camera.stopPreview();
} catch (Exception ex1) {
ex.printStackTrace();
}
try {
camera.release();
} catch (Exception ex2) {
ex.printStackTrace();
}
camera = null;
}
} catch (Exception ex3) {
ex.printStackTrace();
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
try {
if (camera != null) {
try {
camera.stopPreview();
} catch (Exception ex) {
ex.printStackTrace();
}
try {
camera.release();
} catch (Exception ex) {
ex.printStackTrace();
}
camera = null;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (camera==null)
return;
try {
final Camera.Parameters parameters = camera.getParameters();
try {
List<Camera.Size> supportedSizes = null;
// On older devices (<1.6) the following will fail
// the camera will work nevertheless
supportedSizes = CameraCompatibility.getSupportedPreviewSizes(parameters);
// preview form factor
float ff = (float) w / h;
// holder for the best form factor and size
float bff = 0;
int bestw = 0;
int besth = 0;
Iterator<Camera.Size> itr = supportedSizes.iterator();
// we look for the best preview size, it has to be the closest
// to the
// screen form factor, and be less wide than the screen itself
while (itr.hasNext()) {
Camera.Size element = itr.next();
// current form factor
float cff = (float) element.width / element.height;
// check if the current element is a candidate to replace
// the best match so far
// current form factor should be closer to the bff
// preview width should be less than screen width
// preview width should be more than current bestw
// this combination will ensure that the highest resolution
// will win
if ((ff - cff <= ff - bff) && (element.width <= w) && (element.width >= bestw)) {
bff = cff;
bestw = element.width;
besth = element.height;
}
}
// Some Samsung phones will end up with bestw and besth = 0
// because their minimum preview size is bigger then the screen
// size.
// In this case, we use the default values: 480x320
if ((bestw == 0) || (besth == 0)) {
bestw = 480;
besth = 320;
}
parameters.setPreviewSize(bestw, besth);
} catch (Exception ex) {
parameters.setPreviewSize(480, 320);
}
///
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(0, info);
int rotation = ctx.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360;
// compensate the mirror
} else {
// back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
camera.setParameters(parameters);
camera.startPreview();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void setCamFocusMode(){
if(null == camera) {
return;
}
/* Set Auto focus */
Parameters parameters = camera.getParameters();
List<String> focusModes = parameters.getSupportedFocusModes();
if(focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)){
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else
if(focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)){
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
camera.setParameters(parameters);
}
}
AugmentedView.java://Этот класс рисует маркеры на экране предварительного просмотра камеры.
/**
* This class extends the View class and is designed draw the zoom bar, radar
* circle, and markers on the View.
*
*/
public class AugmentedView extends View {
private static final String TAG = "AugmentedView";
private static final AtomicBoolean drawing = new AtomicBoolean(false);
private static final Radar radar = new Radar();
private static final float[] locationArray = new float[3];
private static final List<Marker> cache = new ArrayList<Marker>();
private static final Set<Marker> updated = new HashSet<Marker>();
public AugmentedView(Context context) {
super(context);
Log.v(TAG, "portrait = "+CameraPreviewFragment.ui_portrait);
Log.v(TAG, "useCollisionDetection = "+CameraPreviewFragment.useCollisionDetection);
Log.v(TAG, "useSmoothing = "+CameraPreviewFragment.useDataSmoothing);
Log.v(TAG, "showRadar = "+CameraPreviewFragment.showRadar);
Log.v(TAG, "showZoomBar = "+CameraPreviewFragment.showZoomBar);
//radar = new Radar(context);
}
/**
* {@inheritDoc}
*/
@Override
protected void onDraw(Canvas canvas) {
if (canvas == null) return;
if (drawing.compareAndSet(false, true)) {
//Log.v(TAG, "DIRTY flag found, re-populating the cache.");
// Get all the markers
List<Marker> collection = ARData.getMarkers();
// Prune all the markers that are out of the radar radius (speeds
// up drawing and collision detection)
cache.clear();
for (Marker m : collection) {
m.update(canvas, 0, 0);
if (m.isOnRadar() && m.isInView()&& m.isMarkerToBeShown()) cache.add(m);
}
/*//Draw only 10 markers
if(cache.size()>10)
collection = cache.subList(0, 10);
else*/
collection = cache;
if (CameraPreviewFragment.useCollisionDetection)
adjustForCollisions(canvas, collection);
// Draw AR markers in reverse order since the last drawn should be
// the closest
ListIterator<Marker> iter = collection.listIterator(collection.size());
while (iter.hasPrevious()) {
Marker marker = iter.previous();
marker.draw(canvas);
}
// Radar circle and radar markers
if (CameraPreviewFragment.showRadar)
radar.draw(canvas);
drawing.set(false);
}
}
private static void adjustForCollisions(Canvas canvas, List<Marker> collection) {
updated.clear();
// Update the AR markers for collisions
for (int i=0; i<collection.size(); i++) {
Marker marker1 = collection.get(i);
if (!marker1.isInView()) {
updated.add(marker1);
continue;
}
if (updated.contains(marker1))
continue;
int collisions = 1;
for (int j=i+1; j<collection.size(); j++) {
// Marker marker2 = collection.get(j);
Marker marker2 = collection.get(j);
if (!marker2.isInView()) {
updated.add(marker2);
continue;
}
if (updated.contains(marker2))
continue;
float width = marker1.getWidth();
float height = marker1.getHeight();
float max = Math.max(width, height);
if (marker1.isMarkerOnMarker(marker2)) {
marker2.getLocation().get(locationArray);
float y = locationArray[1];
float h = collisions * max;
locationArray[1] = y + h;
marker2.getLocation().set(locationArray);
marker2.update(canvas, 0, 0);
collisions++;
updated.add(marker2);
}
}
updated.add(marker1);
}
}
}