Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
350 views
in Technique[技术] by (71.8m points)

android - Canvas draw functions not working after screen locked and unlocked

I'm working on an augmented reality application in which I have a camera preview screen on which I draw some markers which moves with respect to device movement.

When I lock and unlock the device, the markers freezes and doesn't move further. I'm unable to find the reason why this happens.Is there any possible work around for this? Any help will be greatly appreciated.

My SurfaceView class:

    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 draws the markers on camera preview screen

    /**
 * 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's 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.getLoca

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I resolved the issue. It was with my SensorManager. The SensorManager was null when onStart() is executed.I initialized it inside the onStart() and resolved it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...