Android kamera android.hardware.Camera kullanımdan kaldırıldı


97

Kullanımdan android.hardware.Camerakaldırılırsa ve değişkeni kullanamazsanız, Camerabunun alternatifi ne olabilir?



1
Bir uygulamayla bu sorunu yaşadım ve bunu çok yararlı buldum. Niyet kullanırsanız, sınırlısınız. Bu nedenle, bu eğitici bir alternatif açıklıyor: developer.android.com/guide/topics/media/…
Ronaldo Bahia

Yanıtlar:


103

API Belgeleri

Göre Android geliştiricileri rehber için android.hardware.Camera, onlar devlet:

Yeni uygulamalar için yeni android.hardware.camera2 API'sini kullanmanızı öneririz .

Hakkında bilgi sayfasında android.hardware.camera2(yukarıda bağlantısı verilen) şu şekilde belirtilir:

Android.hardware.camera2 paketi, bir Android cihaza bağlı ayrı kamera cihazları için bir arayüz sağlar. Kullanımdan kaldırılan Camera sınıfının yerini alır.

Sorun

Bu belgeleri kontrol ettiğinizde, bu 2 Kamera API'sinin uygulamasının çok farklı olduğunu göreceksiniz.

Örneğin, kamera yönünü alma android.hardware.camera

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

Karşı 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;
    }
}

Bu, birinden diğerine geçmeyi ve her iki uygulamayı da idare edebilecek kod yazmayı zorlaştırır.

Bu tek kod örneğinde int, yeni kamera Stringnesnelerle çalışırken eski kamera API'sinin kamera kimlikleri için ilkel öğelerle çalıştığı gerçeğini zaten aşmam gerektiğine dikkat edin . Bu örnek için, int'i yeni API'de bir dizin olarak kullanarak hızlı bir şekilde düzelttim. Kameranın iade edilmesi her zaman aynı sırada değilse, bu zaten sorunlara neden olacaktır. Alternatif yaklaşım, String nesneleri ve muhtemelen daha güvenli olan eski int kamera kimliklerinin String temsilleriyle çalışmaktır.

Biri etrafta

Şimdi bu büyük farkı aşmak için önce bir arabirim uygulayabilir ve kodunuzda bu arabirime başvurabilirsiniz.

Burada bu arayüz ve 2 uygulama için bazı kodları listeleyeceğim. İş miktarını sınırlandırmak için uygulamayı, kamera API'sini gerçekte kullandığınızla sınırlayabilirsiniz.

Bir sonraki bölümde, birinin veya diğerinin nasıl yükleneceğini hızlı bir şekilde açıklayacağım.

Arayüz ihtiyacınız olan her şeyi sarıyor, bu örneği sınırlamak için burada sadece 2 yöntemim var.

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

Şimdi eski kamera donanımı API'si için bir sınıfa sahip olun:

@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;
    }
}

Ve yeni donanım api için bir tane daha:

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;
        }
    }
}

Uygun API'yi yükleme

Şimdi ister sınıfınızı CameraOldister CameraNewsınıfınızı yüklemek için API seviyesini kontrol etmeniz gerekecek, çünkü CameraNewsadece api level 21'de mevcut.

Bağımlılık enjeksiyon kurulumunuz varsa, CameraSupportuygulamayı sağlarken modülünüzde bunu yapabilirsiniz . Misal:

