Autore Topic: [medio] Come utilizzare la Camera di Android per scattare una foto  (Letto 36936 volte)

Offline Nokias

  • Utente junior
  • **
  • Post: 58
  • Respect: +1
    • Mostra profilo
Re:[medio] Come utilizzare la Camera di Android per scattare una foto
« Risposta #90 il: 08 Maggio 2013, 11:52:34 CEST »
0
Anche a me presenta lo stesso identico problema. Qualcuno sa il perché?

Offline DarnellNajanReed

  • Utente normale
  • ***
  • Post: 359
  • Respect: +49
    • Google+
    • Mostra profilo
  • Dispositivo Android:
    LG Optimus One, Acer Iconia A500/501, Asus Transformer Prime, Galaxy ACE, Galaxy S Plus, Galaxy S Advance P, Galaxy Tab 2 7.0, Google Nexus 7
  • Play Store ID:
    Luigi Notaro
  • Sistema operativo:
    OS X 10.8.3
Re:[medio] Come utilizzare la Camera di Android per scattare una foto
« Risposta #91 il: 08 Maggio 2013, 12:16:40 CEST »
0
"l'applicazione mi crasha" è un pelo generico... posta il LogCat e si può cominciare ad elucubrare  :-)

Offline OssoMasticato

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Note GT-N7000
  • Sistema operativo:
    Windows XP SP2/Win Vista
Re:[medio] Come utilizzare la Camera di Android per scattare una foto
« Risposta #92 il: 29 Maggio 2013, 21:49:42 CEST »
0
Ciao a tutti. Sto operando un mix tra codici che ho trovato per il salvataggio delle foto scattate con la mia app direttamente nelle cartelle foto del dispositivo. Ma non va. Devo aggiungere questa parte:

Codice (Java): [Seleziona]
/* Foto album per questa applicazione */
private String getAlbumName() {
         return getString(R.string.album_name);
}


private File getAlbumDir() {
        File storageDir = null;

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
               
                storageDir = mAlbumStorageDirFactory.getAlbumStorageDir(getAlbumName());

                if (storageDir != null) {
                        if (! storageDir.mkdirs()) {
                                if (! storageDir.exists()){
                                        Log.d("CameraSample", "impossibile creare la directory");
                                        return null;
                                }
                        }
                }
               
        } else {
                Log.v(getString(R.string.app_name), "La memoria esterna non è montata in LETTURA/SCRITTURA.");
        }
       
        return storageDir;
}

private File createImageFile() throws IOException {
        // Crea un nome per l'immagine
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = JPEG_FILE_PREFIX + timeStamp + "_";
        File albumF = getAlbumDir();
        File imageF = File.createTempFile(imageFileName, JPEG_FILE_SUFFIX, albumF);
        return imageF;
}


@SuppressWarnings("unused")
private File setUpPhotoFile() throws IOException {
       
        File f = createImageFile();
        mCurrentPhotoPath = f.getAbsolutePath();
       
        return f;
}



private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

private void setPic() {

        /* Non c'è abbastanza memoria per aprirepiù di un paio di foto */
        /* Quindi pre-scala il bitmap in quello decodificato */

        /* Ricava le dimensioni della SurfaceView */
        int targetW = mSurfaceView.getWidth();
        int targetH = mSurfaceView.getHeight();

        /* Ricava le dimensioni dell'immagine */
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
       
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;
       
        /* Capisce quale dimensione deve essere ridotta */
        int scaleFactor = 1;
        if ((targetW > 0) || (targetH > 0)) {
                scaleFactor = Math.min(photoW/targetW, photoH/targetH);
        }

        /* Imposta le opzioni bitmap  */
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inPurgeable = true;

        /* Decodifica il JPEG file in Bitmap */
        @SuppressWarnings("unused")
        Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
       


}

@SuppressWarnings("unused")
private void handleBigCameraPhoto() {

        if (mCurrentPhotoPath != null) {
                setPic();
                galleryAddPic();
                mCurrentPhotoPath = null;
        }

}

Naturalmente ho creato anche un file Java chiamato "AlbumStorageDirFactory" che non dà alcun problema. Ho già aggiunto anche

