Frage

I'm making an app that turns the flashlight on when the phone starts ringing and should turn it off when it stops ringing. The problem is that the camera gets locked when the phone starts ringing, and the object reference to it is lost so I don't know how to turn it off later.

I'm using a BroadcastReceiver to turn it on/off:

@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();
    }
}

Does anyone know how to keep the reference to camera object or any workaround? Using a service comes to my mind but the other apps on market don't seem to use services to accomplish the same task.

War es hilfreich?

Lösung 2

Thanks to Paul Lammertsma for advice. I solved the problem by adding a service that saves the camera object.

Receiver code:

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));
    }
}
}

Service code:

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();
}   
}

Andere Tipps

According to the documentation on controlling the camera, you should hold a reference in the class to the Camera object and release it when you're done with it. They do this by addressing the object through a field.

You might be able to simply resolve your problem by doing the same:

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;
        }
    }

}

If you are doing this from a service, I would suggest also adding the logic for releasing the camera in the onDestroy() to make sure the camera is properly freed. Perhaps even release it after a fixed maximum duration to prevent it from staying on for a prolonged period of time.

Sounds like a nifty app!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top