我正在尝试制作适用于所有Android设备的简单手电筒应用,包括Nexus 5(要求我实施SurfaceView
)。
但我的应用程序在运行时随时都会崩溃。我做错了什么?
我的完整代码如下:
public class MainActivity extends Activity implements Callback {
//flag to detect flash is on or off
private boolean isLighOn = false;
private Camera camera;
private Button button;
private Parameters p;
private SurfaceHolder mHolder;
@Override
protected void onStart() {
super.onStart();
SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW);
SurfaceHolder mHolder = preview.getHolder();
mHolder.addCallback(this);
}
@Override
protected void onStop() {
super.onStop();
if (camera != null) {
camera.release();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Context context = this;
PackageManager pm = context.getPackageManager();
// if device support camera?
if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Log.e("err", "Device has no camera!");
return;
}
camera = Camera.open();
final Parameters p = camera.getParameters();
final ToggleButton tb = (ToggleButton) findViewById(R.id.toggle);
final ImageView image = (ImageView) findViewById(R.id.photo);
tb.setText(null);
tb.setTextOn(null);
tb.setTextOff(null);
tb.setBackgroundResource(R.drawable.check);
tb.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (tb.isChecked()) {
image.setImageResource(R.drawable.b);
turnOffFlash();
} else {
image.setImageResource(R.drawable.a);
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private void turnOnFlash(){
Log.i("info", "torch is turn on!");
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
isLighOn = true;
}
private void turnOffFlash(){
Log.i("info", "torch is turn off!");
p.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.stopPreview();
isLighOn = false;
}
@Override
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder){
mHolder = holder;
try {
Log.i("SurfaceHolder", "setting preview");
camera.setPreviewDisplay(mHolder);
} catch (IOException e){
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder){
Log.i("SurfaceHolder", "stopping preview");
camera.stopPreview();
mHolder = null;
}
}
我的布局XML文件中的代码发布在
下面<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal" >
<ImageView
android:id="@+id/photo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/b"
android:scaleType="centerCrop"
android:contentDescription="@string/happy" />
<ToggleButton
android:id="@+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_margin="10dp"
android:layout_marginBottom="17dp"
android:background="@drawable/check"
android:focusable="false"
android:focusableInTouchMode="false" />
<SurfaceView
android:id="@+id/PREVIEW"
android:layout_width="1dp"
android:layout_height="1dp" />
</RelativeLayout>
这是我的Logcat
07-24 03:09:14.433: V/Provider/Settings(16560): invalidate [system]: current 64 != cached 0
07-24 03:09:14.436: V/Provider/Settings(16560): from db cache, name = sound_effects_enabled , value = 0
07-24 03:09:14.437: I/info(16560): torch is turn off!
07-24 03:09:14.437: D/AndroidRuntime(16560): Shutting down VM
07-24 03:09:14.437: W/dalvikvm(16560): threadid=1: thread exiting with uncaught exception (group=0x4112d9a8)
07-24 03:09:14.441: E/AndroidRuntime(16560): FATAL EXCEPTION: main
07-24 03:09:14.441: E/AndroidRuntime(16560): java.lang.NullPointerException
07-24 03:09:14.441: E/AndroidRuntime(16560): at com.example.torch.MainActivity.turnOffFlash(MainActivity.java:103)
07-24 03:09:14.441: E/AndroidRuntime(16560): at com.example.torch.MainActivity.access$0(MainActivity.java:100)
07-24 03:09:14.441: E/AndroidRuntime(16560): at com.example.torch.MainActivity$1.onClick(MainActivity.java:76)
07-24 03:09:14.441: E/AndroidRuntime(16560): at android.view.View.performClick(View.java:4211)
07-24 03:09:14.441: E/AndroidRuntime(16560): at android.widget.CompoundButton.performClick(CompoundButton.java:100)
07-24 03:09:14.441: E/AndroidRuntime(16560): at android.view.View$PerformClick.run(View.java:17446)
07-24 03:09:14.441: E/AndroidRuntime(16560): at android.os.Handler.handleCallback(Handler.java:725)
07-24 03:09:14.441: E/AndroidRuntime(16560): at android.os.Handler.dispatchMessage(Handler.java:92)
07-24 03:09:14.441: E/AndroidRuntime(16560): at android.os.Looper.loop(Looper.java:153)
07-24 03:09:14.441: E/AndroidRuntime(16560): at android.app.ActivityThread.main(ActivityThread.java:5297)
07-24 03:09:14.441: E/AndroidRuntime(16560): at java.lang.reflect.Method.invokeNative(Native Method)
07-24 03:09:14.441: E/AndroidRuntime(16560): at java.lang.reflect.Method.invoke(Method.java:511)
07-24 03:09:14.441: E/AndroidRuntime(16560): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
07-24 03:09:14.441: E/AndroidRuntime(16560): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
07-24 03:09:14.441: E/AndroidRuntime(16560): at dalvik.system.NativeStart.main(Native Method)
答案 0 :(得分:1)
导致问题的一行是
p.setFlashMode(Parameters.FLASH_MODE_OFF);
此时p
为空。您可能认为已使用
final Parameters p = camera.getParameters();
在onCreate()
方法中,但这不正确。此p
已在onCreate()
内声明并初始化,因此这是唯一可用的地方。
private Parameters p;
以上p
是您的应用在p.setFlashMode(Parameters.FLASH_MODE_OFF);
行中使用的{。}}。
要纠正这一点,只需更改
final Parameters p = camera.getParameters();
到
p = camera.getParameters();
如果你真的需要它是最终的,你可以将该关键字添加到你的排行榜上
private Parameters p;