Codice (XML): [Seleziona]
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Il fatto è che per quanto abbia provato ad implementare il codice scritto sopra non ci son riuscito. Avete qualche idea?  Grazie!

Offline Deeniel

  • Nuovo arrivato
  • *
  • Post: 1
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xperia Arc S
  • Sistema operativo:
    Windows 7
Re:[medio] Come utilizzare la Camera di Android per scattare una foto
« Risposta #93 il: 01 Giugno 2013, 14:57:35 CEST »
0
Ho seguito questo tutorial ed altri e ogni volta mi crasha l'app prima ancora di partire. Per il momento vorrei solo visualizzare la preview della fotocamera, senza scattare nulla.

Manifest
Codice: [Seleziona]
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

Java Class
Codice: [Seleziona]
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;



public class MainActivity extends Activity implements SurfaceHolder.Callback{

    /* VARIABILI PRIVATE */
    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    private Camera mCamera;

    /** Called when the activity is first created. */
    @override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mSurfaceView = (SurfaceView)findViewById(R.id.surfaceView);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(this);
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }





    @override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {

        Camera.Parameters params = mCamera.getParameters();
        params.setPreviewSize(arg2, arg3);
        mCamera.setParameters(params);
        try {
            //lancio la preview
            mCamera.setPreviewDisplay(arg0);
            mCamera.startPreview();
        } catch (IOException e) {
            //gestione errore
        }

    }

    @override
    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open();

    }

    @override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mCamera.stopPreview();
        mCamera.release();

    }

LogCat
Codice: [Seleziona]
06-01 13:32:31.187      616-661/system_process                 I/ActivityManager: Start proc com.android.vending for service com.android.vending/com.google.android.finsky.services.ContentSyncService: pid=25552 uid=10005 gids={50005, 3003, 1015, 1028}
06-01 13:32:31.227  25552-25552/com.android.vending            E/Trace: error opening trace file: No such file or directory (2)
06-01 13:32:31.387      616-841/system_process                 I/ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.droidcam/.MainActivity bnds=[240,408][240,408]} from pid 861
06-01 13:32:31.437  25566-25566/?                              D/dalvikvm: Late-enabling CheckJNI
06-01 13:32:31.447     616-1341/system_process                 I/ActivityManager: Start proc com.example.droidcam for activity com.example.droidcam/.MainActivity: pid=25566 uid=10019 gids={50019, 1006, 1028}
06-01 13:32:31.607  25566-25566/com.example.droidcam           E/Trace: error opening trace file: No such file or directory (2)
06-01 13:32:31.787  25552-25552/com.android.vending            D/Finsky: [1] FinskyApp.onCreate: Initializing network with DFE https://android.clients.google.com/fdfe/
06-01 13:32:31.987  25552-25552/com.android.vending            D/Finsky: [1] DailyHygiene.goMakeHygieneIfDirty: No need to run daily hygiene.
06-01 13:32:32.037  25552-25552/com.android.vending            W/Settings: Setting download_manager_max_bytes_over_mobile has moved from android.provider.Settings.Secure to android.provider.Settings.Global.
06-01 13:32:32.037  25552-25552/com.android.vending            W/Settings: Setting download_manager_recommended_max_bytes_over_mobile has moved from android.provider.Settings.Secure to android.provider.Settings.Global.
06-01 13:32:32.178      616-881/system_process                 D/dalvikvm: GC_FOR_ALLOC freed 656K, 26% free 11321K/15124K, paused 82ms, total 86ms
06-01 13:32:32.238  25566-25566/com.example.droidcam           D/libEGL: loaded /system/lib/egl/libEGL_adreno200.so
06-01 13:32:32.258  25566-25566/com.example.droidcam           D/libEGL: loaded /system/lib/egl/libGLESv1_CM_adreno200.so
06-01 13:32:32.258  25566-25566/com.example.droidcam           D/libEGL: loaded /system/lib/egl/libGLESv2_adreno200.so
06-01 13:32:32.268  25566-25566/com.example.droidcam           I/Adreno200-EGL: <qeglDrvAPI_eglInitialize:294>: EGL 1.4 QUALCOMM build: AU_LINUX_ANDROID_JB.04.01.01.00.036_msm8960_JB_CL2644550_release_AU (CL2644550)
        Build Date: 07/31/12 Tue
        Local Branch:
        Remote Branch: quic/master
        Local Patches: NONE
        Reconstruct Branch: AU_LINUX_ANDROID_JB.04.01.01.00.036 +  NOTHING
