200 likes | 342 Views
camera. Make new project Give permission to use camera Make button called TakePicture Make button called ShowLastPic Add SurfaceView to layout Surface view is something we can draw on This will show the picture preview Set layout height = fill_parent (or try 10dip)
E N D
Make new project • Give permission to use camera • Make button called TakePicture • Make button called ShowLastPic • Add SurfaceView to layout • Surface view is something we can draw on • This will show the picture preview • Set layout height = fill_parent (or try 10dip) • Set layout width = fill_parent • Set layout weight = 1 • Id = @+id/surface_camera • SurfaceView changes when the phone’s orientation changes.
To handle the surface and changes in the surface, we need our activity to implement SurfaceHolder.Callback. • public class MyCamera extends Activity implements SurfaceHolder.Callback { • Our MyCamera class needs some objects • Camera mCamera; // to hold the camera object • private SurfaceViewmSurfaceView; // to hold the surface view • private SurfaceHoldermSurfaceHolder; // to hold the interface for the surfacevieww • We’ll add some more later • After super.onCreate • setContentView(R.layout.main); • mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera); // get surface object • mSurfaceHolder = mSurfaceView.getHolder(); // get surface holder • mSurfaceHolder.addCallback(this); // this activity is the callback • // note, instead this, we could make a new classss that implements SurfcaeHolder.Callback • mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // says ? • Implementing SurfaceHolder.CallBack requires three functions to be implemented • surfaceCreated • surfaceChanged • Called when orientation is changed and after surfaceCreated • surfaceDestroyed
public void surfaceCreated(SurfaceHolder holder) { Log.e("My camera app", "surfaceCreated"); mCamera = Camera.open();}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { Log.d("My camera app", "surfaceChanged"); mCamera.stopPreview(); …. Set up preview …. mCamera.startPreview(); But mCamera.stopPreview() requires that startPreview was called
booleanpreviewRunning = false; public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { Log.d(“My camera app”, "surfaceChanged"); If (previewRunning) mCamera.stopPreview(); …. Set up preview …. mCamera.startPreview(); previewRunning = true;
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { Log.d(“My camera app”, "surfaceChanged"); if (previewRunning) { mCamera.stopPreview(); } Log.e("My camera app","view width"+w+" height"+h); Camera.Parameters p = mCamera.getParameters(); // set the preview size p.setPreviewSize(w, h); mCamera.setParameters(p); try { mCamera.setPreviewDisplay(holder); } catch (IOException e) { e.printStackTrace(); } mCamera.startPreview(); mPreviewRunning= true; }
public void surfaceDestroyed(SurfaceHolder holder) { Log.e("My camera app", "surfaceDestroyed"); mCamera.stopPreview(); mCamera.release(); previewRunning = false;}
run • It crashes on nexus 1 • Check log • Note that error when setting preview size • Note that preview size is odd. • Check web for more info on Camera.Parameters and Camera.Parameters.setPreviewSize • see getSupportedPreviewSizes
Before setParameters, do the following Log.e("My camera app","width"+w+" h"+h); List<Camera.Size> sizes = mCamera.getParameters().getSupportedPreviewSizes(); Camera.Size sizeToSet = null; for (Camera.Size t: sizes) { String str = "view"; str += t.width; str += "by" + t.height; Log.e("My camera app”, str); } Log.e("My camera app“,"w="+sizeToSet.width+" h="+sizeToSet.height); add Boolean found = new Boolean(false); Inside loop, add if (t.width<=w && t.height<=h && found==false) { sizeToSet = t; found = true; }
Change parameter setting to: Camera.Parameters p = mCamera.getParameters(); p.setPreviewSize(sizeToSet.width, sizeToSet.height); mCamera.setParameters(p);
Rotation/orientation • Note that the orientation is messed up • Perhaps the image is correct in only one orientation. • Two fixes • Fix the orientation to be in portrait or landscape and set display orientation accordingly • In onCreate, add • setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); • In surfaceChanged, add • mCamera.setDisplayOrientation(180); // or whatever value works • Get the rotation and then set camera orientation accordingly • In surfaceChanged, add • Display display = getWindowManager().getDefaultDisplay(); • switch (display.getRotation()) { • case Surface.ROTATION_0: • Log.e("DEBUG INFO","rotation = 0"); • mCamera.setDisplayOrientation(180); // whatever value works • break; • case Surface.ROTATION_90: • Etc. etc.
Take picture • In onCreate add button click listener • When clicked call • previewRunning = false; • mCamera.stopPreview(); • mCamera.takePicture(null, null, pictureCallback); • The first null could be set to play a sound. But we will just use the default • pictureCallback is a Camera.PictureCallback object that we must make
Where to save files? • Private directories • Only accessible by this app (cannot share files) • Deleted when app is uninstalled • Can be on internal memory or external (e.g., sdcard) • External Storage Directory • Might be on sdcard or internal memory • Can be mounted on another machine • when attaching phone to laptop via usb, the external memory is accessible by the laptop and might not be accessible by the phone apps • No standard directories, so files can get messy. Hence not recommended unless you are careful to clean up after yourself • External Storage Public Directory • Like External Storage Directory, but uses specific directories e.g., pictures, music, video
External storage • Before external storage is used, the app must check that the storage is accessible • If the phone is attached to a computer via usb, the storage might not be accessible because the computer is controlling the storage device • booleanmExternalStorageAvailable = false; • booleanmExternalStorageWriteable = false; • String state = Environment.getExternalStorageState(); • if (Environment.MEDIA_MOUNTED.equals(state)) { • // We can read and write the media • mExternalStorageAvailable = mExternalStorageWriteable = true; • Log.e("DEBUG INFO","storage is readble and writable"); • } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { • // We can only read the media • mExternalStorageAvailable = true; • mExternalStorageWriteable = false; • Log.e("DEBUG INFO","storage is readable only"); • } else { • // Something else is wrong. It may be one of many other states, but all we need • // to know is we can neither read nor write • mExternalStorageAvailable = mExternalStorageWriteable = false; • Log.e("DEBUG INFO","storage is not accessible"); • }
External Storage Public Directory • If external storage is available, we can get the directory • if (mExternalStorageWriteable) { • File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); • // arg must not be null, can be • DIRECTORY_MUSIC, DIRECTORY_PODCASTS, DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS, DIRECTORY_PICTURES, DIRECTORY_MOVIES, DIRECTORY_DOWNLOADS, or • DIRECTORY_DCIM • Pcitures and videos from camera • // this is a small set of directories • path.mkdirs(); • File file = new File(path, "my_pic.jpeg");
External Storage Directory • if (mExternalStorageWriteable) { • File path = Environment. getExternalStorageDirectory(); • File file = new File(path, "my_pic.jpeg");
Application Storage • Internal storage: only accessible by the applications. Security is enforced • File path = getFilesDir(); • File file = new File(path, "my_pic.jpeg"); • External storage. • Typically not visible to user media applications (e.g., if you store a movie here, your movie player will not find it) • No security enforcement. So other applications could overwrite • File path = getExternalFilesDir (type); • // type is DIRECTORY_MUSIC, DIRECTORY_PODCASTS, DIRECTORY_RINGTONES, DIRECTORY_ALARMS, DIRECTORY_NOTIFICATIONS, DIRECTORY_PICTURES, or DIRECTORY_MOVIES. • Or null • File file = new File(path, "my_pic.jpeg");
Camera.PictureCallbackmPictureCallback = new Camera.PictureCallback() { public void onPictureTaken(byte[] imageData, Camera c) { if (imageData== null) { Log.e("DEBUG INFO","image is null"); } else { // get file as just explained We will use Bitmap, which has lots of bitmap related functions To create a Bitmap we use BitmapFactory. decodeByteArray(byte[] data, int offset, int length) Where data is imageData (the function argument,; offset = 0; and length = imageData.length add Bitmap bitmap = BitmapFactory.decodeByteArray(imageData,0,imageData.length); To write to a jpeg file, we use Bitmap.compress(file format, quality, outputStream); add FileOutputStreamfos= new FileOutputStream(file); bitmap.compress(CompressFormat.JPEG, 50, fos); // quality is 50, but could be between 0 and 100 fos.close(); Finally, start the preview again: • previewRunning = false; • mCamera.startPreview();
Show picture • Make new activity (see previous tutorial on making another activity) • In layout add • Add ImageView • In onCreate Get file name String pathForAppFiles = getFilesDir().getAbsolutePath(); pathForAppFiles= pathForAppFiles + "/" + "myPic.jpeg"; Log.d("Still image source filename:", pathForAppFiles); Get bitmap from file Bitmap bm = BitmapFactory.decodeFile(pathForAppFiles); Show bitmap in ImageView ImageViewimageView = (ImageView)this.findViewById(R.id.ImageView); imageView.setImageBitmap(bm);