Pertanyaan Kamera Android android.hardware.Camera tidak digunakan lagi


jika android.hardware.Camera sudah ditinggalkan dan Anda tidak dapat menggunakan variabel Camera, lalu apa alternatifnya?


75
2018-01-21 11:18


asal


Jawaban:


Dokumentasi API

Menurut Panduan pengembang Android untuk android.hardware.Camera, mereka menyatakan:

Kami merekomendasikan menggunakan yang baru android.hardware.camera2 API untuk aplikasi baru.

Di halaman informasi tentang android.hardware.camera2, (terkait di atas), dinyatakan:

Paket android.hardware.camera2 menyediakan antarmuka ke perangkat kamera individu yang terhubung ke perangkat Android. Ini menggantikan kelas Kamera usang.

Masalah

Ketika Anda memeriksa dokumentasi itu, Anda akan menemukan bahwa penerapan 2 Kamera API ini sangat berbeda.

Misalnya mendapatkan orientasi kamera android.hardware.camera

@Override
public int getOrientation(final int cameraId) {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    return info.orientation;
}

Melawan android.hardware.camera2 

@Override
public int getOrientation(final int cameraId) {
    try {
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        String[] cameraIds = manager.getCameraIdList();
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
        return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
    } catch (CameraAccessException e) {
        // TODO handle error properly or pass it on
        return 0;
    }
}

Ini membuat sulit untuk beralih dari satu ke yang lain dan menulis kode yang dapat menangani kedua implementasi.

Perhatikan bahwa dalam contoh kode tunggal ini saya sudah harus bekerja di sekitar fakta bahwa API kamera lama bekerja dengan int primitif untuk ID kamera sementara yang baru bekerja dengan String objek. Untuk contoh ini saya dengan cepat memperbaikinya dengan menggunakan int sebagai indeks di API baru. Jika kamera yang dikembalikan tidak selalu dalam urutan yang sama, ini akan menyebabkan masalah. Pendekatan alternatif adalah bekerja dengan objek String dan representasi String dari kamera-kamera lama yang mungkin lebih aman.

Satu lagi

Sekarang untuk mengatasi perbedaan besar ini Anda dapat mengimplementasikan antarmuka terlebih dahulu dan referensi antarmuka itu dalam kode Anda.

Di sini saya akan daftar beberapa kode untuk antarmuka itu dan 2 penerapannya. Anda dapat membatasi implementasi ke apa yang sebenarnya Anda gunakan dari API kamera untuk membatasi jumlah pekerjaan.

Di bagian selanjutnya saya akan segera menjelaskan cara memuat satu atau lainnya.

Antarmuka membungkus semua yang Anda butuhkan, untuk membatasi contoh ini saya hanya memiliki 2 metode di sini.

public interface CameraSupport {
    CameraSupport open(int cameraId);
    int getOrientation(int cameraId);
}

Sekarang memiliki kelas untuk api perangkat keras kamera tua:

@SuppressWarnings("deprecation")
public class CameraOld implements CameraSupport {

    private Camera camera;

    @Override
    public CameraSupport open(final int cameraId) {
        this.camera = Camera.open(cameraId);
        return this;
    }

    @Override
    public int getOrientation(final int cameraId) {
       Camera.CameraInfo info = new Camera.CameraInfo();
       Camera.getCameraInfo(cameraId, info);
       return info.orientation;
    }
}

Dan satu lagi untuk api perangkat keras baru:

public class CameraNew implements CameraSupport {

    private CameraDevice camera;
    private CameraManager manager;

    public CameraNew(final Context context) {
        this.manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
    }

    @Override
    public CameraSupport open(final int cameraId) {
        try {
            String[] cameraIds = manager.getCameraIdList();
            manager.openCamera(cameraIds[cameraId], new CameraDevice.StateCallback() {
                @Override
                public void onOpened(CameraDevice camera) {
                    CameraNew.this.camera = camera;
                }

                @Override
                public void onDisconnected(CameraDevice camera) {
                    CameraNew.this.camera = camera;
                    // TODO handle
                }

                @Override
                public void onError(CameraDevice camera, int error) {
                    CameraNew.this.camera = camera;
                    // TODO handle
                }
            }, null);
        } catch (Exception e) {
            // TODO handle
        }
        return this;
    }

