2014-10-04 188 views
0

我用簡單的SOS按鈕創建了一個應用程序,當我按下按鈕時,它從手電筒發出莫爾斯碼的SOS信號。這工作正常。但是當我再次按下按鈕,或者第二次運行應用程序時,它就會崩潰。第二次按下android應用程序按鈕導致崩潰

之後,它再次工作1次。

我不知道什麼是錯的。

下面是主要的活動我的代碼:

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

我認爲你必須遵循的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

希望這將有助於:)

+0

謝謝,這使得它爲我工作。但是我懷疑如果getInstance返回null,如果這個錯誤不會發生錯誤,那麼最後你還是要做cam.release(),如果cam爲null,那麼你得到一個null pointerexception。我想知道如果我的解決方案在最後只能使用cam.release嗎? – user3801533 2014-10-04 14:33:48

+0

@ user3801533查看我的編輯,在你的try catch finally塊中放入一個catch異常。 – Spurdow 2014-10-04 14:59:52