2014-04-05 53 views
0

我對Android非常陌生,正試圖做一些簡單的事情:使用相機API,我想捕獲圖像並將其保存到目錄。Android:保存時捕獲的圖像爲零字節

我認爲我的主要問題是picturecallback()類。通過此代碼,我可以將JPEG圖像保存到SD卡上的已知目錄中。我可以看到它在正確的位置;但是,文件大小爲0字節,無法打開。

這裏是我的代碼:

PictureCallback myPictureCallback_JPG = new PictureCallback(){ 

    @Override 
    public void onPictureTaken(byte[] arg0, Camera arg1) { 
    // TODO Auto-generated method stub 

    if (arg0 == null){ 
     Toast.makeText(AndroidCamera.this, 
        "Image not saved. ", 
        Toast.LENGTH_LONG).show(); 
     return; 
     //Why is it returning NULL the first time and a 0-byte thing next... 
    } 


    File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); 
    if (pictureFile == null){ 
     System.out.println("Error creating media file, check storage permissions: "); 
     return; 
    } 

//  
    Uri uriTarget = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues()); 

    try { 

     FileOutputStream fos = new FileOutputStream(pictureFile); 
     fos.write(arg0); 
     fos.close(); 

    Toast.makeText(AndroidCamera.this, 
     "Image saved: " + uriTarget.toString(), 
     Toast.LENGTH_LONG).show(); 

    } catch (FileNotFoundException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } catch (IOException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 

    camera.startPreview(); 
    }}; 

當通過調試去,字節數組arg0中似乎包含了很多隨機數從-255到255,我不知道爲什麼任何圖像值將apear除了它們並沒有被正確捕獲到第一個位置(捕獲發生在oncreate)之外。

這裏是主類:

package com.example.androidcamera; 

import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.text.SimpleDateFormat; 
import java.util.Date; 

//import com.example.androidcamera.R; 

import android.app.Activity; 
import android.content.ContentValues; 
import android.content.pm.ActivityInfo; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Matrix; 
import android.graphics.Paint; 
import android.graphics.PixelFormat; 
import android.hardware.Camera; 
import android.hardware.Camera.AutoFocusCallback; 
import android.hardware.Camera.PictureCallback; 
import android.hardware.Camera.ShutterCallback; 
import android.net.Uri; 
import android.os.Bundle; 
import android.os.Environment; 
import android.provider.MediaStore.Images.Media; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.ViewGroup.LayoutParams; 
import android.widget.Button; 
import android.widget.LinearLayout; 
import android.widget.Toast; 

public class AndroidCamera extends Activity implements SurfaceHolder.Callback{ 

Camera camera; 
SurfaceView surfaceView; 
SurfaceHolder surfaceHolder; 
boolean previewing = false; 
LayoutInflater controlInflater = null; 

Button buttonTakePicture; 

final int RESULT_SAVEIMAGE = 0; 
public static final int MEDIA_TYPE_IMAGE = 1; 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 

     getWindow().setFormat(PixelFormat.UNKNOWN); 
     surfaceView = (SurfaceView)findViewById(R.id.camerapreview); 
     surfaceHolder = surfaceView.getHolder(); 
     surfaceHolder.addCallback(this); 
     surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

     controlInflater = LayoutInflater.from(getBaseContext()); 
     View viewControl = controlInflater.inflate(R.layout.control, null); 
     LayoutParams layoutParamsControl 
     = new LayoutParams(LayoutParams.FILL_PARENT, 
     LayoutParams.FILL_PARENT); 
     this.addContentView(viewControl, layoutParamsControl); 

     buttonTakePicture = (Button)findViewById(R.id.takepicture); 
     buttonTakePicture.setOnClickListener(new Button.OnClickListener(){ 
      @Override 
      public void onClick(View arg0) { 
      // TODO Auto-generated method stub 
      //camera.takePicture(myShutterCallback, 
       //myPictureCallback_JPG, myPictureCallback_JPG); 
       camera.takePicture(null, null, myPictureCallback_JPG); 
      } 
     }); 

     LinearLayout layoutBackground = (LinearLayout)findViewById(R.id.background); 
     layoutBackground.setOnClickListener(new LinearLayout.OnClickListener(){ 

    @Override 
    public void onClick(View arg0) { 
    // TODO Auto-generated method stub 

    buttonTakePicture.setEnabled(false); 
    camera.autoFocus(myAutoFocusCallback); 
    //camera. 
    }}); 
    } 

    AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback(){ 

    @Override 
    public void onAutoFocus(boolean arg0, Camera arg1) { 
    // TODO Auto-generated method stub 
    buttonTakePicture.setEnabled(true); 
    }}; 

    ShutterCallback myShutterCallback = new ShutterCallback(){ 

    @Override 
    public void onShutter() { 
    // TODO Auto-generated method stub 

    }}; 