    @Override
    public int getOrientation(final int cameraId) {
        try {
            String[] cameraIds = manager.getCameraIdList();
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIds[cameraId]);
            return characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
        } catch (CameraAccessException e) {
            // TODO handle
            return 0;
        }
    }
}

Memuat API yang tepat

Sekarang untuk memuat baik Anda CameraOld atau CameraNew kelas Anda harus memeriksa tingkat API sejak CameraNew hanya tersedia dari level api 21.

Jika Anda sudah menyiapkan suntikan ketergantungan, Anda dapat melakukannya di modul Anda saat menyediakan CameraSupport pelaksanaan. Contoh:

@Module public class CameraModule {

    @Provides
    CameraSupport provideCameraSupport(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return new CameraNew(context);
        } else {
            return new CameraOld();
        }
    } 
}

Jika Anda tidak menggunakan DI Anda bisa membuat utilitas atau menggunakan pola Pabrik untuk membuat yang tepat. Bagian penting adalah bahwa tingkat API dicentang.


77
2018-01-21 11:26



Menghadapi masalah yang sama, mendukung perangkat yang lebih lama melalui API kamera yang tidak lagi digunakan dan memerlukan API Kamera2 baru untuk kedua perangkat saat ini dan bergerak ke masa depan; Saya mengalami masalah yang sama - dan memiliki tidak menemukan pustaka pihak ke-3 yang menjembatani 2 API, kemungkinan karena keduanya sangat berbeda, Saya beralih ke prinsip dasar OOP.

2 API sangat berbeda membuat interchanging mereka bermasalah untuk objek klien yang mengharapkan antarmuka disajikan dalam API lama. API baru memiliki objek yang berbeda dengan metode yang berbeda, dibangun menggunakan arsitektur yang berbeda. Mendapat cinta untuk Google, tapi ragnabbit! itu membuat frustrasi.

Jadi saya membuat antarmuka yang fokus hanya pada fungsi kamera yang dibutuhkan aplikasi saya, dan membuat pembungkus sederhana untuk kedua API yang mengimplementasikan antarmuka itu. Dengan begitu, aktivitas kameraku tidak perlu peduli dengan platform mana yang berjalan ...

Saya juga mengatur Singleton untuk mengelola API (s); instancing pembungkus API yang lama dengan antarmuka saya untuk perangkat OS Android yang lebih lama, dan kelas pembungkus API baru untuk perangkat yang lebih baru menggunakan API baru. Singleton memiliki kode yang khas untuk mendapatkan level API dan kemudian instances objek yang benar.

Antarmuka yang sama digunakan oleh kedua kelas pembungkus, jadi tidak masalah jika Aplikasi berjalan di Jellybean atau Marshmallow - selama antarmuka menyediakan aplikasi saya dengan apa yang dibutuhkan dari API Kamera, menggunakan tanda tangan metode yang sama; kamera berjalan di Aplikasi dengan cara yang sama untuk versi Android yang lebih baru dan lebih lama.

Singleton juga dapat melakukan beberapa hal terkait yang tidak terikat pada API - seperti mendeteksi bahwa memang ada kamera di perangkat, dan menyimpan ke perpustakaan media.

Saya harap ide ini membantu Anda.


5
2018-06-16 18:25



Sekarang kita harus menggunakan android.hardware.camera2 sebagai android.hardware.Camera tidak digunakan lagi yang hanya akan berfungsi pada API> 23 FlashLight

   public class MainActivity extends AppCompatActivity {

     Button button;

     Boolean light=true;

     CameraDevice cameraDevice;

     private CameraManager cameraManager;

     private CameraCharacteristics cameraCharacteristics;

     String cameraId;

     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button)findViewById(R.id.button);
        cameraManager = (CameraManager) 
        getSystemService(Context.CAMERA_SERVICE);
        try {
          cameraId = cameraManager.getCameraIdList()[0];
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(light){
                    try {

                        cameraManager.setTorchMode(cameraId,true);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }

                    light=false;}
                    else {

                    try {

                      cameraManager.setTorchMode(cameraId,false);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }


                    light=true;
                    }


            }
        });
    }
}

0
2018-06-20 13:47