我用一个简单的SOS按钮创建了一个应用程序,当我按下按钮时,它会从手电筒发出摩尔斯电码的SOS信号。这很好用。但是当我第二次按下按钮,或者第二次运行应用程序时它就会崩溃。
之后再次使用一次。
我不知道出了什么问题。
以下是主要活动的代码:
public class MainActivity extends ActionBarActivity {
public final static String SOS_MORSE = "111000111";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/** Called when the user clicks the Send button */
public void sendSOS(View view) {
/* Open the camera and get the parameters to control the flashlight */
Camera cam = Camera.open();
Parameters p = cam.getParameters();
char prevChar = 1;
for (int i = 0; i < SOS_MORSE.length(); i++) {
/* If it's part of the S's the signal has to be faster, short on, short off */
if (SOS_MORSE.charAt(i) == '1') {
/* The last char was a 0 so it was part of the letter O signal, so we pause for a brief time to distinguish between the signals of the O and the S */
if(prevChar == '0'){
try {
Thread.sleep(50); /* Pause for a very short time */
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/* Turn the camera on */
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
/* Short on */
try {
Thread.sleep(120);
} catch (InterruptedException e) {
e.printStackTrace();
}
/* Turn the camera off */
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
cam.setParameters(p);
/* Short off */
try {
Thread.sleep(120);
} catch (InterruptedException e) {
e.printStackTrace();
}
prevChar = SOS_MORSE.charAt(i);
} else { /* If it's part of the O, the signals have to be longer */
/* The last char was a 1 so it was part of the letter S signal, so we pause for a brief time to distinguish between the signals of the S and the O */
if(prevChar == '1'){
try {
Thread.sleep(50); /* Pause for a very short time */
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/* Turn the camera on */
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
/* Turn it on for a longer time */
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
/* Turn the camera off */
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
cam.setParameters(p);
/* Turn it off for a longer time */
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
prevChar = SOS_MORSE.charAt(i);
}
}
cam = null;
}
@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;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
这是活动主xml文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/buttonFlashlight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:onClick="sendSOS"
android:text="SOS" />
这是清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myfirstapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
在logcat中它表示无法连接到相机服务,这行代码:
Camera cam = Camera.open();
答案 0 :(得分:0)
我认为您必须遵守Android准则才能使用Camera
而不是
Camera cam = Camera.open();
使用
Camera cam = getCameraInstance();
// check for null, if it is, then camera is either not available or in use
...
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
使用Camera
之后(如果你已经完成了它),使用Camera的release()
方法并最后使用try catch块
/** Called when the user clicks the Send button */
public void sendSOS(View view) {
Camera cam = null;
try{
cam = getCameraInstance();
...
}
catch(Exception e){
// TODO: if camera is null
// find a work around
// either prompt user that camera is still not available
// or(bad idea) recursion with ProgressBar
// like sendSOS(view); and let the user wait using Handler
// if these doesnt work, add a callback to the camera
// `Camera.ErrorCallback`
// if CAMERA_ERROR_SERVER_DIED will return in `onError(int,Camera)`
// then In this case, the application must release the Camera object and instantiate a new one.
}
finally{
// this should be in a worker thread, and use a callback if camera is already release
// in some cases this should work, but in order not to block the main thread
// we can use asynctask to release the camera resources here and use a callback
// whenever the onPostExecute executes, then trigger a function that camera is ready again to
// be opened
cam.release();
}
}
以下是来自Android指南,您必须检查异常,我认为Camera已经可用,这就是您在logcat中出现异常的原因。
警告:使用Camera.open()时始终检查异常。如果相机正在使用或不存在,则无法检查异常将导致系统关闭您的应用程序。
进一步阅读文档here
希望这会有所帮助:)