再次按下android app按钮会导致崩溃

时间:2014-10-04 13:03:45

标签: java android xml android-camera

我用一个简单的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();

1 个答案:

答案 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

希望这会有所帮助:)