06-01 13:32:32.318  25566-25566/com.example.droidcam           D/OpenGLRenderer: Enabling debug mode 0
06-01 13:32:32.348      256-515/?                              I/AwesomePlayer: setDataSource_l(URL suppressed)
06-01 13:32:32.378    256-25622/?                              D/MediaExtractor: returning default extractor
06-01 13:32:32.388      256-515/?                              I/AwesomePlayer: setDataSource_l(URL suppressed)
06-01 13:32:32.408    256-25626/?                              D/MediaExtractor: returning default extractor
06-01 13:32:32.408      256-515/?                              I/CameraClient: Opening camera 0
06-01 13:32:32.408      256-515/?                              W/ServiceManager: Permission failure: com.sonyericsson.permission.CAMERA_EXTENDED from uid=10019 pid=25566
06-01 13:32:32.438    256-25630/?                              I/caladbolg: 3348999538 cald_camctrl.c                    (6713) 25630 P [SVR] -945967758 + Cald_CamCtrl_PowerUp
06-01 13:32:32.438    256-25630/?                              I/caladbolg: 3348999630 cald_camctrl.c                    (7484) 25630 P [SVR] -945967666 + Cald_CamCtrl_FSM_Func_PowerUp
06-01 13:32:32.438    256-25630/?                              I/caladbolg: 3349003170 cald_hal_qct.c                    (2789) 25630 P [HAL] -945964126 + Cald_Hal_Qct_If_PowerUp
06-01 13:32:32.438    256-25630/?                              I/caladbolg: 3349003323 cald_hal_qct.c                    (2847) 25630 P [HAL] -945963973 - Cald_Hal_Qct_If_PowerUp (0)
06-01 13:32:32.438    256-25630/?                              I/caladbolg: 3349004665 cald_camctrl.c                    (7563) 25630 P [SVR] -945962631 - Cald_CamCtrl_FSM_Func_PowerUp (0)
06-01 13:32:32.438    256-25630/?                              I/caladbolg: 3349004726 cald_camctrl.c                    (6720) 25630 P [SVR] -945962570 - Cald_CamCtrl_PowerUp (0)
06-01 13:32:32.448    256-25630/?                              E/caladbolg: 3349014431 cald_camctrl.c                   (11888) 25630 E [SVR] PreviewSize Invalid param: value[402x527]
06-01 13:32:32.458  25566-25566/com.example.droidcam           D/AndroidRuntime: Shutting down VM
06-01 13:32:32.458  25566-25566/com.example.droidcam           W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x2b5d9930)
06-01 13:32:32.488  25566-25566/com.example.droidcam           E/AndroidRuntime: FATAL EXCEPTION: main
        java.lang.RuntimeException: setParameters failed
        at android.hardware.Camera.native_setParameters(Native Method)
        at android.hardware.Camera.setParameters(Camera.java:1496)
        at com.example.droidcam.MainActivity.surfaceChanged(MainActivity.java:41)
        at android.view.SurfaceView.updateWindow(SurfaceView.java:580)
        at android.view.SurfaceView.access$000(SurfaceView.java:86)
        at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:174)
        at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:680)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1842)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
        at android.view.Choreographer.doCallbacks(Choreographer.java:562)
        at android.view.Choreographer.doFrame(Choreographer.java:532)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
        at android.os.Handler.handleCallback(Handler.java:725)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:5226)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
        at dalvik.system.NativeStart.main(Native Method)
