1

hello I am trying to take a picture and save that picture in a fragment. my user should press a button and take the picture and save it,my camera preview is in my fragment so I thought these things should happen in fragment too,so I tried to bring buttons in fragment but I got NullPointerException so i tried to get the bitmap and send it to activity using [this]:Passing data between a fragment and its container activity but it gives me class cast exception and i don't know what to do. remember that I want to take and save the picture,any help would be wonderful.thanks here is my code in camera fragment:

public class CameraFragment extends Fragment {
 private Preview mPreview;
 Camera mCamera;
 int mNumberOfCameras;
    // The first rear facing camera
    int mDefaultCameraId;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.d("aron", "we are in oncreate");
        super.onCreate(savedInstanceState);
        // Create a container that will hold a SurfaceView for camera previews
        mPreview = new Preview(this.getActivity());
        Log.d("aron", "we are in oncreate and we made preview successfuly");
    }
    public interface OnDataPass {
        public void onDataPass(Bitmap data);
    }
    OnDataPass dataPasser;

    @Override
    public void onAttach(Activity a) {
        super.onAttach(a);
        Log.d("aron", "we are in onattach");
        dataPasser = (OnDataPass) a;
    }
    public void passData() {
        Bitmap data=mPreview.getBitmap();
        Log.d("aron", "we are in passdata");
        dataPasser.onDataPass(data);
    }
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Add an up arrow to the "home" button, indicating that the button will go "up"
        // one activity in the app's Activity heirarchy.
        // Calls to getActionBar() aren't guaranteed to return the ActionBar when called
        // from within the Fragment's onCreate method, because the Window's decor hasn't been
        // initialized yet.  Either call for the ActionBar reference in Activity.onCreate()
        // (after the setContentView(...) call), or in the Fragment's onActivityCreated method.
       /* Activity activity = this.getActivity();
        ActionBar actionBar = activity.getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);*/
        Log.d("aron", "we are in onactivitycreated and we are done with it");
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.d("aron", "we are in oncreateview");
        return mPreview;
    }
    @Override
    public void onResume() {
        super.onResume();
        // Use mCurrentCamera to select the camera desired to safely restore
        // the fragment after the camera has been changed
        mCamera = Camera.open();
        mPreview.setCamera(mCamera);
        Log.d("aron", "we are in onresume");
    }
    @Override
    public void onPause() {
        super.onPause();
        // Because the Camera object is a shared resource, it's very
        // important to release it when the activity is paused.
        if (mCamera != null) {
            mPreview.setCamera(null);
            mCamera.release();
            mCamera = null;
        }
        Log.d("aron", "we are in onpause");
    }
   /* @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        if (mNumberOfCameras > 1) {
            // Inflate our menu which can gather user input for switching camera
            inflater.inflate(R.menu.main, menu);
        } else {
            super.onCreateOptionsMenu(menu, inflater);
        }
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
        case R.id.menu_switch_cam:
            // Release this camera -> mCameraCurrentlyLocked
            if (mCamera != null) {
                mCamera.stopPreview();
                mPreview.setCamera(null);
                mCamera.release();
                mCamera = null;
            }
            // Acquire the next camera and request Preview to reconfigure
            // parameters.
            mCurrentCamera = (mCameraCurrentlyLocked + 1) % mNumberOfCameras;
            mCamera = Camera.open(mCurrentCamera);
            mCameraCurrentlyLocked = mCurrentCamera;
            mPreview.switchCamera(mCamera);
            // Start the preview
            mCamera.startPreview();
            return true;
        case android.R.id.home:
            Intent intent = new Intent(this.getActivity(), MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
            startActivity(intent);
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }*/
}
// ----------------------------------------------------------------------
/**
 * A simple wrapper around a Camera and a SurfaceView that renders a centered
 * preview of the Camera to the surface. We need to center the SurfaceView
 * because not all devices have cameras that support preview sizes at the same
 * aspect ratio as the device's display.
 */