PictureCallback myPictureCallback_RAW = new PictureCallback(){ 

    @Override 
    public void onPictureTaken(byte[] arg0, Camera arg1) { 
    // TODO Auto-generated method stub 

    }}; 

PictureCallback myPictureCallback_JPG = new PictureCallback(){ 

    @Override 
    public void onPictureTaken(byte[] arg0, Camera arg1) { 
    // TODO Auto-generated method stub 

    if (arg0 == null){ 
     Toast.makeText(AndroidCamera.this, 
        "Image not saved. ", 
        Toast.LENGTH_LONG).show(); 
     return; 
     //Why is it returning NULL the first time and a 0-byte thing next... 
    } 


    File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); 
    if (pictureFile == null){ 
     System.out.println("Error creating media file, check storage permissions: "); 
     return; 
    } 

//  
    Uri uriTarget = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues()); 

    try { 

     FileOutputStream fos = new FileOutputStream(pictureFile); 
     fos.write(arg0); 
     fos.close(); 

    Toast.makeText(AndroidCamera.this, 
     "Image saved: " + uriTarget.toString(), 
     Toast.LENGTH_LONG).show(); 

    } catch (FileNotFoundException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } catch (IOException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 

    camera.startPreview(); 
    }}; 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
    int height) { 
    // TODO Auto-generated method stub 
    if(previewing){ 
    camera.stopPreview(); 
    previewing = false; 
    } 

    if (camera != null){ 
    try { 
    camera.setPreviewDisplay(surfaceHolder); 
    camera.startPreview(); 
    previewing = true; 
    } catch (IOException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } 
    } 
} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    // TODO Auto-generated method stub 
    camera = Camera.open(); 
} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    // TODO Auto-generated method stub 
    camera.stopPreview(); 
    camera.release(); 
    camera = null; 
    previewing = false; 
} 

/** Create a File for saving an image or video */ 
private static File getOutputMediaFile(int type){ 
    // To be safe, you should check that the SDCard is mounted 
    // using Environment.getExternalStorageState() before doing this. 

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
       Environment.DIRECTORY_PICTURES), "MyCameraApp"); 
    // This location works best if you want the created images to be shared 
    // between applications and persist after your app has been uninstalled. 

    // Create the storage directory if it does not exist 
    if (! mediaStorageDir.exists()){ 
     if (! mediaStorageDir.mkdirs()){ 
      Log.d("MyCameraApp", "failed to create directory"); 
      return null; 
     } 
    } 

    // Create a media file name 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
    File mediaFile; 
    if (type == MEDIA_TYPE_IMAGE){ 
     mediaFile = new File(mediaStorageDir.getPath() + File.separator + 
     "IMG_"+ timeStamp + ".jpg"); 
    } else { 
     return null; 
    } 

    return mediaFile; 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    releaseCamera();    // release the camera immediately on pause event 
} 

private void releaseCamera(){ 
    if (camera != null){ 
     camera.release();  // release the camera for other applications 
     camera = null; 
    } 
} 

} 

我AndroidManifest文件:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.androidcamera" 
    android:versionCode="1" 
    android:versionName="1.0"> 
    <application android:icon="@drawable/ic_launcher" android:label="@string/app_name"> 
     <activity android:name="AndroidCamera" 
       android:label="@string/app_name"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

    </application> 
    <uses-sdk android:minSdkVersion="8" /> 
    <uses-permission android:name="android.permission.CAMERA"></uses-permission> 
    <uses-feature android:name="android.hardware.camera" /> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
    <uses-feature android:name="android.hardware.camera.autofocus" /> 
</manifest> 

最後我主要的XML文件:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/background" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:gravity="bottom" 
    > 
<Button 
android:id="@+id/takepicture" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:text=" * Take Picture " 
android:layout_gravity="right" 
android:layout_margin="10dp" 
/> 
</LinearLayout> 

提前非常感謝。

回答

0

如果arg0[]中的數字看起來很奇怪,請不要擔心。這是因爲Java沒有unsigned byte原始數據類型。

在您的文件保存代碼,請注意您顯示吐司

"Image saved: " + uriTarget.toString() 

write()實際上恰好

File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); 

也許你會發現,圖像存儲,但不是在我所預期他們。

+0

謝謝,果然實際的圖像在別處結束了。令人困惑的是,在我重啓手機之前,我實際上無法看到其他目錄中的圖像!這是正常的嗎? – user3502402

+0

這不是_normal_,但預計。要「查看」添加的照片,[運行MediaScanner](http://developer.android.com/training/camera/photobasics.html#TaskGallery)。 –

相關問題