06-01 13:32:32.498      616-943/system_process                 W/ActivityManager: Force finishing activity com.example.droidcam/.MainActivity
06-01 13:32:32.688  25552-25552/com.android.vending            D/Finsky: [1] 2.run: Loaded library for account: [i1YaFxIWaZrcOQ26zxNX5K0RvvY]
06-01 13:32:32.688  25552-25552/com.android.vending            D/Finsky: [1] 2.run: Finished loading 1 libraries.
06-01 13:32:32.908  25552-25552/com.android.vending            D/Finsky: [1] 5.onFinished: Installation state replication succeeded.
06-01 13:32:33.018      616-647/system_process                 W/ActivityManager: Activity pause timeout for ActivityRecord{2b946870 u0 com.example.droidcam/.MainActivity}

Ho pure provato facendo copia incolla spudorato del codice nel tutorial, aggiungendo pure il bottone scatta che non mi serviva alla fine. Ma niente. Non riesco davvero a capire
« Ultima modifica: 01 Giugno 2013, 16:58:16 CEST da Deeniel »

Offline OssoMasticato

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Note GT-N7000
  • Sistema operativo:
    Windows XP SP2/Win Vista
Re:[medio] Come utilizzare la Camera di Android per scattare una foto
« Risposta #94 il: 05 Giugno 2013, 18:39:39 CEST »
0
Ora mi restituisce una Nullpointer in

Codice (Java): [Seleziona]
Camera.Parameters p = mCamera.getParameters();

Codice: [Seleziona]
06-05 16:32:20.884: E/AndroidRuntime(1055): FATAL EXCEPTION: main
06-05 16:32:20.884: E/AndroidRuntime(1055): java.lang.NullPointerException
06-05 16:32:20.884: E/AndroidRuntime(1055): at com.example.testphoto.CameraPreview.surfaceChanged(CameraPreview.java:121)


Offline OssoMasticato

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Note GT-N7000
  • Sistema operativo:
    Windows XP SP2/Win Vista
Re:[medio] Come utilizzare la Camera di Android per scattare una foto
« Risposta #95 il: 09 Giugno 2013, 19:23:18 CEST »
0
Sarebbe possibile usare startActivityForResult(Intent, int) dopo

Codice (Java): [Seleziona]
        PictureCallback jpegCallback = new PictureCallback(){
per far apparire la foto appena scattata e decidere se eliminarla oppure salvarla?

Offline sfregio

  • Nuovo arrivato
  • *
  • Post: 10
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Sony Ericsson Xperia ArcS
  • Play Store ID:
    Fabrizio Ravì
  • Sistema operativo:
    Snow Leopard
Re:[medio] Come utilizzare la Camera di Android per scattare una foto
« Risposta #96 il: 24 Luglio 2013, 11:44:56 CEST »
0
Buongiorno a tutti
volevo realizzare una applicazione che analizza frame per frame un video (per poter fare ad esempio una face detection) però utilizzando l'oggetto Camera e non la camera di opencv...tuttavia non riesco ad ottenere i vari frame in maniera consecutiva....c'è qualcuno che mi possa aiutare???
« Ultima modifica: 24 Luglio 2013, 11:48:06 CEST da sfregio »

Offline Wallace911

  • Nuovo arrivato
  • *
  • Post: 1
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Xiaomi Mi5, LG G2 D802
  • Sistema operativo:
    Windows 10 Creators Update
Re:[medio] Come utilizzare la Camera di Android per scattare una foto
« Risposta #97 il: 26 Settembre 2017, 10:58:23 CEST »
0
Livello di difficoltà: medio
Versione SDK utilizzata: 2.1
Link al file compresso del progetto eclipse: file in allegato

In questo tutorial voglio farvi vedere come fare ad avere accesso alla Camera messa a disposizione del vostro device e come poter con questa scattare una foto. Il tutorial si concentra sulle funzionalità base messe a disposizione da android, vuole solo essere un trampolino di lancio, lasciando allo sviluppatore ulteriori accorgimenti per arricchire e migliorare la propria app.

Per iniziare avremo bisogno di una SurfaceView ed una interfaccia SurfaceHolder. Vediamo brevemente di cosa si tratta.
Una SurfaceView, come dice il nome, è una particolare View che permette di disegnare sul display elementi grafici, nel nostro caso la preview proveniente dalla camera. SurfaceHolder è un'interfaccia che ci permette di gestire la SurfaceView, mediante l'utilizzo di particolare operazioni (callback), che ci serviranno per capire quando la Surface verrà creata, quando subirà cambiamenti e quando verrà distrutta.
Utilizzeremo anche la classe Camera, che ci permette di interagire direttamente con il dispositivo hardware del device. La utilizzeremo per occupare la risorsa camera, per rilasciarla, per scattare una foto, per far partire la preview, per settare i parametri come autofocus, flash etc... questi ultimi due avranno bisogno di un tutorial a parte che provvederò a fornire prossimamente.
Infine dovremo utilizzare un'ulteriore interfaccia Camera.PictureCallback per definire le operazioni da fare quando verrà scattata la foto.

Questi sono gli elementi essenziali. Partiamo con il tutorial vero e proprio.  :-)

