2014-03-25 12 views
6

ich ein wirklich seltsames Problem haben. Der folgende Code Ich habe verwendet, um ein Bild auf Tastenklick zu nehmen. Es funktioniert auf Jelly Bean Handys, aber nicht auf Kitkat:Kamera-API funktioniert nicht auf 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; 
} 
} 

Manifest-Datei:

<?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> 

Ich habe einige Toast-Nachrichten und Druckanweisungen für Debugging-Zwecke gesetzt. Ich habe nicht logcat hier gepostet, weil, wenn ich dies auf einem KitKat Telefon laufen, ich nichts auf logcat. Keine Ausnahme oder Warnung.

Wenn ich dies auf einem Telefon jellybean läuft, läuft es richtig, zeigt alle Toasts und druckt und macht das Bild.

Als ich das laufe auf Kitkat, ich erhalte keine Debug-Meldungen nach den

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

Ich vermute Problem mit dem Takepicture-API ist, aber ich bin nicht in der Lage, es zu debuggen.

Bitte helfen Sie mir, dieses Problem zu lösen.

EDIT: Nach weiterer Analyse fand ich den Grund für die Ausgabe. Das PhotoHandler Objekt wird erfolgreich aufgerufen, aber die onPictureTaken Methode wird nicht genannt, wahrscheinlich weil es keine Informationen bekommen hat, dass von der Kamera geklickt wurde. Ich weiß nicht warum. Bitte helfen Sie mir, dieses Problem zu beheben.

+0

prüfen untenstehenden Link Hilfe Sie http://stackoverflow.com/questions/22576049/gallery-has-stopped-while-cropping-image-in-kitkat-nexus7 – KeTaN

+0

Mein Problem nicht mit Galerie ist .. seiner wahrscheinlich mit der takePicture API. Außerdem bekomme ich keine Ausnahmen wie in diesem Post. – SoulRayder

+0

Haben Sie versucht, einen Debugger anzuhängen und ihn einzeln zu durchlaufen, um zu sehen, wo es hingeht? – fadden

Antwort

5

Ich habe festgestellt, dass Sie der Kamera keinen Oberflächenhalter zuweisen. Es ist wichtig, der Kamera eine Vorschauoberfläche zu geben.

Nach den docs hier:

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

folgen Sie den Code durch den doc vorgeschlagen. Das Fotografieren ohne Vorschau ist ein großes Sicherheitsrisiko. Android-Leute könnten dies in kitkat behoben haben.

Sie haben diesen Teil des Codes vielleicht verpasst, während hier einfügen, um eine zusätzliche Sorge auch überprüfen, ob Sie Ihren Code ausführen ‚camera.takePicture (null, null, Rückruf)‘ innerhalb der Callback-Methode ‚onSurfaceCreated‘ von SurfaceHolder .

Sie können den gesamten relevanten Code oben genannten Link erhalten.

+0

Ihr Link hat mir sehr geholfen :) Der Hauptfehler, den ich gemacht habe, war nicht die Zuweisung einer Oberfläche Halter. Anscheinend ist dies eine Notwendigkeit für Kitkat-Telefone, während es ohne es in JB-Telefonen funktioniert. Danke für Ihre Hilfe. :) – SoulRayder

+0

glücklich zu helfen :) –

2

Garbage Collection des KitKat funktioniert anders als die bisherigen APIs.

Ich vermute, dass das PhotoHandler Objekt, das Sie an die takePicture() Methode übergeben wird Mülltonne vor onPictureTaken gesammelt immer aufgerufen werden.

Versuchen Sie, in Ihrer MainActivity ein PhotoHandler Objekt als Instanzvariable zu erstellen.

An der Spitze der Klasse:

PhotoHandler photoHandler; 

Dann in onCreate()

photoHandler = new PhotoHandler(getApplicationContext()); 

Dann, wenn Sie anrufen takePicture():

camera.takePicture(null, null, photoHandler); 
+0

Scheint logisch .. wird akzeptieren, sobald ich es ausprobiere und es funktioniert – SoulRayder

+0

Ich versuchte Ihren Ansatz, es funktioniert nicht. Wenn Sie "an der Spitze der Klasse" für PhotoHandler sagen, meinen Sie als ein Klassenmitglied oder * außerhalb * der Klasse? – SoulRayder

+0

Klassenmitglied - sie werden Instanzvariablen in Java –

1

hinzufügen uses-feature in Ihrer Manifest-Datei:

<uses-feature android:name="android.hardware.camera" /> 
<uses-feature android:name="android.hardware.camera.autofocus" /> 

und überprüfen Sie diese link. Es könnte dir helfen.

Verwandte Themen