Kamera Android android.hardware.Camera tidak digunakan lagi

97

jika android.hardware.Camerasudah tidak digunakan lagi dan Anda tidak dapat menggunakan variabel Camera, lalu apa alternatifnya?

raja121
sumber
1
Saya mengalami masalah ini dengan sebuah aplikasi dan merasa ini sangat membantu. Jika Anda menggunakan niat, Anda terbatas. Jadi tutorial ini menjelaskan alternatif: developer.android.com/guide/topics/media/…
Ronaldo Bahia

Jawaban:

102

Dokumentasi API

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

Kami merekomendasikan penggunaan API android.hardware.camera2 baru untuk aplikasi baru.

Pada halaman informasi tentang android.hardware.camera2, (ditautkan di atas), disebutkan:

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

Masalah

Saat Anda memeriksa dokumentasi itu, Anda akan menemukan bahwa penerapan 2 Camera API ini sangat berbeda.

Misalnya mengaktifkan 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 menyulitkan 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 mengatasi fakta bahwa API kamera lama bekerja dengan intprimitif untuk ID kamera sementara yang baru bekerja dengan Stringobjek. Untuk contoh ini saya dengan cepat memperbaikinya dengan menggunakan int sebagai indeks di API baru. Jika kamera dikembalikan tidak selalu dalam urutan yang sama, ini sudah menyebabkan masalah. Pendekatan alternatif adalah bekerja dengan objek String dan representasi String dari cameraID int lama yang mungkin lebih aman.

Satu lagi di sekitar

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

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

Di bagian selanjutnya saya akan menjelaskan dengan cepat 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 miliki kelas untuk api perangkat keras kamera lama:

@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 salah satu CameraOldatau CameraNewkelas Anda, Anda harus memeriksa level API karena CameraNewhanya tersedia dari api level 21.

Jika Anda sudah menyiapkan injeksi dependensi, Anda dapat melakukannya di modul Anda saat menyediakan CameraSupportimplementasi. 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 dapat membuat utilitas atau menggunakan pola Pabrik untuk membuat yang tepat. Bagian penting adalah bahwa level API diperiksa.

Komunitas
sumber
25
Bagaimana jika saya perlu mendukung Android API level kurang dari 21?
niveuseverto
1
@Angelius mungkin dokumentasi ini akan membantu developer.android.com/guide/topics/media/camera.html - tetapi itu bisa menjadi pertanyaan terpisah, atau mencari pertanyaan tentang harus menggunakan variabel yang tidak digunakan lagi.
@Angelius di sini adalah beberapa informasi tentang @SuppressWarningsdi QA stackoverflow.com/questions/7397996/…
5
Saya berpikir untuk tidak hanya menggunakan kelas @deprecated, tetapi bagaimana membuat aplikasi dengan kompatibilitas mundur? ada bantuan resmi dalam hal ini? Saya punya ide tentang ini: Antarmuka kamera, yang didukung dengan objek Kamera yang sesuai dengan versi ponsel saat ini, tetapi ini agak mudah dan sulit dipelihara ...
niveuseverto
@Angelius apa yang Anda gambarkan bisa menjadi pertanyaan terpisah (periksa untuk melihat apakah sudah ditanyakan sebelumnya).
5

Menghadapi masalah yang sama , mendukung perangkat lama melalui API kamera yang sudah tidak digunakan lagi dan membutuhkan API Camera2 baru untuk perangkat saat ini dan untuk masa mendatang; Saya mengalami masalah yang sama - dan belum menemukan perpustakaan pihak ke-3 yang menjembatani 2 API, kemungkinan karena keduanya sangat berbeda, saya beralih ke kepala sekolah OOP dasar .

Kedua API tersebut sangat berbeda sehingga mempertukarkannya menjadi masalah untuk objek klien yang mengharapkan antarmuka yang disajikan dalam API lama. API baru memiliki objek berbeda dengan metode berbeda, dibangun menggunakan arsitektur berbeda. Punya cinta untuk Google, tapi ragnabbit! itu membuat frustrasi.

