onPictureTaken从来没有所谓的 [英] onPictureTaken never called

查看:129
本文介绍了onPictureTaken从来没有所谓的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在code作品大多正常。唯一的问题是,onPictureTaken函数永远不会被调用。我需要使用此功能可以存储图像到SD卡。

MainActivity

 公共类MainActivity延伸活动{//私有静态相机mCamera;
//私人相机preVIEW米preVIEW;
私有静态字符串标记=CamraOne;@覆盖
公共无效的onCreate(捆绑savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.camera_layout);
    Log.d(TAG的setContentView结束);
    意向意图=新意图(这一点,CameraServiceOne.class);
    Log.d(TAG,启动意图);
    startService(意向);
    Log.d(TAG,在bkgrd运行);}

相机服务

CameraService

 公共类CameraServiceOne延伸服务{
私人SurfaceHolder史荷特;
//一个变量来控制相机
私有静态相机mCamera;
//摄像机参数
私人参数参数;
私有静态字符串标记=摄像机一体;
/ **当第一次创建活动调用。 * /@覆盖
公共无效的onCreate()
{
    super.onCreate();}
@覆盖
公共无效调用onStart(意向意图,诠释startId){
// TODO自动生成方法存根
super.onStart(意向,startId);mCamera = Camera.open();
SurfaceView SV =新SurfaceView(getApplicationContext());
尝试{
mCamera.set previewDisplay(sv.getHolder());
参数= mCamera.getParameters();//设置相机参数
mCamera.setParameters(参数);
mCamera.start preVIEW();
视频下载(1000);
Log.d(TAG,以PIC);
mCamera.takePicture(NULL,NULL,MCALL);
Log.d(TAG,PIC结束);
视频下载(5000);
mCamera.stop preVIEW();
mCamera.release();
}赶上(IOException异常五){
// TODO自动生成catch块
e.printStackTrace();
}赶上(InterruptedException的E){
// TODO自动生成catch块
e.printStackTrace();
}
//获取表面
史荷特= sv.getHolder();
//告诉Android这个表面都会有它的数据不断更换
sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}公共静态Camera.PictureCallback MCALL =新Camera.PictureCallback()
{
公共无效onPictureTaken(字节[]数据,相机摄像头)
{
mCamera = NULL;
Log.d(TAG,回调);
//德code。通过相机获得成位图数据
/ *
FileOutputStream中outStream = NULL;
尝试{
outStream =新的FileOutputStream(/ SD卡/ image.jpg文件);
Log.d(TAG,写PIC);
outStream.write(数据);
Log.d(TAG写入结束);
outStream.close();
}赶上(FileNotFoundException异常五){
Log.d(照相机,e.getMessage());
}赶上(IOException异常五){
Log.d(照相机,e.getMessage());
}
* /文件PictureFile的= getOutputMediaFile(MEDIA_TYPE_IMAGE);
如果(PictureFile的== NULL){
Log.d(TAG错误创建媒体文件,检查存储权限:);
返回;
}尝试{
FOS的FileOutputStream =新的FileOutputStream(PictureFile的);
fos.write(数据);
fos.close();
/ *
文件mediaStorageDir =新的文件(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES),MyCameraApp);
sendBroadcast(新意图(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse(文件://+ mediaStorageDir)));
* /
}赶上(FileNotFoundException异常五){
Log.d(TAG,找不到文件:+ e.getMessage());
}赶上(IOException异常五){
Log.d(TAG,访问文件时出错:+ e.getMessage());
}
}
};
@覆盖
公众的IBinder onBind(意向意图){
// TODO自动生成方法存根
返回null;
}公共静态最终诠释MEDIA_TYPE_IMAGE = 1;
公共静态最终诠释MEDIA_TYPE_VIDEO = 2;/ **创建一个开放的文件保存图像或视频* /
私有静态乌里getOutputMediaFileUri(整型){返回Uri.fromFile(getOutputMediaFile(类型));
}/ **保存图像或视频创建文件* /
私有静态文件getOutputMediaFile(整型){
//为了安全起见,你应该检查SD卡安装
//这样做之前,使用Environment.getExternalStorageState()。
如果(Environment.getExternalStorageDirectory()== NULL){
Log.d(MyCameraApp,getExternalStorageDirectory空);
}
文件mediaStorageDir =新的文件(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES),CameraServiceOne);
      //如果你想共享的创建的映像这个位置效果最佳
      //应用程序之间以及您的应用程序已被卸载后仍然存在。      //创建存储目录,如果它不存在
      如果(!mediaStorageDir.exists()){
          如果(!mediaStorageDir.mkdirs()){
              Log.d(MyCameraApp,无法创建目录路径:+
mediaStorageDir.getPath());
              返回null;
          }
      }      //创建一个媒体文件名
      字符串的timeStamp =新的SimpleDateFormat(YYYYMMDD_HHMMSS)格式(新的Date());
      文件媒体文件;
      Log.d(TAG,写媒体文件);
      如果(类型== MEDIA_TYPE_IMAGE){
          媒体文件=新的文件(mediaStorageDir.getPath()+文件分割符+
          IMG _+ +的timeStamp.JPG);
      }否则如果(类型== MEDIA_TYPE_VIDEO){
          媒体文件=新的文件(mediaStorageDir.getPath()+文件分割符+
          VID _+的timeStamp +.MP4);
      }其他{
          返回null;
      }      返回媒体文件;
  }

的Manifest.xml

 <?XML版本=1.0编码=UTF-8&GT?;
<清单的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
包=com.example.cameraone
安卓版code =1
机器人:=的versionName1.0><使用许可权的android:NAME =android.permission.CAMERA/>
<使用许可权的android:NAME =android.permission.WRITE_EXTERNAL_STORAG​​E/>
<用途-SDK
    安卓的minSdkVersion =19
    机器人:targetSdkVersion =19/><应用
    机器人:allowBackup =真
    机器人:图标=@绘制/ ic_launcher
    机器人:标签=@字符串/ APP_NAME
    机器人:主题=@风格/ AppTheme>    <服务机器人。CameraServiceOneNAME = />
    <活动
        机器人:名字=com.example.cameraone.MainActivity
        机器人:标签=@字符串/ APP_NAME>
        &所述;意图滤光器>
            <作用机器人:名字=android.intent.action.MAIN/>            <类机器人:名字=android.intent.category.LAUNCHER/>
        &所述; /意图滤光器>
    < /活性GT;
< /用途>< /清单>

更新CameraService

 公共类CameraServiceOne扩展服务实现SurfaceHolder.Callback {
  私人SurfaceHolder史荷特;
  //一个变量来控制相机
  私有静态相机mCamera;
  //摄像机参数
  私人参数参数;
  私有静态字符串标记=摄像机一体;
  / **当第一次创建活动调用。 * /
@覆盖
公共无效的onCreate()
{
    super.onCreate();}
@覆盖
公共无效调用onStart(意向意图,诠释startId){
  // TODO自动生成方法存根
  super.onStart(意向,startId);
  Log.d(TAG,关于启动);
   mCamera = Camera.open();
   //改变SV为findViewByID
   // SurfaceView SV =新SurfaceView(getApplicationContext());   LayoutInflater吹气=(LayoutInflater)
           getSystemService(LAYOUT_INFLATER_SERVICE);
         查看布局= inflater.inflate(R.layout.camera_layout,NULL);
         SurfaceView SV =(SurfaceView)layout.findViewById(R.id.camera_surfaceview);
          参数= mCamera.getParameters();
          mCamera.setParameters(参数);          mCamera.start preVIEW();
          Log.d(TAG,启动preVIEW);
         sv.post(新的Runnable(){公共无效的run(){mCamera.takePicture(NULL,NULL,MCALL);}});
/ *
   尝试{
              mCamera.set previewDisplay(sv.getHolder());
              参数= mCamera.getParameters();               //设置相机参数
             mCamera.setParameters(参数);
             mCamera.start preVIEW();
             视频下载(1000);
             Log.d(TAG,以PIC);
             mCamera.takePicture(NULL,NULL,MCALL);
             Log.d(TAG,PIC结束);
             视频下载(5000);
             mCamera.stop preVIEW();
             mCamera.release();
        }赶上(IOException异常五){
              // TODO自动生成catch块
              e.printStackTrace();
        }赶上(InterruptedException的E){
            // TODO自动生成catch块
            e.printStackTrace();
        }
* /   //获取表面
     史荷特= sv.getHolder();
    //告诉Android这个表面都会有它的数据不断更换
     sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}公共静态Camera.PictureCallback MCALL =新Camera.PictureCallback()
{
   公共无效onPictureTaken(字节[]数据,相机摄像头)
   {
       mCamera = NULL;
       Log.d(TAG,回调);
         //德code。通过相机获得成位图数据
       / *
         FileOutputStream中outStream = NULL;
              尝试{
                  outStream =新的FileOutputStream(/ SD卡/ image.jpg文件);
                  登录.D(TAG,写PIC);
                  outStream.write(数据);
                  Log.d(TAG写入结束);
                  outStream.close();
              }赶上(FileNotFoundException异常五){
                  Log.d(照相机,e.getMessage());
              }赶上(IOException异常五){
                  Log.d(照相机,e.getMessage());
              }
    * /        文件PictureFile的= getOutputMediaFile(MEDIA_TYPE_IMAGE);
        如果(PictureFile的== NULL){
            Log.d(TAG错误创建媒体文件,检查存储权限:);
            返回;
        }        尝试{
            FOS的FileOutputStream =新的FileOutputStream(PictureFile的);
            fos.write(数据);
            fos.close();
            / *
            文件mediaStorageDir =新的文件(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES),MyCameraApp);
            sendBroadcast(新意图(Intent.ACTION_MEDIA_MOUNTED,
            Uri.parse(文件://+ mediaStorageDir)));
            * /
        }赶上(FileNotFoundException异常五){
            Log.d(TAG,找不到文件:+ e.getMessage());
        }赶上(IOException异常五){
            Log.d(TAG,访问文件时出错:+ e.getMessage());
        }
   }
};
  @覆盖
  公众的IBinder onBind(意向意图){
        // TODO自动生成方法存根
        返回null;
  }  公共静态最终诠释MEDIA_TYPE_IMAGE = 1;
  公共静态最终诠释MEDIA_TYPE_VIDEO = 2;  / **创建一个开放的文件保存图像或视频* /
  私有静态乌里getOutputMediaFileUri(整型){        返回Uri.fromFile(getOutputMediaFile(类型));
  }  / **保存图像或视频创建文件* /
  私有静态文件getOutputMediaFile(整型){
      //为了安全起见,你应该检查SD卡安装
      //这样做之前,使用Environment.getExternalStorageState()。
    如果(Environment.getExternalStorageDirectory()== NULL){
        Log.d(MyCameraApp,getExternalStorageDirectory空);
    }
      文件mediaStorageDir =新的文件(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES),CameraServiceOne);
      //如果你想共享的创建的映像这个位置效果最佳
      //应用程序之间以及您的应用程序已被卸载后仍然存在。      //创建存储目录,如果它不存在
      如果(!mediaStorageDir.exists()){
          如果(!mediaStorageDir.mkdirs()){
              Log.d(MyCameraApp,无法创建目录路径:+ mediaStorageDir.getPath());
              返回null;
          }
      }      //创建一个媒体文件名
      字符串的timeStamp =新的SimpleDateFormat(YYYYMMDD_HHMMSS)格式(新的Date());
      文件媒体文件;
      Log.d(TAG,写媒体文件);
      如果(类型== MEDIA_TYPE_IMAGE){
          媒体文件=新的文件(mediaStorageDir.getPath()+文件分割符+
          IMG _+ +的timeStamp.JPG);
      }否则如果(类型== MEDIA_TYPE_VIDEO){
          媒体文件=新的文件(mediaStorageDir.getPath()+文件分割符+
          VID _+的timeStamp +.MP4);
      }其他{
          返回null;
      }      返回媒体文件;
  } @覆盖
  公共无效surfaceCreated(SurfaceHolder持有人){
      //表面有被创建,现在告诉相机在哪里画preVIEW。
  }
@覆盖
公共无效surfaceChanged(SurfaceHolder为arg0,ARG1 INT,INT ARG2,诠释ARG3){
    // TODO自动生成方法存根}
@覆盖
公共无效surfaceDestroyed(SurfaceHolder为arg0){
    // TODO自动生成方法存根
}


解决方案

您正确地发现, takePicture()不应该被称为启动preVIEW()或紧随其后。但不幸的是它是不够的,增加额外的睡眠()之间。

诀窍是,有才能的问题,必须执行少数回调 takePicture():一个SurfaceView必须做好准备,和preVIEW开始玩这个SurfaceView。

所以,首先你必须显示 SV 视图。你可以简单地prepare一个SurfaceView作为camera_layout.xml的一部分,而不是调用新SurfaceView(getApplicationContext())使用 findViewById(R .id.camera_surface_view)

二,添加实现SurfaceHolder.Callback 你的 CameraServiceOne 类,并实现回调(例如见了Android教程)。

现在,你可以的发布的(异步执行的另一个层面) takePicture()直接从 SurfaceCreated()

  sv.post(新的Runnable(){公共无效的run(){mCamera.takePicture(NULL,NULL,MCALL);}}});

最后,可以考虑使用一个后台线程Camera.open()和配置(如的AsyncTask ):这些冗长的操作可能会冻结UI(主)线程不可接受的长时间。

The code works mostly fine. The only problem is that the onPictureTaken function never called. I need to use this function to store the image to SD Card.

MainActivity

public class MainActivity extends Activity {

//private static Camera mCamera;
//private CameraPreview mPreview;
private static String TAG = "CamraOne";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.camera_layout);
    Log.d(TAG, "setContentView end");
    Intent intent = new Intent(this, CameraServiceOne.class);
    Log.d(TAG,"start intent");
    startService(intent);
    Log.d(TAG,"run in bkgrd");

}

Camera Service

CameraService

public class CameraServiceOne extends Service{
private SurfaceHolder sHolder; 
//a variable to control the camera
private static Camera mCamera;
//the camera parameters
private Parameters parameters;
private static String TAG = "CameraOne";
/** Called when the activity is first created. */



@Override
public void onCreate()
{
    super.onCreate();

}
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);

mCamera = Camera.open();
SurfaceView sv = new SurfaceView(getApplicationContext());


try {
mCamera.setPreviewDisplay(sv.getHolder());
parameters = mCamera.getParameters();

//set camera parameters
mCamera.setParameters(parameters);
mCamera.startPreview();
Thread.sleep(1000);
Log.d(TAG,"take pic");
mCamera.takePicture(null, null, mCall);
Log.d(TAG,"pic end");
Thread.sleep(5000);
mCamera.stopPreview();
mCamera.release();


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


//Get a surface
sHolder = sv.getHolder();
//tells Android that this surface will have its data constantly replaced
sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}



public static Camera.PictureCallback mCall = new Camera.PictureCallback()
{
public void onPictureTaken(byte[] data, Camera camera)
{   
mCamera = null;
Log.d(TAG,"in callback");
//decode the data obtained by the camera into a Bitmap
/*
FileOutputStream outStream = null;
try{
outStream = new FileOutputStream("/sdcard/Image.jpg");
Log.d(TAG,"write pic");
outStream.write(data);
Log.d(TAG,"write end");
outStream.close();
} catch (FileNotFoundException e){
Log.d("CAMERA", e.getMessage());
} catch (IOException e){
Log.d("CAMERA", e.getMessage());
}
*/

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

try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
/*
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
Uri.parse("file://"+ mediaStorageDir)));
*/
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};


@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}



public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){

return Uri.fromFile(getOutputMediaFile(type));
}

/** 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.
if(Environment.getExternalStorageDirectory() == null){
Log.d("MyCameraApp","getExternalStorageDirectory null");
}
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "CameraServiceOne");
      // 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 path: " +    
mediaStorageDir.getPath());
              return null;
          }
      }

      // Create a media file name
      String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
      File mediaFile;
      Log.d(TAG,"write mediafile");
      if (type == MEDIA_TYPE_IMAGE){
          mediaFile = new File(mediaStorageDir.getPath() + File.separator +
          "IMG_"+ timeStamp + ".jpg");
      } else if(type == MEDIA_TYPE_VIDEO) {
          mediaFile = new File(mediaStorageDir.getPath() + File.separator +
          "VID_"+ timeStamp + ".mp4");
      } else {
          return null;
      }

      return mediaFile;
  }

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cameraone"
android:versionCode="1"
android:versionName="1.0" >

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


<uses-sdk
    android:minSdkVersion="19"
    android:targetSdkVersion="19" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <service android:name=".CameraServiceOne"/>
    <activity
        android:name="com.example.cameraone.MainActivity"
        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>

</manifest>

Updated CameraService

public class CameraServiceOne extends Service implements SurfaceHolder.Callback{
  private SurfaceHolder sHolder; 
  //a variable to control the camera
  private static Camera mCamera;
  //the camera parameters
  private Parameters parameters;
  private static String TAG = "CameraOne";
  /** Called when the activity is first created. */
@Override
public void onCreate()
{
    super.onCreate();

}
@Override
public void onStart(Intent intent, int startId) {
  // TODO Auto-generated method stub
  super.onStart(intent, startId);
  Log.d(TAG,"on start");
   mCamera = Camera.open();
   //change sv to findViewByID
   //SurfaceView sv = new SurfaceView(getApplicationContext());

   LayoutInflater inflater = (LayoutInflater)
           getSystemService(LAYOUT_INFLATER_SERVICE);
         View layout = inflater.inflate(R.layout.camera_layout, null);
         SurfaceView sv = (SurfaceView) layout.findViewById(R.id.camera_surfaceview);
          parameters = mCamera.getParameters();
          mCamera.setParameters(parameters);

          mCamera.startPreview();
          Log.d(TAG,"startPreview");
         sv.post(new Runnable() { public void run() { mCamera.takePicture(null, null, mCall); } });
/*
   try {
              mCamera.setPreviewDisplay(sv.getHolder());
              parameters = mCamera.getParameters();

               //set camera parameters
             mCamera.setParameters(parameters);
             mCamera.startPreview();
             Thread.sleep(1000);
             Log.d(TAG,"take pic");
             mCamera.takePicture(null, null, mCall);
             Log.d(TAG,"pic end");
             Thread.sleep(5000);
             mCamera.stopPreview();
             mCamera.release();


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

   //Get a surface
     sHolder = sv.getHolder();
    //tells Android that this surface will have its data constantly replaced
     sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public static Camera.PictureCallback mCall = new Camera.PictureCallback()
{
   public void onPictureTaken(byte[] data, Camera camera)
   {    
       mCamera = null;
       Log.d(TAG,"in callback");
         //decode the data obtained by the camera into a Bitmap
       /*
         FileOutputStream outStream = null;
              try{
                  outStream = new FileOutputStream("/sdcard/Image.jpg");
                  Log   .d(TAG,"write pic");
                  outStream.write(data);
                  Log.d(TAG,"write end");
                  outStream.close();
              } catch (FileNotFoundException e){
                  Log.d("CAMERA", e.getMessage());
              } catch (IOException e){
                  Log.d("CAMERA", e.getMessage());
              }
    */

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

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
            /*
            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "MyCameraApp");
            sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
            Uri.parse("file://"+ mediaStorageDir)));
            */
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
   }
};


  @Override
  public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
  }



  public static final int MEDIA_TYPE_IMAGE = 1;
  public static final int MEDIA_TYPE_VIDEO = 2;

  /** Create a file Uri for saving an image or video */
  private static Uri getOutputMediaFileUri(int type){

        return Uri.fromFile(getOutputMediaFile(type));
  }

  /** 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.
    if(Environment.getExternalStorageDirectory() == null){
        Log.d("MyCameraApp","getExternalStorageDirectory null");
    }
      File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "CameraServiceOne");
      // 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 path: " + mediaStorageDir.getPath());
              return null;
          }
      }

      // Create a media file name
      String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
      File mediaFile;
      Log.d(TAG,"write mediafile");
      if (type == MEDIA_TYPE_IMAGE){
          mediaFile = new File(mediaStorageDir.getPath() + File.separator +
          "IMG_"+ timeStamp + ".jpg");
      } else if(type == MEDIA_TYPE_VIDEO) {
          mediaFile = new File(mediaStorageDir.getPath() + File.separator +
          "VID_"+ timeStamp + ".mp4");
      } else {
          return null;
      }

      return mediaFile;
  }

 @Override
  public void surfaceCreated(SurfaceHolder holder) {
      // The Surface has been created, now tell the camera where to draw the preview.
  }       
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    // TODO Auto-generated method stub

}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
    // TODO Auto-generated method stub
}

解决方案

You correctly found that takePicture() should not be called before startPreview() or immediately after it. But unfortunately it's not enough to add extra sleep() between them.

The trick is that there are few callbacks that must be executed before you can issue takePicture(): a SurfaceView must be ready, and preview start playing on this SurfaceView.

So, first of all you must display the sv view. You can simply prepare a SurfaceView as part of camera_layout.xml, and instead of calling new SurfaceView(getApplicationContext()) use findViewById(R.id.camera_surface_view).

Second, add implements SurfaceHolder.Callback to your CameraServiceOne class, and implement the callbacks (see e.g. the Android tutorial).

Now, you can post (another level of async execution) takePicture() directly from the SurfaceCreated():

sv.post(new Runnable() { public void run() { mCamera.takePicture(null, null, mCall); } } });

Finally, consider using a background thread (e.g. AsyncTask) for Camera.open() and configuration: these lengthy operations may freeze the UI (main) thread for unacceptably long time.

这篇关于onPictureTaken从来没有所谓的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