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

カメラオブジェクトへの参照または回避策を保持する方法を知っている人はいますか?サービスの使用が頭に浮かびますが、市場に出回っている他のアプリは、同じタスクを実行するためにサービスを使用していないようです。

4

2 に答える 2

1

カメラの制御に関するドキュメントによると、クラス内で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()、カメラが適切に解放されるようにすることをお勧めします。おそらく、それが長期間オンのままになるのを防ぐために、固定された最大期間の後にそれを解放することさえできます。

気の利いたアプリのようですね!

于 2013-02-08T22:08:05.323 に答える
1

アドバイスをくれたPaulLammertsmaに感謝します。カメラオブジェクトを保存するサービスを追加することで問題を解決しました。

受信者コード:

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();
}   
}
于 2013-02-10T23:14:16.560 に答える