我想写一个手电筒。这段代码结果出来了,但是由于某些原因它不能在 Android 5.1 上运行。我在我的 Galaxy Grand Prime 手机上检查了它。
public class MainActivity extends AppCompatActivity {
private ImageButton btnSwitch = null;
private Camera camera = null;
private boolean isFlashOn; //булева переменная для определения включен ли фонарик
private boolean hasFlash; //переменная для определения есть ли вообще фонарик
private Camera.Parameters params;
private CameraManager mCameraManager;
private String mCameraId;
private MediaPlayer mp;
private RelativeLayout activity_main;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
activity_main = (RelativeLayout) findViewById(R.id.activity_main);
btnSwitch = (ImageButton) findViewById(R.id.btnOnOff);
isFlashOn = false;
//найти камеру
hasFlash = getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if (!hasFlash) {
errorDialog();
}
getCamera();
btnSwitch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isFlashOn) {
turnOff();
} else {
turnOn();
}
}
});
}
//Получаем камеру устройства
public void getCamera() {
if (Build.VERSION.SDK_INT >= 21) {
mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
mCameraId = mCameraManager.getCameraIdList()[0];
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
if (camera == null) {
try {
camera = Camera.open();
camera.getParameters();
} catch (RuntimeException ex) {
ex.printStackTrace();
}
}
}
}
public void turnOff() {
if (isFlashOn) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
mCameraManager.setTorchMode(mCameraId, false);
isFlashOn = false;
playOnOffSound();
btnSwitch.setImageResource(R.drawable.button_off);
activity_main.setBackgroundResource(R.drawable.bg_off);
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
if (camera == null || params == null) {
return;
}
params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(params);
camera.stopPreview();
isFlashOn = false;
playOnOffSound();
btnSwitch.setImageResource(R.drawable.button_off);
activity_main.setBackgroundResource(R.drawable.bg_off);
}
}
}
public void turnOn() {
if (!isFlashOn) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
mCameraManager.setTorchMode(mCameraId, true);
playOnOffSound();
isFlashOn = true;
btnSwitch.setImageResource(R.drawable.button_on);
activity_main.setBackgroundResource(R.drawable.bg_on);
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
if (camera == null || params == null) {
return;
}
params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
playOnOffSound();
btnSwitch.setImageResource(R.drawable.button_on);
activity_main.setBackgroundResource(R.drawable.bg_on);
isFlashOn = true;
}
}
}
private void playOnOffSound(){
mp = MediaPlayer.create(this, R.raw.flash_sound);
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
mp.start();
}
@Override
protected void onStop() {
super.onStop();
if(isFlashOn){
turnOff();
}
}
@Override
protected void onPause() {
super.onPause();
if(isFlashOn){
turnOff();
}
}
@Override
protected void onResume() {
super.onResume();
if(isFlashOn){
turnOn();
}
}
public void errorDialog() {
//создаем диалоговое окно
AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).create();
dialog.setTitle("Ошибка!");
dialog.setMessage("Ваше устройство не поддерживает работу со вспышкой.");
dialog.setButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
});
dialog.show();
return;
}
}
我在清单中写了以下内容
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.flash" />
<uses-feature android:name="android.hardware.camera2"/>
据我了解,由于条件原因,它不起作用
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
但如果我改为这样写条件
if (Build.VERSION.SDK_INT >= 21)
然后在这个地方发誓
mCameraManager.setTorchMode(mCameraId, false);
调用需要 API 级别 23(当前最小值为 14):android.hardware.camera2.CameraManager#setTorchMode less... (Ctrl+F1)
在 Android 6 上没问题
该方法
CameraManager.setTorchMode()从 API 23 开始可用,因此“发誓”。您不需要在条件下缩小 API - 对于较小的 API,您有一个带有替代包含的分支。问题是并非所有设备都正确处理该属性
Camera.Parameters.FLASH_MODE_TORCH,因此手电筒无法打开。尤其是三星的产品以这种行为而闻名,必须为其产品发明拐杖,还有一些其他特殊型号。他们需要寻找个性化的解决方案。
在 enSO上更新关于这个问题
的 好问题。据我了解,API < 23 没有通用解决方案。