Per prima cosa creariamo una nostra activity che estenda Activity e (importantissimo!) implementi SurfaceHolder.Callback, altrimenti non saremmo in grado di utilizzare le callback per gestire la surface.
Quello che vogliamo è un'activity che mostri a tutto schermo la camera con un pulsante dedicato per far partire lo scatto. Quindi creiamo la nostra Activity e informiamo Android che vogliamo settare alcuni parametri come essere a full screen e senza la barra di stato.
Codice (Java): [Seleziona]
getWindow().setFormat(PixelFormat.TRANSLUCENT); //aggiungo il traslucido
requestWindowFeature(Window.FEATURE_NO_TITLE);  //no barra titolo
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);   //full screen

Fatto questo recuperiamo la nostra SurfaceView il la nostra SurfaceHolder e diciamo ad Android di collegarla alla nostra Activity. In questo modo la nostra activity risponderà alle chiamate a callback della surface.
Codice (Java): [Seleziona]
mSurfaceView = (SurfaceView)findViewById(R.id.camera_surface);   //recupero il riferimento alla SurfaceView da XML
mSurfaceHolder = mSurfaceView.getHolder();      //recupero l'holder della SurfaceView
mSurfaceHolder.addCallback(this);       //faccio la bind con la nostra activity
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        // setto tipo di surface, suggerito nei tutorial ufficiali

A questo punto dobbiamo implementare i 3 metodi dell'interfaccia SurfaceHolder: surfaceCreated(), surfaceChanged, surfaceDestroyed(). Tutte e 3 hanno come parametro la SurfaceHolder collegata alla surface creata.
Codice (Java): [Seleziona]
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        if (mPreviewRunning)
                mCamera.stopPreview();
               
        //setto le preferenze
        Camera.Parameters p = mCamera.getParameters();  //prendo le preferenze della camera
        p.setPreviewSize(arg2, arg3);
        ArrayList<Size> list = (ArrayList<Size>) p.getSupportedPictureSizes();  //recuepro le risoluzioni supportate dalla camera
        int picture_width = list.get(list.size()-1).width;
        int picture_height = list.get(list.size()-1).height;
        p.setPictureSize(picture_width, picture_height);        //setto la camera alla risoluzione più bassa
        p.setJpegQuality(80);   // qualità compressione JPEG
   
        // salvo le pref
        mCamera.setParameters(p);
        try {
                //lancio la preview
                mCamera.setPreviewDisplay(arg0);       
                mCamera.startPreview();
                mPreviewRunning = true;
        } catch (IOException e) {
                        //gestione errore
        }
       
               
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open();               
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
        mCamera.stopPreview();
        mPreviewRunning = false;
        mCamera.release();

}

La surfaceCreated viene chiama appena la surface viene creata. Qui dobbiamo semplicemente ottenere l'accesso alla Camera con la open().
La surfaceDestroyed viene chiamata quando la surface o l'activity vengono distrutte. Non facciamo altro che fermare la preview sulla surface e rilasciare la camera (importante).
Nella surfaceChanged che viene chiamata ogni volta che la surface subisce un cambiamento, vengono effettuati i settaggi dei paramentri della camera. E' consigliato effettuare questi settaggi solo quando la preview non è partita, in modo da evitare flickering o crash improvvisi.
La setPreviewSize() mi setta la dimensione di quello che saranno i frames visti a video secondo width e heigth forniti in automatico dalla callback come parametri.
La getSupportedPictureSize restituisce le risoluzioni supportate dalla camera del nostro device. La successiva chiamata a setPictureSize() non fa altro che definire a quale risoluzione vogliamo scattare la foto. Per comodità io l'ho impostata alla più bassa, ma ognuno è ovviamente libero di decidere quale utilizzare.
La setQualityJpeg() credo sia intuitiva... il valore 80 è quello solitamente utilizzato.
Infine coe startPreview() si fa partire la preview sulla nostra surface e visulizziamo cosa la camera sta riprendendo.

