我正在制作一个手电筒应用程序,其中我放置了两个切换按钮,两个切换按钮的功能是
1)给予频闪(sos)效果。 EnableStrobe / DisableStrobe。
2)简单的手电筒效果。 EnableFlashlight / DisableFlashlight。如果我单独切换这些ToggleButtons或在这些切换之间慢慢切换ToggleBUttonsthen我的应用程序工作正常。但快速切换这些切换按钮我的应用程序突然终止。我已经为每个ToggleButton创建了两个线程类。事情正在发挥作用,我觉得我的onClickListener代码存在一些问题。
主要ui线程中的onClickListener代码
strobebutton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (flag1 == 1) {
flasheffect.isflashOn = true;
flashbutton.setChecked(false);
}
if (strobebutton.isChecked()) {
bw = new Thread(strobeffect);
bw.start();
flag2 = 1;
} else {
strobeffect.requestStop = true;
}
}
});
flashbutton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
if (flag2 == 1) {
runner.requestStop = true;
strobeffect.setChecked(false);
}
if (togglebutton1.isChecked()) {
aw = new Thread(flasheffect);
aw.start();
flag1 = 1;
} else {
flasheffect.isflashOn = true;
}
}
});
与StrobeClass关联的ToggleButton
public class StrobeRunner implements Runnable {
protected StrobeRunner() {
}
public static StrobeRunner getInstance() {
return (instance == null ? instance = new StrobeRunner() : instance);
}
private static StrobeRunner instance;
public volatile boolean requestStop = false;
public volatile boolean isRunning = false;
public volatile int delay = 10;
public volatile int delayoff = 10;
public volatile StrobeLightConfig controller;
public volatile String errorMessage = "";
public void run() {
if (isRunning)
return;
requestStop = false;
isRunning = true;
Camera cam = Camera.open();
Camera.Parameters pon = cam.getParameters(), poff = cam.getParameters();
pon.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
poff.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
while (!requestStop) {
try {
cam.setParameters(pon);
Thread.sleep(delay);
cam.setParameters(poff);
Thread.sleep(delayoff);
} catch (InterruptedException ex) {
} catch (RuntimeException ex) {
requestStop = true;
errorMessage = "Error setting camera flash status. Your device may be unsupported.";
}
}
cam.release();
isRunning = false;
requestStop = false;
controller.mHandler.post(controller.mShowToastRunnable);
}
}
使用FlashEffect类的代码
public class FlashOn implements Runnable {
protected FlashOn() {
}
public static FlashOn getInstance() {
return (instance == null ? instance = new FlashOn() : instance);
}
private static FlashOn instance;
public volatile StrobeLightConfig control;
public volatile boolean isflashOn = false;
public volatile boolean isRunning = false;
public volatile String errMessage = "";
Parameters param;
public void run() {
if (isRunning) {
return;
}
isRunning = true;
isflashOn = false;
Camera camera = Camera.open();
param = camera.getParameters();
param.setFlashMode(Parameters.FLASH_MODE_TORCH);
while (!isflashOn) {
try {
camera.setParameters(param);
} catch (RuntimeException e) {
isflashOn = true;
}
}
camera.release();
isflashOn = false;
isRunning = false;
}
}
logcat的
10-19 03:37:29.521: E/AndroidRuntime(27146): FATAL EXCEPTION: Thread-16457
10-19 03:37:29.521: E/AndroidRuntime(27146): Process: com.stwalkerster.android.apps.strobelight, PID: 27146
10-19 03:37:29.521: E/AndroidRuntime(27146): java.lang.RuntimeException: Fail to connect to camera service
10-19 03:37:29.521: E/AndroidRuntime(27146): at android.hardware.Camera.native_setup(Native Method)
10-19 03:37:29.521: E/AndroidRuntime(27146): at android.hardware.Camera.<init>(Camera.java:364)
10-19 03:37:29.521: E/AndroidRuntime(27146): at android.hardware.Camera.open(Camera.java:334)
10-19 03:37:29.521: E/AndroidRuntime(27146): at com.stwalkerster.android.apps.strobelight.FlashOn.run(FlashOn.java:28)
10-19 03:37:29.521: E/AndroidRuntime(27146): at java.lang.Thread.run(Thread.java:841)
我的问题可能很愚蠢,但我已经坚持了很长一段时间。
谢谢
答案 0 :(得分:0)
看起来你的下一个线程正在尝试打开相机,而前一个尚未发布它,添加日志以验证它。您的线程同步代码可能有问题,下一个线程应始终只在前一个线程停止后启动。使用ExecutorService应该可以很容易地实现从队列中执行一个runnable。
我认为你可以保留一个全局活动Camera对象并在onStart中打开它并在onPause中释放,或者至少在某个全局实例或类上同步你的线程。
答案 1 :(得分:0)
我建议每个活动只使用一个Camera对象。因为你的线程正在使用不同的Camera对象一个线程正在尝试打开相机,而另一个线程尚未释放它并且快速切换会导致Fail to connect to camera service
。
<强>原因:强>
根据 android camera open documentation ,会抛出运行时异常:
如果与相机服务的连接失败(例如,如果相机正在被其他进程使用或设备策略管理器已禁用相机)
如何实现:
在Activity中创建一个( only )相机对象,并使用Thread类的构造函数 getter setter将Pass Camera Object传递给Runnable类。