class Preview extends ViewGroup implements SurfaceHolder.Callback {
    private final String TAG = "Preview";
    SurfaceView mSurfaceView;
    SurfaceHolder mHolder;
    Bitmap cameraBitmap;
    Size mPreviewSize;
    List<Size> mSupportedPreviewSizes;
    Camera mCamera;
    boolean mSurfaceCreated = false;
    Preview(Context context) {
        super(context);
        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
    }
    public void setCamera(Camera camera) {
        mCamera = camera;
        if (mCamera != null) {
            mSupportedPreviewSizes = mCamera.getParameters()
                    .getSupportedPreviewSizes();
            if (mSurfaceCreated) requestLayout();
        }
    }
    public void switchCamera(Camera camera) {
        setCamera(camera);
        try {
            camera.setPreviewDisplay(mHolder);
        } catch (IOException exception) {
            Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
        }
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // We purposely disregard child measurements because act as a
        // wrapper to a SurfaceView that centers the camera preview instead
        // of stretching it.
        final int width = resolveSize(getSuggestedMinimumWidth(),
                widthMeasureSpec);
        final int height = resolveSize(getSuggestedMinimumHeight(),
                heightMeasureSpec);
        setMeasuredDimension(width, height);
        if (mSupportedPreviewSizes != null) {
            mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
                    height);
        }
        if (mCamera != null) {
          Camera.Parameters parameters = mCamera.getParameters();
          parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
          mCamera.setParameters(parameters);
        }
    }
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if (getChildCount() > 0) {
            final View child = getChildAt(0);
            final int width = r - l;
            final int height = b - t;
            int previewWidth = width;
            int previewHeight = height;
            if (mPreviewSize != null) {
                previewWidth = mPreviewSize.width;
                previewHeight = mPreviewSize.height;
            }
            // Center the child SurfaceView within the parent.
            if (width * previewHeight > height * previewWidth) {
                final int scaledChildWidth = previewWidth * height
                        / previewHeight;
                child.layout((width - scaledChildWidth) / 2, 0,
                        (width + scaledChildWidth) / 2, height);
            } else {
                final int scaledChildHeight = previewHeight * width
                        / previewWidth;
                child.layout(0, (height - scaledChildHeight) / 2, width,
                        (height + scaledChildHeight) / 2);
            }
        }
    }
    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where
        // to draw.
        try {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(holder);
            }
        } catch (IOException exception) {
            Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
        }
        if (mPreviewSize == null) requestLayout();
        mSurfaceCreated = true;
    }
    public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the preview.
        if (mCamera != null) {
            mCamera.stopPreview();
        }
    }
    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null)
            return null;
        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;
        int targetHeight = h;
        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // Now that the size is known, set up the camera parameters and begin
        // the preview.
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        requestLayout();
        Log.d("aron", "we are in surface changed");
        mCamera.setParameters(parameters);
        mCamera.startPreview();
    }
    public Bitmap getBitmap(){
        @SuppressWarnings("unused")
        PictureCallback pic=new PictureCallback() {
            @Override
            public void onPictureTaken(byte[] data, Camera arg1) {
                Log.d("aron", "onPicturetaken");
                cameraBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
            }
        };
        return cameraBitmap;
    }
}

it says ClassCastException when in

dataPasser = (OnDataPass) a;

please note that i don't want to use intent because of the other parts of my project. please help me!!!

and this is my host activity:

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ImageButton capturebtn=(ImageButton)findViewById(R.id.capturebtn);
    Log.d("aron", "Image button is created");
    capturebtn.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            @SuppressWarnings("unused")
            OnDataPass bitmapPasser=new OnDataPass() {
                @Override
                public void onDataPass(Bitmap cameraBitmap) {
                    Log.d("aron","we are in act on click and in datapass got bitmap");
                     int  wid = cameraBitmap.getWidth();
                     int  hgt = cameraBitmap.getHeight();
                     Bitmap newImage = Bitmap.createBitmap(wid, hgt, Bitmap.Config.ARGB_8888);
                     Canvas canvas = new Canvas(newImage); 
                     canvas.drawBitmap(cameraBitmap, 0f, 0f, null);
                     Log.d("aron","bitmap and canvas are made");
                     FrameLayout frm = (FrameLayout)findViewById(R.id.frameLayout1);
                     frm.setDrawingCacheEnabled(true);
                     frm.buildDrawingCache();
                     Bitmap bitmap = frm.getDrawingCache();
                     canvas.drawBitmap(bitmap, 0f, 0f, null);
                     Log.d("aron","framelayout dorost shod");
                }
            };
        }
    });
}
}

as you can see I implemented OnDataPass.

Community
  • 1
  • 1
Pouya Danesh
  • 1,557
  • 2
  • 19
  • 36

1 Answers1

0

so after a while I solved it myself the point was that Could use

Camera.PictureCallback

and i do now.like this:

    @Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    View myActivityView=(RelativeLayout)getActivity().findViewById(R.id.parentContainer);
    ImageButton capturebtn=(ImageButton)myActivityView.findViewById(R.id.capturebtn);
    capturebtn.setOnClickListener(new View.OnClickListener() {
        @SuppressWarnings("UnusedDeclaration")
        @Override
        public void onClick(View v) {
            Log.d("aron", "this is in fragment and this is a damned button say halelooya");
            mPreview.TakePicture();
        }
    });
}

as you can see in fragment in the onActivity I called the fragment parent activity and called the method for taking pictures.

Pouya Danesh
  • 1,557
  • 2
  • 19
  • 36