2011-12-21 50 views
0
outStream = new FileOutputStream(String.format(
         "/sdcard/%d.jpeg", System.currentTimeMillis())); 

我正試圖將相機中的圖像保存到手機中。我可以拍攝照片,看到SurfaceView上的照片和所有內容,但是當我轉到手機的文件系統時,無法找到照片。我認爲這是特定的代碼行,但我會發布我的整個活動只是爲了確保。這行代碼有什麼問題?

package com.commonsware.android.skeleton; 

import android.app.Activity; 
import android.content.Context; 
import android.content.Intent; 
import android.hardware.Camera; 
import android.hardware.Camera.*; 
import android.net.Uri; 
import android.os.Bundle; 
import android.os.Environment; 
import android.util.Log; 
import android.view.Display; 
import android.view.Surface; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.Window; 
import android.view.WindowManager; 
import android.widget.Button; 
import android.widget.FrameLayout; 

import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.List; 

// ---------------------------------------------------------------------- 

public class SimpleBulbActivity extends Activity { 
    private Preview mPreview; 
    private static final String TAG = "CameraDemo"; 
    FrameLayout preview; 
    Camera mCamera; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Hide the window title. 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     setContentView(R.layout.main); 
    } 

    protected void onResume() { 
     super.onResume(); 
     //Setup the FrameLayout with the Camera Preview Screen 
     mPreview = new Preview(this); 
     preview = (FrameLayout)findViewById(R.id.preview); 
     preview.addView(mPreview); 
    } 

    public void snap(View view) { 
     mCamera.takePicture(shutterCallback, rawCallback, jpegCallback); 
    } 
    ShutterCallback shutterCallback = new ShutterCallback() { 
     public void onShutter() { 
      Log.d(TAG, "onShutter'd"); 
     } 
    }; 

    PictureCallback rawCallback = new PictureCallback() { 
     public void onPictureTaken(byte[] _data, Camera _camera) { 
      Log.d(TAG, "onPictureTaken - raw"); 
     } 
    }; 

    PictureCallback jpegCallback = new PictureCallback() { 
     public void onPictureTaken(byte[] data, Camera _camera) { 
      FileOutputStream outStream = null; 
      try { 
       // write to local sandbox file system 
       // outStream = 
       // CameraDemo.this.openFileOutput(String.format("%d.jpg", 
       // System.currentTimeMillis()), 0); 
       // Or write to sdcard 
       outStream = new FileOutputStream(String.format(
         "/sdcard/%d.jpeg", System.currentTimeMillis())); 
       sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory()))); 
       outStream.write(data); 
       outStream.close(); 
       Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length); 
      } catch (FileNotFoundException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } finally { 
      } 
      Log.d(TAG, "onPictureTaken - jpeg"); 
     } 
    }; 

// ---------------------------------------------------------------------- 

    class Preview extends SurfaceView implements SurfaceHolder.Callback { 
     SurfaceHolder mHolder; 

     Preview(Context context) { 
      super(context); 

      // Install a SurfaceHolder.Callback so we get notified when the 
      // underlying surface is created and destroyed. 
      mHolder = getHolder(); 
      mHolder.addCallback(this); 
      mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     } 

     public void surfaceCreated(SurfaceHolder holder) { 
      // The Surface has been created, acquire the camera and tell it where 
      // to draw. 
      mCamera = Camera.open(); 
      try { 
       mCamera.setPreviewDisplay(holder); 
       mCamera.setPreviewCallback(new PreviewCallback() { 

       public void onPreviewFrame(byte[] data, Camera arg1) { 
        FileOutputStream outStream = null; 
        try { 
         outStream = new FileOutputStream(Environment.getExternalStorageDirectory().toString()); 
         outStream.write(data); 
         outStream.close(); 
         Log.d(TAG, "onPreviewFrame - wrote bytes: " 
           + data.length); 
        } catch (FileNotFoundException e) { 
         e.printStackTrace(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } finally { 
        } 
        Preview.this.invalidate(); 
       } 
      }); 
     } catch (IOException e) { 
       mCamera.release(); 
       mCamera = null; 
       e.printStackTrace(); 
      } 
     } 

     public void surfaceDestroyed(SurfaceHolder holder) { 
      // Surface will be destroyed when we return, so stop the preview. 
      // Because the CameraDevice object is not a shared resource, it's very 
      // important to release it when the activity is paused. 
      mCamera.stopPreview(); 
      mCamera.release(); 
      mCamera = null; 
     } 


     private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) { 
      final double ASPECT_TOLERANCE = 0.05; 
      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(); 

      List<Size> sizes = parameters.getSupportedPreviewSizes(); 
      Size optimalSize = getOptimalPreviewSize(sizes, w, h); 

      Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay(); 

      if(display.getRotation() == Surface.ROTATION_0) 
      { 
       parameters.setPreviewSize(optimalSize.height, optimalSize.width);       
       mCamera.setDisplayOrientation(90); 
      } 

      if(display.getRotation() == Surface.ROTATION_90) 
      { 
       parameters.setPreviewSize(optimalSize.width, optimalSize.height);       
      } 

      if(display.getRotation() == Surface.ROTATION_180) 
      { 
       parameters.setPreviewSize(optimalSize.width, optimalSize.height);    
      } 

      if(display.getRotation() == Surface.ROTATION_270) 
      { 
       parameters.setPreviewSize(optimalSize.width, optimalSize.height); 
       mCamera.setDisplayOrientation(0); 
      } 

      mCamera.setParameters(parameters); 
      mCamera.startPreview(); 
     } 

    } 

} 
+4

*「這行代碼出了什麼問題?」 - 它硬編碼到SD卡的路徑。這很糟糕,因爲這會因設備而異。而是使用['Environment.getExternalStorageDirectory()'](http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory%28%29)來確定路徑。不知道這是否是確切的問題,只是一般性的建議。 – 2011-12-21 23:48:48

+4

'我在想這是一段特定的代碼,但是我會發布我的整個活動只是爲了確保'你真的應該花一些時間隔離哪些代碼行可能是問題,而不是猜測。 – 2011-12-21 23:59:49

+1

我是Android新手。如果我能夠確實地做到這一點,我會。不過,無論如何,我仍然不好。所以我給你的是我懷疑是罪魁禍首的路線,但我現在有了一定的方法。我真的很感謝alextsc給出的建議。我會試試這個。 – 2011-12-22 04:06:54

回答

1

你有

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
在AndroidManifest.xml中

+0

我沒有那個,我完全忘了它。謝謝!但它仍然不保存圖像。 – 2011-12-22 05:23:36

+0

這與「Environment.getExternalStorageDirectory()」一起解決了問題! – 2011-12-22 16:19:58