Mancano ancora due pezzi del puzzle per concludere il nostro tutorial. Come si fa a scattare la foto?

Ora definiamo l'evento onClick sul pulsante per scattare.
Codice (Java): [Seleziona]
ImageButton buttonPicture = (ImageButton) findViewById(R.id.camera_surface_button);
                buttonPicture.setOnClickListener(new OnClickListener(){
                        public void onClick(View v) {
                                mCamera.takePicture(null, null, jpegCallback);  
                        }
                });

Come vedete è presente un metodo d'istanza di Camera, che si occuperà di fare la foto e che utilizza una serie di callback che vengono chiamate durante lo scatto. E' a discrezione del programmatore utilizzarle a seconda del bisogno. Per approfonditmenti vi rimando alla documentazione ufficiale. A noi interessa l'ultima, che io ho chiamato jpegCallback, che non è altro che la definizione dell'interfaccia Camera.PictureCallback a cui accennavo prima.
Codice (Java): [Seleziona]
PictureCallback jpegCallback = new PictureCallback() {
                public void onPictureTaken(byte[] _data, Camera _camera) {
                        //riparte la preview della camera
                        mCamera.startPreview();
                       
                }
        };

L'evento onPictureTaken fornisce tra i paramentri l'array di byte, che mi rappresenta l'immagine scattata. Sta a noi programmatori decide come utilizzarla, per esempio è possibile salvarla sulla SD card e magari decidere di renderla visibile nella gallery... infine va di nuovo chiamata la startPreview() per far ripartire la camera e renderla nuovamente disponibile a successive foto.  ;-)

Ci sarebbero ancora diverse cose da dire, come per esempio la gestione dell'autofocus o del flash... ma credo che questo sia un buon punto da cui partire.

Vi ricordo che nel Manifest andrà inserito il relativo permesso per utilizzare la Camera
Codice (XML): [Seleziona]
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera"/>
Il primo indica che l'app utilizzerà la CAMERA. Se lasciassi solo questo la mia app avrebbe accesso a tutte le funzionalità della camera del device su cui la mia app è installata, rendola incompatibile se facessei uso a programma di features che non sono supportate dal device. Se invece specifico le features una per una sono più selettivo e indico effettivamente quelle utilizzate. Se invece mi limito a fare come nel tutorial, indicando cioè solo la feature generica android.hardware.camera, dico che non uso nessuna features particolare e rendo la mia app altamente compatibile. Sta a voi anche qui decidere il giusto compromesso a seconda delle necessità.
Maggiori info a riguardo le trovate come sempre nella documentazione ufficiale. QUI.


Sorgenti:

CameraView.java
Codice (Java): [Seleziona]
import java.io.IOException;
import java.util.ArrayList;

import android.app.Activity;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.ImageButton;

