jika android.hardware.Camera
sudah tidak digunakan lagi dan Anda tidak dapat menggunakan variabel Camera
, lalu apa alternatifnya?
jika android.hardware.Camera
sudah tidak digunakan lagi dan Anda tidak dapat menggunakan variabel Camera
, lalu apa alternatifnya?
Jawaban:
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.
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 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 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.
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;
}
}
}
Sekarang untuk memuat salah satu CameraOld
atau CameraNew
kelas Anda, Anda harus memeriksa level API karena CameraNew
hanya tersedia dari api level 21.
Jika Anda sudah menyiapkan injeksi dependensi, Anda dapat melakukannya di modul Anda saat menyediakan CameraSupport
implementasi. 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.
@SuppressWarnings
di QA stackoverflow.com/questions/7397996/…
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.
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(); } }
Kemudian metode untuk mengembalikannya ...
camera2
? Saya benar-benar bingung ... Saya hanya perlu enableAutofocus
metode untuk membuka kamera dan mengatur fokusnya: stackoverflow.com/questions/19076316/…
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;
}
}
});
}
}
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.
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