我想在按下耳机按钮时用相机拍照。
但我收到运行时错误消息“无法启动接收器...takePictureFailed”。
米主活动:
public class MainActivity extends AppCompatActivity{
protected static Camera myCamera;
private CameraPreview mPreview;
int iCantCameras;
int iActiveCamera = 0;
Camera.Parameters cpParameters;
AudioManager am;
static Context context;
public static String appName;
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
appName = getString(R.string.app_name_long);
context = getApplicationContext();
// To register and unregister the receiver of the headset button
am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
}
@Override
protected void onResume(){
super.onResume();
// Check if there's a camera
if(!checkCameraHardware(this)){
Toast.makeText(this, R.string.no_camera_message, Toast.LENGTH_SHORT).show();
return;
}
// Start listening for button presses
am.registerMediaButtonEventReceiver(new ComponentName(this, Receiver.class));
// Get the number of cameras
iCantCameras = Camera.getNumberOfCameras();
// Activate the camera
if (iCantCameras > 0) {
activateCamera(iActiveCamera);
}
}
public static void takeP(){
// get an image from the camera
myCamera.takePicture(null, null, mPicture);
//Toast.makeText(context,"Botón presionado", Toast.LENGTH_SHORT).show();
}
public void takePhoto(View view){
// get an image from the camera
myCamera.takePicture(null, null, mPicture);
}
public void showFlashOptions(View view){
}
// Change between cameras
public void switchCamera(View view){
// Return if there are less than 2 cameras
if (iCantCameras < 2) {
return;
}
if (iActiveCamera == Camera.CameraInfo.CAMERA_FACING_BACK) {
iActiveCamera = Camera.CameraInfo.CAMERA_FACING_FRONT;
} else {
iActiveCamera = Camera.CameraInfo.CAMERA_FACING_BACK;
}
activateCamera(iActiveCamera);
}
// Activate the indicated camera
public void activateCamera(int cameraID){
// Get an instance of the camera
releaseCamera();
myCamera = getCameraInstance(cameraID);
if(myCamera == null){
Toast.makeText(this, R.string.no_access_to_camera, Toast.LENGTH_SHORT).show();
return;
}
// Get the camera parameters
cpParameters = myCamera.getParameters();
// Set the orientation of the camera
setCameraDisplayOrientation(this, 0, myCamera);
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, myCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.removeAllViews(); // This ensures the switch of cameras as this calls the mPreview.surfaceChanged method
preview.addView(mPreview);
}
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(int cameraID){
Camera c = null;
try {
c = Camera.open(cameraID); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
// Sets the orientation of the camera as the display
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
// release the camera for other applications
private void releaseCamera(){
if (myCamera != null){
myCamera.stopPreview();
myCamera.setPreviewCallback(null);
myCamera.release();
myCamera = null;
}
}
// This saves the picture into the storage
public static Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
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();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
// Gets the picture into media library
MediaScanner client = new MediaScanner(context, pictureFile, null);
}
};
/** Create a File for saving an image */
private static File getOutputMediaFile(){
// 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), appName);
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d(appName, "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
return mediaFile;
}
@Override
protected void onStop(){
super.onStop();
releaseCamera();
// Stop listening for button presses
am.unregisterMediaButtonEventReceiver(new ComponentName(this, Receiver.class));
}
@Override
protected void onDestroy(){
super.onDestroy();
releaseCamera();
// Stop listening for button presses
am.unregisterMediaButtonEventReceiver(new ComponentName(this, Receiver.class));
}
}
我的预习课:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("TAG", "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d("TAG", "Error starting camera preview: " + e.getMessage());
}
}
}
我的接收器类,我在其中调用 MainActivity 类的 takeP() 方法:
public class Receiver extends BroadcastReceiver {
// Constructor is mandatory
public Receiver ()
{
super ();
}
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
int key = event.getKeyCode();
switch (key) {
case KeyEvent.KEYCODE_BREAK:
case KeyEvent.KEYCODE_MEDIA_PLAY:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_MEDIA_STOP:
case KeyEvent.KEYCODE_HEADSETHOOK:
MainActivity.takeP();
break;
default:
break;
}
}
}
}
我的逻辑:
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: FATAL EXCEPTION: main
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: Process: com.garanal.photoclick, PID: 28252
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: java.lang.RuntimeException: Unable to start receiver com.garanal.photoclick.Receiver: java.lang.RuntimeException: takePicture failed
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.app.ActivityThread.handleReceiver(ActivityThread.java:2680)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.app.ActivityThread.access$1700(ActivityThread.java:156)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1428)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.os.Looper.loop(Looper.java:211)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5389)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:372)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: Caused by: java.lang.RuntimeException: takePicture failed
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.hardware.Camera.native_takePicture(Native Method)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.hardware.Camera.takePicture(Camera.java:1475)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.hardware.Camera.takePicture(Camera.java:1420)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at com.garanal.photoclick.MainActivity.takeP(MainActivity.java:82)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at com.garanal.photoclick.Receiver.onReceive(Receiver.java:33)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.app.ActivityThread.handleReceiver(ActivityThread.java:2673)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.app.ActivityThread.access$1700(ActivityThread.java:156)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1428)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.os.Looper.loop(Looper.java:211)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5389)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:372)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020)
10-30 20:10:43.257 28252-28252/? E/AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815)
感谢您给我的任何帮助以及来自哥伦比亚麦德林的问候。