se android.hardware.Camera
for obsoleto e você não puder usar a variável Camera
, qual seria a alternativa para isso?
se android.hardware.Camera
for obsoleto e você não puder usar a variável Camera
, qual seria a alternativa para isso?
Respostas:
De acordo com o guia do desenvolvedor Android para android.hardware.Camera
, eles afirmam:
Recomendamos o uso da nova API android.hardware.camera2 para novos aplicativos.
Na página de informações sobre android.hardware.camera2
, ( link acima), é indicado:
O pacote android.hardware.camera2 fornece uma interface para dispositivos de câmera individuais conectados a um dispositivo Android. Ele substitui a classe obsoleta Camera.
Ao verificar essa documentação, você descobrirá que a implementação dessas 2 APIs de câmera são muito diferentes.
Por exemplo, obter orientação da câmera em android.hardware.camera
@Override
public int getOrientation(final int cameraId) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
return info.orientation;
}
Versus 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;
}
}
Isso torna difícil mudar de um para outro e escrever código que possa lidar com ambas as implementações.
Observe que neste único exemplo de código eu já tive que contornar o fato de que a API de câmera olde funciona com int
primitivas para IDs de câmera enquanto a nova funciona com String
objetos. Para este exemplo, resolvi rapidamente isso usando o int como um índice na nova API. Se as câmeras devolvidas não estiverem sempre na mesma ordem, isso já causará problemas. Uma abordagem alternativa é trabalhar com objetos String e representação String dos antigos cameraIDs int, o que provavelmente é mais seguro.
Agora, para contornar essa enorme diferença, você pode implementar uma interface primeiro e fazer referência a essa interface em seu código.
Aqui vou listar alguns códigos para essa interface e as 2 implementações. Você pode limitar a implementação ao que você realmente usa da API da câmera para limitar a quantidade de trabalho.
Na próxima seção, explicarei rapidamente como carregar um ou outro.
A interface envolve tudo que você precisa, para limitar este exemplo, tenho apenas 2 métodos aqui.
public interface CameraSupport {
CameraSupport open(int cameraId);
int getOrientation(int cameraId);
}
Agora tem uma aula para a API de hardware de câmera antiga:
@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;
}
}
E outro para a nova API de hardware:
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;
}
}
}
Agora, para carregar sua classe CameraOld
ou, CameraNew
você terá que verificar o nível da API, pois CameraNew
está disponível apenas a partir do nível 21 da API.
Se você já tiver a injeção de dependência configurada, poderá fazê-lo em seu módulo ao fornecer a CameraSupport
implementação. Exemplo:
@Module public class CameraModule {
@Provides
CameraSupport provideCameraSupport(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return new CameraNew(context);
} else {
return new CameraOld();
}
}
}
Se você não usa DI, pode apenas fazer um utilitário ou usar o padrão de fábrica para criar o apropriado. Parte importante é que o nível da API é verificado.
@SuppressWarnings
neste controle de qualidade stackoverflow.com/questions/7397996/…
Enfrentando o mesmo problema , suportando dispositivos mais antigos por meio da API de câmera obsoleta e precisando da nova API Camera2 para os dispositivos atuais e para o futuro; Eu tive os mesmos problemas - e não encontrei uma biblioteca de terceiros que faça a ponte entre as 2 APIs, provavelmente porque elas são muito diferentes, mudei para os princípios OOP básicos .
As 2 APIs são marcadamente diferentes, tornando seu intercâmbio problemático para objetos clientes que esperam as interfaces apresentadas na API antiga. A nova API possui objetos diferentes com métodos diferentes, construídos usando uma arquitetura diferente. Adorei o Google, mas ragnabbit! isso é frustrante.
Então, criei uma interface focando apenas na funcionalidade de câmera de que meu aplicativo precisa e criei um wrapper simples para ambas as APIs que implementam essa interface. Dessa forma, minha atividade de câmera não precisa se preocupar com a plataforma em que está sendo executada ...
Também configurei um Singleton para gerenciar a (s) API (s); instanciar o wrapper da API mais antiga com minha interface para dispositivos Android OS mais antigos e a classe de wrapper da nova API para dispositivos mais novos que usam a nova API. O singleton tem um código típico para obter o nível de API e, em seguida, instancia o objeto correto.
A mesma interface é usada por ambas as classes de wrapper , portanto, não importa se o aplicativo é executado em Jellybean ou Marshmallow - contanto que a interface forneça ao meu aplicativo o que ele precisa de qualquer API de câmera, usando as mesmas assinaturas de método; a câmera funciona no aplicativo da mesma maneira para as versões mais recentes e mais antigas do Android.
O Singleton também pode fazer algumas coisas relacionadas não vinculadas às APIs - como detectar se realmente há uma câmera no dispositivo e salvar na biblioteca de mídia.
Espero que a ideia ajude você.
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(); } }
Em seguida, um método para devolvê-lo ...
camera2
? Estou muito confuso ... Eu só preciso do enableAutofocus
método para abrir a câmera e definir seu foco: stackoverflow.com/questions/19076316/…
Agora temos que usar android.hardware.camera2, pois android.hardware.Camera está obsoleto, o que só funcionará na 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;
}
}
});
}
}
As respostas fornecidas aqui como qual câmera api usar estão erradas. Ou melhor, são insuficientes.
Alguns telefones (por exemplo, Samsung Galaxy S6) podem estar acima do nível 21 da API, mas ainda podem não oferecer suporte à 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;
}
A classe CameraManager em Camera2Api tem um método para ler as características da câmera. Você deve verificar se o dispositivo inteligente de hardware é compatível com Camera2 Api ou não.
Mas há mais problemas a serem resolvidos se você realmente quiser fazer funcionar para um aplicativo sério: Por exemplo, a opção de flash automático pode não funcionar para alguns dispositivos ou o nível da bateria do telefone pode criar um RuntimeException na câmera ou no telefone pode retornar um inválido id da câmera e etc.
Portanto, a melhor abordagem é ter um mecanismo de fallback, pois por algum motivo o Camera2 falha ao iniciar, você pode tentar o Camera1 e, se isso também falhar, você pode fazer uma chamada para o Android para abrir a câmera padrão para você.
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