相机API适用于Jelly Bean,但不适用于Kitkat [英] Camera API working on Jelly Bean but not Kitkat

查看:74
本文介绍了相机API适用于Jelly Bean,但不适用于Kitkat的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常奇怪的问题.我使用的以下代码用于在单击按钮时拍照.它可以在Jelly Bean手机上正常运行,但不能在Kitkat上运行:

I have a really strange problem. The following code I have is used to take a picture on button click. It works properly on Jelly Bean phones, but not on Kitkat:

MainActivity.java :

package com.example.takepic;

import android.app.Activity;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;


public class MainActivity extends Activity {
  private final static String DEBUG_TAG = "MakePhotoActivity";
  private Camera camera;
  private Button capture = null;
  private int cameraId = 0;

  @Override
  public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  capture = (Button)findViewById(R.id.captureBack);
  capture.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
         camera.startPreview(); //After this, nothing gets printed, and picture does not get taken
        System.out.println("Camera preview has started.");
            camera.takePicture(null, null, new PhotoHandler(getApplicationContext()));
    }
});
// do we have a camera?
if (!getPackageManager()
    .hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
  Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG)
      .show();
} else {
  cameraId = findBackFacingCamera();
  if (cameraId < 0) {
    Toast.makeText(this, "No back facing camera found.",
        Toast.LENGTH_LONG).show();
  } else {
    camera = Camera.open(cameraId);
  }
}
  }



 private int findBackFacingCamera() {
int cameraId = -1;
// Search for the front facing camera
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
  CameraInfo info = new CameraInfo();
  Camera.getCameraInfo(i, info);
  if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
    Log.d(DEBUG_TAG, "Camera found");
    cameraId = i;
    break;
  }
}
return cameraId;
}

  @Override
  protected void onPause() {
if (camera != null) {
  camera.release();
  camera = null;
}
super.onPause();
 }

} 

PhotoHandler.java :

package com.example.takepic;



import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

public class PhotoHandler implements PictureCallback {

  private final Context context;

  public PhotoHandler(Context context) {
    this.context = context;
  }

  @Override
 public void onPictureTaken(byte[] data, Camera camera) {

   File pictureFileDir = getDir();
  Toast.makeText(context, "Entered onPictureTaken", Toast.LENGTH_LONG).show();
   if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {

  Log.d("Directory error", "Can't create directory to save image.");
  Toast.makeText(context, "Can't create directory to save image.",
      Toast.LENGTH_LONG).show();
  return;

 }

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_" + date + ".jpg";

String filename = pictureFileDir.getPath() + File.separator + photoFile;

File pictureFile = new File(filename);

try {
  FileOutputStream fos = new FileOutputStream(pictureFile);
  fos.write(data);
  fos.close();
  Toast.makeText(context, "New Image saved:" + photoFile,
      Toast.LENGTH_LONG).show();
} catch (Exception error) {
  Log.d("File saving error", "File" + filename + "not saved: "
      + error.getMessage());
  Toast.makeText(context, "Image could not be saved.",
      Toast.LENGTH_LONG).show();
  }
}

  private File getDir() {
  //  File sdDir =    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
 File sdDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
 Toast.makeText(context, ("Path : "+sdDir.getAbsolutePath()), Toast.LENGTH_LONG).show();
  return sdDir;
 }
} 

清单文件:

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

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.takepic.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>

出于调试目的,我已经投放了很多吐司消息和打印语句.我没有在此处发布logcat,因为当我在KitKat手机上运行logcat时,我在logcat上一无所获.没有例外或警告.

I have put quite a few toast messages and print statements for debugging purposes. I have not posted logcat here, because, when I run this on a KitKat phone, I get nothing on logcat. No exception or warning.

当我在豆形软糖手机上运行此程序时,它会正常运行,显示所有吐司和照片并拍照.

When I run this on a jellybean phone, it runs properly, displaying all the toasts and prints and takes the picture.

当我在 Kitkat 上运行此程序时,

When I run this on Kitkat, I do not get any debugging messages after the

camera.startPreview();
System.out.println("Camera preview has started.");

我怀疑takePicture API存在问题,但是我无法对其进行调试.

I suspect problem is with the takePicture API, but I am unable to debug it.

经过进一步分析,我找到了问题的原因. PhotoHandler 对象已成功调用,但是未调用 onPictureTaken 方法,这可能是因为它没有获取有关相机单击图片的信息.我不知道为什么.

After further analysis, I found the reason for issue. The PhotoHandler object gets invoked successfully, but the onPictureTaken method is not called, probably because it did not get information that picture was clicked by the camera. I don't know why.

推荐答案

我发现您没有为相机分配任何表面支架.为相机提供预览表面很重要.

I have observed that you are not assigning any surface holder to the camera. Giving a preview surface to the camera is important.

根据此处的文档:

http://developer.android.com/guide/topics/media/camera.html

遵循文档建议的代码.在没有预览的情况下拍照是一个很大的安全隐患. Android家伙可能已经在kitkat中修复了此问题.

follow the code suggested by the doc. Taking a picture without a preview is a big security concern. Android guys might have fixed this in kitkat.

您可能会在粘贴到此处时错过了代码的这一部分,因此,作为额外的关注,还要检查您是否正在SurfaceHolder的回调方法"onSurfaceCreated"内执行代码"camera.takePicture(null,null,callback)".

You might have missed that part of the code while pasting here so as an added concern also check that you are executing your code 'camera.takePicture(null,null,callback)' inside the callback method 'onSurfaceCreated' of SurfaceHolder.

您可以在上述链接中获得所有相关代码.

You can get all the relevant code at aforementioned link.

这篇关于相机API适用于Jelly Bean,但不适用于Kitkat的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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