@Module public class CameraModule {

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

DI kullanmazsanız, sadece bir yardımcı program yapabilir veya uygun olanı oluşturmak için Fabrika modelini kullanabilirsiniz. Önemli olan, API seviyesinin kontrol edilmesidir.


25
21'den az android API seviyesini desteklemem gerekirse ne olur?
niveuseverto

1
@Angelius, belki de bu dokümantasyon geliştiriciye yardımcı olabilir.android.com/guide/topics/media/camera.html - ancak bu ayrı bir soru olabilir veya kullanımdan kaldırılmış değişkenleri kullanma zorunluluğuyla ilgili soruları araştırabilir.

@Angelius @SuppressWarnings, bu KG stackoverflow.com/questions/7397996/… ile

5
Sadece @deprecated sınıfları kullanmayı değil, aynı zamanda geriye dönük uyumluluğa sahip uygulama yapmayı düşünüyorum? bu konuda herhangi bir resmi yardım var mı? Bunun hakkında bir fikrim var: Mevcut telefon sürümüne karşılık gelen Kamera nesnesi ile desteklenen ICamera arayüzü, ancak bu biraz basit ve bakımı zor ...
19'a kadar niveusever

@Angelius, tarif ettiğiniz şey ayrı bir soru olabilir (önce sorulup sorulmadığını kontrol edin).

5

Eski cihazları kullanımdan kaldırılan kamera API'si aracılığıyla destekleyen ve hem mevcut cihazlar hem de geleceğe taşınan yeni Camera2 API'ye ihtiyaç duyan aynı sorunla karşı karşıya ; Aynı sorunları koştu - ve var olmayan çok farklıdır olasılıkla çünkü, 2 API'leri köprü bir 3. parti kitaplığı bulundu temel OOP ilkeleri döndü .

2 API belirgin şekilde farklıdır ve eski API'de sunulan arayüzleri bekleyen istemci nesneleri için birbirlerini değiştirmeyi sorunlu hale getirir. Yeni API, farklı bir mimari kullanılarak oluşturulan farklı yöntemlere sahip farklı nesnelere sahiptir. Google'ı sevdim ama ragnabbit! bu sinir bozucu.

Bu yüzden, yalnızca uygulamamın ihtiyaç duyduğu kamera işlevlerine odaklanan bir arayüz oluşturdum ve bu arayüzü uygulayan her iki API için de basit bir sarmalayıcı oluşturdum . Bu şekilde, kamera etkinliğim hangi platformda çalıştığını umursamak zorunda değil ...

Ayrıca API'leri yönetmek için bir Singleton kurdum; eski API'nin sarmalayıcısını eski Android işletim sistemi cihazları için arayüzümle ve yeni API'yi kullanarak yeni cihazlar için yeni API'nin sarmalayıcı sınıfını örneklemek. Singleton, API seviyesini elde etmek için tipik bir koda sahiptir ve ardından doğru nesneyi örnekler.

Aynı arabirim her iki sarmalayıcı sınıfı tarafından da kullanılır , bu nedenle Uygulamanın Jellybean veya Marshmallow üzerinde çalışıp çalışmadığı önemli değildir - arabirim uygulamama aynı yöntem imzalarını kullanarak her iki Kamera API'sinden de ihtiyaç duyduğu şeyi sağladığı sürece; kamera, Uygulamada Android'in hem yeni hem de eski sürümleri için aynı şekilde çalışır.

Singleton, API'lere bağlı olmayan bazı ilgili şeyleri de yapabilir - örneğin, cihazda gerçekten bir kamera olduğunu tespit etmek ve medya kitaplığına kaydetmek gibi.

Umarım fikir size yardımcı olur.


Örneğin:public interface AllCameraInterface { void open(); boolean setDirection(); Bitmap preview(); Bitmap takePhoto(); void close(); }
Robert Sherman

örn: 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(); } }O zaman onu döndürmek için bir yöntem ...
Robert Sherman

görünüşe göre ;-) yorumlarda satır kesmelerine izin verilmiyor ama gerçekten işe yarıyor.
Robert Sherman

4
neden yorumlardaki kodları doğrudan Yanıta eklemiyorsunuz?
Angel Koh

@RobertSherman Merhaba Robert, Bu küçük küçük parçacığı yeni için yeniden yazmama yardım eder misin camera2? Gerçekten kafam karıştı ... Sadece enableAutofocuskamerayı açmak ve odağını ayarlamak için bir yönteme ihtiyacım var : stackoverflow.com/questions/19076316/…

0

Şimdi android.hardware.camera2'yi android.hardware olarak kullanmalıyız.Camera kullanımdan kaldırıldı, bu sadece API> 23 FlashLight üzerinde çalışacak

   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

Hangi kamera apisinin kullanılacağı konusunda burada verilen yanıtlar yanlıştır. Ya da yetersiz olduklarını söylemek daha iyi.

Bazı telefonlar (örneğin Samsung Galaxy S6) api seviyesi 21'in üzerinde olabilir ancak yine de Camera2 api'yi desteklemeyebilir.

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;
}

Camera2Api'deki CameraManager sınıfı, kamera özelliklerini okumak için bir yönteme sahiptir. Donanım açısından akıllı cihazın Camera2 Api'yi destekleyip desteklemediğini kontrol etmelisiniz.

Ancak, gerçekten ciddi bir uygulama için çalışmasını istiyorsanız, ele alınması gereken daha fazla sorun var: Gibi, otomatik flaş seçeneği bazı cihazlar için çalışmayabilir veya telefonun pil seviyesi, Kamerada bir RuntimeException oluşturabilir veya telefon geçersiz bir kamera kimliği vb.

Bu nedenle, en iyi yaklaşım, bir geri dönüş mekanizmasına sahip olmaktır, çünkü Camera2 herhangi bir nedenle başlatılamaz, Camera1'i deneyebilirsiniz ve bu da başarısız olursa, sizin için varsayılan Kamera'yı açmak için Android'e bir arama yapabilirsiniz.


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();
           }


 }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.