今天帮一个同学做一个东西,要求在手机上输入1和0控制手机闪关灯的亮灭。开始以为很简单,仔细一想,还是有点意思的(当然对于大牛来说这都不是事!),简单的布局,这里就贴代码了,直接上效果图
oncreate方法里面也是很简单
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
editText=(EditText) findViewById(R.id.edittext);
button.setOnClickListener(new ButtonOnClick());
context = this;
}
这里通过camera控制闪光灯,当然这是比较古老的方法,也有其他的方法,
这里写了个内部类,更方便的实现对闪光灯的控制,,这部分代码不是我写的,其他人写好了,我只写了后面的控制逻辑
class ControlFlash {
public Camera camera;
public Camera.Parameters parameters;
public ControlFlash() {
camera = Camera.open();
parameters = camera.getParameters();
}
public void open() {
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
camera.startPreview();
}
public void close() {
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.stopPreview();
}
}
重点看一下ButtonOnClick里面的代码
private final class ButtonOnClick implements View.OnClickListener {
ControlFlash cf = new ControlFlash();
public void onClick(View v) {
// TODO Auto-generated method stub
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
String string=editText.getText().toString();
char[] myinput=!TextUtils.isEmpty(string)?string.toCharArray():input;
for (char a : myinput) {
if (a == '1') {
new Handler(context.getMainLooper()).postDelayed(
new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Log.e("mythread", Thread.currentThread().getName());
cf.open();
new Handler(context.getMainLooper())
.postDelayed(
new Runnable() {
@Override
public void run() {
// TODO
// Auto-generated
// method
// stub
cf.close();
}
}, 20);
}
}, 50);
}
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
}
首先拿到一个ControlFlash的对象,这里我习惯在子线程里面做一些其他的事。在run方法中首先拿到输入的字符,判断一下,很简单,input是已经赋值的一个char数组,这里使用Handler的postDelayed方法来处理延时操作,,(如果直接循环判断每个字符的话,运行时间极短,手机根本来不及反应,这里可以了解一下手机闪光灯的原理),,,当然延迟操作还可以使用线程,或者延时器都行,本例中使用postDelayed的方法,,,可以看到我们在new Handler的时候,传入了context.getMainLooper(),context就是activity实例,,,就是让下面run方法中的代码在主线程的消息队列处理(Looper.getMianLoooper也是一样的),,,,这里不知道为啥在new Handler之前使用Looper.perare();的时候,run里面的代码就不执行,,,懂得朋友告诉我哦,,,这里为什么这样做呢,,这里我们是在子线程中处理这些逻辑,而子线程中需要自己去添加消息队列(主线程中系统会处理好),,这里由于Looper.perare试了不知道啥原因不行,所以就添加到主线程的消息队列中,,打印出来的日志,,可以看到确实在主线程里面
下面可能有些朋友会问为啥要让线程sleep0.1秒,,因为我们让打开闪光灯的操作和关闭操作分别延时0.05和0.02秒(这两个值是随手设置的,,)如果没有sleep,,可以想象一下,打开和延迟由于有时间差,就不会成对的交替起作用,这样很可能会导致灯闪的很乱,,,sleep0.1秒让前次的打开关闭操作已经完成,,,这样就OK了,,(本人新手,对looper以及消息处理机制还没有透彻理解,有错的地方还请指出)
高能!!!
刚刚那个人说哦要的不是这样的。。,是这样的
public void run() {
// TODO Auto-generated method stub
String string = editText.getText().toString();
char[] myinput = !TextUtils.isEmpty(string) ? string
.toCharArray() : input;
for (char a : myinput) {
if (a == '1') {
cf.open();
// new Handler(context.getMainLooper()).postDelayed(
// new Runnable() {
//
// @Override
// public void run() {
// // TODO Auto-generated method stub
// Log.e("mythread", Thread
// .currentThread().getName());
// cf.open();
//
// }
// }, 50);
} else {
cf.close();
// new Handler(context.getMainLooper())
// .postDelayed(
// new Runnable() {
//
// @Override
// public void run() {
// // TODO
// // Auto-generated
// // method
// // stub
// cf.close();
// }
// }, 20);
}
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
一行代码,,,我晕,他需要的是1的时候一直亮,而不是闪一下,,,(模拟信号和离散信号吧,,哈哈)。。。伙伴们以后要注意一定要与委托方交流好再动手!!!