0

Я разработал приложение для Android, которое может включить светодиодную вспышку. На большинстве телефонов это нормально работает, но поскольку приложение загружается из Google Play, я получаю некоторые сообщения о сбоях в фонаре. У меня даже есть отчет для Nexus 5, у меня такой же телефон, но у меня нет никаких проблем. Это мой код:Сбой на некоторых устройствах при попытке включения вспышки

private ImageButton mFlashButton; 
private Parameters mParams; 
private Camera mCamera; 
private Thread t; 
private ImageView ivRing; 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.flashlight_fragment, 
      container, false); 

    ivRing = (ImageView) view.findViewById(R.id.ivRing); 

    // flash switch button 
    mFlashButton = (ImageButton) view.findViewById(R.id.flashlight_button); 

    // Switch button click event to toggle flash on/off 
    mFlashButton.setOnClickListener(mClickListener); 

    return view; 
} 

View.OnClickListener mClickListener = new View.OnClickListener() { 
    public void onClick(View v) { 
     if (mLightOn) { 
      turnOffFlash(); 
     } else { 
      turnOnFlash(); 
     } 
    } 
}; 

@Override 
public void onStart() { 
    super.onStart(); 
    SurfaceView preview = (SurfaceView) getView().findViewById(R.id.PREVIEW); 
    SurfaceHolder mHolder = preview.getHolder(); 
    mHolder.addCallback(this); 
} 

@Override 
public void onPause() { 
    super.onPause(); 
    turnOffFlash(true); 
} 

// Turning On flash 
private void turnOnFlash() { 

    if (!mLightOn) { 
     //if camera not found, break 
     if (mCamera == null || mParams == null) { 
      Toast.makeText(getActivity(), "Error", Toast.LENGTH_SHORT).show(); 
     } else { 
      mParams = mCamera.getParameters(); 
      mParams.setFlashMode(Parameters.FLASH_MODE_TORCH); 
      mCamera.setParameters(mParams); 
      mCamera.startPreview(); 
      mLightOn = true; 
     } 
    } 

    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 
} 


// Turning Off flash 
private void turnOffFlash() { 

    if (mLightOn) { 
     //if camera is null, break; 
     if (mCamera == null || mParams == null) { 
      Toast.makeText(getActivity(), "Error", Toast.LENGTH_SHORT).show(); 
     } else { 
      //strobo not running, just turn flash off 
      mParams = mCamera.getParameters(); 
      mParams.setFlashMode(Parameters.FLASH_MODE_OFF); 
      mCamera.setParameters(mParams); 
      mCamera.stopPreview(); 
      mLightOn = false; 
     } 
     getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 
    } 
} 


@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 

} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    if (mCamera != null) { 
     mCamera.stopPreview(); 
     mCamera.setPreviewCallback(null); 
     mCamera.release(); 
     mCamera = null; 
    } 
} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    if (mCamera == null) { 
     //next line forced closed once, should look into this 
     try { 
      mCamera = Camera.open(); 
      mParams = mCamera.getParameters(); 
     } catch (Exception e) { 
      Toast.makeText(getActivity(), "Something went wrong, please restart flashlight", Toast.LENGTH_SHORT).show(); 
     } 
     try { 
      mCamera.setPreviewDisplay(holder); 
     } catch (Exception e) { 
      mCamera.release(); 
      mCamera = null; 
      Toast.makeText(getActivity(), "Something went wrong, please restart flashlight", Toast.LENGTH_SHORT).show(); 
     } 
    } 
} 

} 

Эти отчеты о сбоях я получаю:

java.lang.RuntimeException: setParameters failed 
at android.hardware.Camera.native_setParameters(Native Method) 
at android.hardware.Camera.setParameters(Camera.java:1650) 
at android.view.View.performClick(View.java:4438) 
at android.view.View$PerformClick.run(View.java:18422) 
at android.os.Handler.handleCallback(Handler.java:733) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:136) 
at android.app.ActivityThread.main(ActivityThread.java:5017) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:515) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) 
at dalvik.system.NativeStart.main(Native Method) 

А также этот краш-отчет:

java.lang.NullPointerException: Attempt to invoke virtual method 'void  android.hardware.Camera.setPreviewDisplay(android.view.SurfaceHolder)' on a null object reference 
at android.view.SurfaceView.updateWindow(SurfaceView.java:572) 
at android.view.SurfaceView.access$000(SurfaceView.java:86) 
at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:175) 
at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847) 
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1867) 
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996) 
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5600) 
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761) 
at android.view.Choreographer.doCallbacks(Choreographer.java:574) 
at android.view.Choreographer.doFrame(Choreographer.java:544) 
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747) 
at android.os.Handler.handleCallback(Handler.java:733) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:136) 
at android.app.ActivityThread.main(ActivityThread.java:5001) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 

Кто-нибудь имеет ни малейшего понятия, что происходит Вот? Тот факт, что он не врезаться на моем Nexus 5 и делает на другой путает меня ..

Заранее спасибо

ответ

1

Может быть некоторые устройства не поддерживают для вспышки (может быть, они не имеют вспышки), так что для Для этого сначала нужно проверить, поддерживает ли устройство фонарик или нет.

boolean hasFlash = getApplicationContext().getPackageManager() 
     .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH); 

if (!hasFlash) { 
    // device doesn't support flash 
    // Show alert message and close the application 
    AlertDialog alert = new AlertDialog.Builder(context) 
      .create(); 
    alert.setTitle("Error"); 
    alert.setMessage("Sorry, your device doesn't support flash light!"); 
    alert.setButton("OK", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int which) { 
      // closing the application or what ever you want if device does not support 
      finish(); 
     } 
    }); 
    alert.show(); 
    return; 
} 
else { 
    //turn on flash light code here.... 
} 
+0

Спасибо за ваш ответ, но я уже проверял это. Этот код предназначен только для устройств со светодиодной вспышкой. –

1
mCamera.setPreviewDisplay(holder); 

является то, что выходит из строя. Вы называете NPE другим методом и не обрабатываете NPE в методе.

+0

Не могли бы вы уточнить, как мне это разрешить? –

+0

surfaceCreated как функция действительно странно, если камера == null, вы пытаетесь использовать эти аргументы. Один из них должен пройти вместе с владельцем, который также равен 0. Поскольку я понятия не имею, что такое setPreviewDisplay, я бы предложил вам просмотреть эту часть. – Paul

+0

Я верю, что surfaceCreated вызывается, когда начинается действие, поэтому, если камера в этот момент равна нулю, мне нужно создать экземпляр с помощью Camera.open(). Держатель должен быть создан в onStart(), за исключением того, что я действительно не знаю, почему это иногда терпит неудачу. По моему опыту он работает каждый раз. Спасибо за ваш вклад, кстати! –