Kullanımdan android.hardware.Camera
kaldırılırsa ve değişkeni kullanamazsanız, Camera
bunun alternatifi ne olabilir?
Kullanımdan android.hardware.Camera
kaldırılırsa ve değişkeni kullanamazsanız, Camera
bunun alternatifi ne olabilir?
Yanıtlar:
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.
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 String
nesnelerle ç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.
Ş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;
}
}
}
Şimdi ister sınıfınızı CameraOld
ister CameraNew
sınıfınızı yüklemek için API seviyesini kontrol etmeniz gerekecek, çünkü CameraNew
sadece api level 21'de mevcut.
Bağımlılık enjeksiyon kurulumunuz varsa, CameraSupport
uygulamayı 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.
@SuppressWarnings
, bu KG stackoverflow.com/questions/7397996/… ile
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.
public interface AllCameraInterface { void open(); boolean setDirection(); Bitmap preview(); Bitmap takePhoto(); void close(); }
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 ...
camera2
? Gerçekten kafam karıştı ... Sadece enableAutofocus
kamerayı açmak ve odağını ayarlamak için bir yönteme ihtiyacım var : stackoverflow.com/questions/19076316/…
Ş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;
}
}
});
}
}
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.
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();
}
}
android.hardware.camera2