public class CameraView extends Activity implements SurfaceHolder.Callback{
       
/* VARIABILI PRIVATE */
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
private boolean mPreviewRunning;
       
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFormat(PixelFormat.TRANSLUCENT); //aggiungo il traslucido
        requestWindowFeature(Window.FEATURE_NO_TITLE);  //no barra titolo
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);   //full screen
        setContentView(R.layout.main);
        ImageButton buttonPicture = (ImageButton) findViewById(R.id.camera_surface_button);
                buttonPicture.setOnClickListener(new OnClickListener(){
                        public void onClick(View v) {
                                mCamera.takePicture(null, null, jpegCallback);
                        }
                });
               
        mSurfaceView = (SurfaceView)findViewById(R.id.camera_surface);
        mSurfaceHolder = mSurfaceView.getHolder();      //recupero l'holder della surfaceview
        mSurfaceHolder.addCallback(this);       //faccio la bind alla nostra activity
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        //tipo di surface, suggerito nei tutorial ufficiali
    }
   
   
   
    PictureCallback jpegCallback = new PictureCallback() {
                public void onPictureTaken(byte[] _data, Camera _camera) {
                        //riparte la preview della camera
                        mCamera.startPreview();
                       
                }
        };

        @Override
        public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
                if (mPreviewRunning)
                        mCamera.stopPreview();
               
                //setto le preferenze
                Camera.Parameters p = mCamera.getParameters();  //prendo le preferenze della camera
                p.setPreviewSize(arg2, arg3);
                ArrayList<Size> list = (ArrayList<Size>) p.getSupportedPictureSizes();  //recuepro le risoluzioni supportate dalla camera
        int picture_width = list.get(list.size()-1).width;
        int picture_height = list.get(list.size()-1).height;
        p.setPictureSize(picture_width, picture_height);        //setto la camera alla risoluzione più bassa
        p.setJpegQuality(80);   // qualità compressione JPEG
       
        // salvo le pref
        mCamera.setParameters(p);
        try {
                //lancio la preview
                        mCamera.setPreviewDisplay(arg0);       
                        mCamera.startPreview();
                        mPreviewRunning = true;
                } catch (IOException e) {
                        //gestione errore
                }
       
               
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
                mCamera = Camera.open();
               
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
        mCamera.stopPreview();
        mPreviewRunning = false;
        mCamera.release();
               
        }
}


AndroidManifest.xml
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.tutorial.camera"
     android:versionCode="1"
     android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".CameraView"
                 android:label="@string/app_name"
                 android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    <uses-sdk android:minSdkVersion="7" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera"/>

</manifest>

main.xml
Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
       
                <SurfaceView android:id="@+id/camera_surface"
                        android:layout_width="fill_parent"
                        android:layout_height="fill_parent"
                        android:layout_weight="1">
                </SurfaceView>
               
                <RelativeLayout android:id="@+id/camera_surface_footer"
                        android:layout_width="wrap_content"
                        android:layout_height="fill_parent"
                        android:background="#E4E4E4"
                        android:layout_alignRight="@id/camera_surface">
                       
                        <ImageButton android:id="@+id/camera_surface_button"   
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:src="@drawable/icon"
                                android:layout_centerInParent="true"
                                />
                </RelativeLayout>

</RelativeLayout>

Spero di aver fatto cosa gradita e che questa guida possa risultarvi utile.
Ciao vorrei utilizzare il tuo codice per far partire la fotocamera partendo da un azione su un bottone. Quindi nel mio main activity faccio questo:
Codice (Java): [Seleziona]
final Intent intent = new Intent(this, CameraView.class);
final Button button3 = findViewById(R.id.buttonCamera);
button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(intent);
            }
        });

però quando faccio tap sul bottone
Codice: [Seleziona]
E/AndroidRuntime: FATAL EXCEPTION: main
                                                                   Process: kairosdemo.demokairos, PID: 588
                                                                   java.lang.RuntimeException: setParameters failed
                                                                       at android.hardware.Camera.native_setParameters(Native Method)
                                                                       at android.hardware.Camera.setParameters(Camera.java:2073)
                                                                       at kairosdemo.demokairos.CameraView.surfaceChanged(CameraView.java:75)
                                                                       at android.view.SurfaceView.updateWindow(SurfaceView.java:638)
                                                                       at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:162)
                                                                       at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
                                                                       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2247)
                                                                       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1292)
                                                                       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6368)
                                                                       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:873)
                                                                       at android.view.Choreographer.doCallbacks(Choreographer.java:685)
                                                                       at android.view.Choreographer.doFrame(Choreographer.java:621)
                                                                       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:859)
                                                                       at android.os.Handler.handleCallback(Handler.java:754)
                                                                       at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                       at android.os.Looper.loop(Looper.java:163)
                                                                       at android.app.ActivityThread.main(ActivityThread.java:6315)
                                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:877)
                                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
come posso risolvere?