2013-02-08 101 views
2

我正在制作一个应用程序,可以在手机开始振铃时打开手电筒,并在铃声停止时将其关闭。问题在于手机开始响铃时摄像头被锁定,并且对象引用该对象会丢失,因此我不知道如何在稍后将其关闭。手机停止响铃时关闭手电筒?

我使用一个BroadcastReceiver来开启/关闭:

@Override 
public void onReceive(Context context, Intent intent) { 
    String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 

    if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) { 
     if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) { 
      cam = Camera.open(); 
      Parameters p = cam.getParameters(); 
      p.setFlashMode(Parameters.FLASH_MODE_TORCH); 
      cam.setParameters(p); 
      cam.startPreview(); 
     } 
    } 

    if (TelephonyManager.EXTRA_STATE_IDLE.equals(state)) { 
     cam = Camera.open(); 
     cam.stopPreview(); 
     cam.release(); 
    } 
} 

有谁知道如何保持基准相机对象或任何解决方法吗?在我看来,使用服务是我的想法,但市场上的其他应用程序似乎并未使用服务来完成相同的任务。

回答

1

感谢Paul Lammertsma的建议。 我通过添加一个保存相机对象的服务来解决问题。

接收器代码:

public class Receiver extends BroadcastReceiver { 
SharedPreferences prefs = null; 
boolean enabled = false; 
@Override 
public void onReceive(Context context, Intent intent) { 
    prefs = PreferenceManager.getDefaultSharedPreferences(context); 

    AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 
    int ringState = am.getRingerMode(); 
    enabled = prefs.getBoolean("full", false); 
    if (!enabled || ringState != AudioManager.RINGER_MODE_NORMAL) { 
     return; 
    } 

    String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 

    if (TelephonyManager.EXTRA_STATE_RINGING.equals(state) || 
      TelephonyManager.EXTRA_STATE_IDLE.equals(state) || 
      TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) { 
     context.startService(new Intent(context, MyService.class).putExtra("state", state)); 
    } 
} 
} 

服务代码:

public class MyService extends Service { 
Camera cam = null; 
boolean offhook = false; 

@Override 
public IBinder onBind(Intent intent) { 
    return null; 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 

    String state = intent.getStringExtra("state"); 

    if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) { 
     if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH) && !offhook) { 
        cam = Camera.open(); 
        Parameters p = cam.getParameters(); 
        p.setFlashMode(Parameters.FLASH_MODE_TORCH); 
        cam.setParameters(p); 
     } 
    } 

    if (TelephonyManager.EXTRA_STATE_IDLE.equals(state)) { 
     if (!offhook) { 
      if (cam != null) { 
       cam.release(); 
       cam = null; 
      } 
      this.stopSelf(); 
     } else { 
      offhook = false; 
     } 
    } 

    if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) { 
     offhook = true; 
     if (cam != null) { 
      cam.stopPreview(); 
      cam.release(); 
      cam = null; 
     } 
     this.stopSelf(); 
    } 

    return super.onStartCommand(intent, flags, startId); 
} 

@Override 
public void onDestroy() { 
    if (cam != null) { 
     cam.release(); 
     cam = null; 
    } 
    super.onDestroy(); 
} 
} 
+1

太好了,谢谢分享。 – 2013-02-11 08:48:38

1

根据the documentation on controlling the camera,应该在类中引用Camera对象,并在完成后释放它。他们通过一个领域来解决这个问题。

您可能能够做同样的简单解决您的问题:

public TelephonyReceiver extends BroadcastReceiver { 

    Camera mCamera; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 

     if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) { 
      if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) { 
       mCamera = Camera.open(); 
       Parameters p = mCamera.getParameters(); 
       p.setFlashMode(Parameters.FLASH_MODE_TORCH); 
       mCamera.setParameters(p); 
       mCamera.startPreview(); 
      } 
     } 

     if (TelephonyManager.EXTRA_STATE_IDLE.equals(state) && mCamera != null) { 
      mCamera.stopPreview(); 
      mCamera.release(); 
      // Make sure to clear the reference, otherwise we might attempt to 
      // release the camera a second time 
      mCamera = null; 
     } 
    } 

} 

如果是从一个服务做这个,我建议还增加了逻辑释放的相机在onDestroy()使确定相机已正确释放。也许甚至在固定的最长持续时间后释放它,以防止它长时间停留。

听起来像一个漂亮的应用程序!

+0

是啊,这正是我此刻在做什么。但是,当BroadcastReceiver被触发时,它只能在onReceive方法的持续时间内生效(所以在振铃开始时它会触发手电筒,然后整个实例将与我的相机引用一起死亡),下次它被触发时,会创建一个新对象这也创建了新的相机对象,因为相机正被前一个死相机对象使用,所以无法访问相机)。 – 2013-02-08 23:32:33

+1

那就是你的问题的根源。您需要将BroadcastReceiver封装在Service中。 – 2013-02-09 15:23:05

+1

是的,你说得对。我通过实施一项服务解决了这个问题。 – 2013-02-10 23:09:45