Jadi saya membuat antarmuka yang berfokus hanya pada fungsionalitas kamera yang dibutuhkan aplikasi saya, dan membuat pembungkus sederhana untuk kedua API yang mengimplementasikan antarmuka itu. Dengan begitu, aktivitas kamera saya tidak harus peduli pada platform mana yang dijalankan ...

Saya juga menyiapkan Singleton untuk mengelola API; memberi contoh pembungkus API lama dengan antarmuka saya untuk perangkat OS Android lama, dan kelas pembungkus API baru untuk perangkat baru yang menggunakan API baru. Singleton memiliki kode tipikal untuk mendapatkan level API dan kemudian membuat instance objek yang benar.

Antarmuka yang sama digunakan oleh kedua kelas pembungkus , jadi tidak masalah jika Aplikasi berjalan di Jellybean atau Marshmallow - selama antarmuka menyediakan apa yang dibutuhkan aplikasi saya 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 terkait dengan API - seperti mendeteksi bahwa memang ada kamera di perangkat, dan menyimpan ke perpustakaan media.

Saya harap idenya membantu Anda.

Robert Sherman
sumber
Misalnya:public interface AllCameraInterface { void open(); boolean setDirection(); Bitmap preview(); Bitmap takePhoto(); void close(); }
Robert Sherman
mis: public interface AllCameraInterface { void open(); Bitmap takePhoto(); void close(); etc... } public class NCamera implements AllCameraInterface... public class OCamera implements AllCameraInterface... public class AllCamera { private static AllCamera ourInstance = new AllCamera(); public static AllCamera getInstance() {...} private AllCameraInterface camera; private AllCamera() { if (android.os.Build.VERSION.SDK_INT <= 20) { camera = new OCamera(); } else { camera = new NCamera(); } }Kemudian metode untuk mengembalikannya ...
Robert Sherman
tampaknya tidak ada jeda baris yang diperbolehkan dalam komentar ;-) tetapi itu benar-benar berfungsi.
Robert Sherman
4
mengapa tidak menambahkan kode di komentar langsung ke dalam Answer?
Angel Koh
@RobertSherman Hai Robert, Bisakah Anda membantu saya menulis ulang cuplikan kecil ini untuk yang baru camera2? Saya benar-benar bingung ... Saya hanya perlu enableAutofocusmetode untuk membuka kamera dan mengatur fokusnya: stackoverflow.com/questions/19076316/…
0

Sekarang kita harus menggunakan android.hardware.camera2 karena android.hardware.Camera sudah 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;
                    }


            }
        });
    }
}
abhay rastogi Codeblended
sumber
0

Jawaban yang diberikan di sini karena api kamera yang digunakan salah. Atau lebih baik mengatakan mereka tidak cukup.

Beberapa ponsel (misalnya Samsung Galaxy S6) mungkin memiliki api di atas level 21 tetapi mungkin masih tidak mendukung api Camera2.

CameraCharacteristics mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCameraId);
Integer level = mCameraCharacteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (level == null || level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
    return false;
}

Kelas CameraManager di Camera2Api memiliki metode untuk membaca karakteristik kamera. Anda harus memeriksa apakah perangkat cerdas perangkat keras mendukung Camera2 Api atau tidak.

Tetapi ada lebih banyak masalah yang harus ditangani jika Anda benar-benar ingin membuatnya berfungsi untuk aplikasi yang serius: Seperti, opsi flash otomatis mungkin tidak berfungsi untuk beberapa perangkat atau tingkat baterai ponsel dapat membuat RuntimeException pada Kamera atau ponsel dapat mengembalikan yang tidak valid id kamera dan lain-lain

Jadi pendekatan terbaik adalah memiliki mekanisme fallback karena untuk beberapa alasan Camera2 gagal memulai, Anda dapat mencoba Camera1 dan jika gagal juga Anda dapat melakukan panggilan ke Android untuk membuka Kamera default untuk Anda.

Oguz Ozcan
sumber
0
 if ( getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {

          CameraManager cameraManager=(CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);


           try {
               String cameraId = cameraManager.getCameraIdList()[0];
               cameraManager.setTorchMode(cameraId,true);
           } catch (CameraAccessException e) {
               e.printStackTrace();
           }


 }
Rohith S.
sumber