0

電話の受信中にカメラの懐中電灯の点滅をシミュレートする単純な Android アプリケーションを作成しようとしています。ユーザーが電話に出るかキャンセルした場合、懐中電灯の点滅を止めたいです。Handler と Runnable を使用してまばたきをシミュレートしていますが、問題は、ユーザーが応答した後にハンドラーを停止したり、呼び出しをキャンセルしたりできないことです。私のソースコード:

public class CallReceiver extends BroadcastReceiver 
{
    private static Camera cam = null;
    private Handler handler = new Handler();

    @Override
    public void onReceive(Context context, Intent intent) 
    {
        //device is ringing
        if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING))
        {
            if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) 
            {
                startFlashBlink();
            }
        }
        //call was answered or canceled
        else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE) 
            || intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
        {
            stopFlashBlink();
        }
    }

    //for simulating flash blink
    Runnable flashBlinkRunnable = new Runnable()
    {
        public void run() 
        {   
            cam = Camera.open();
            Parameters p = cam.getParameters();
            p.setFlashMode(Parameters.FLASH_MODE_TORCH);
            cam.setParameters(p);
            cam.startPreview();
            cam.stopPreview();
            cam.release();
            cam = null;
            handler.post(flashBlinkRunnable);
        }       
    };

    //start flash blink light
    public void startFlashBlink()
    {
        flashBlinkRunnable.run();
    }

    //stop flash blink light
    public void stopFlashBlink()
    {
        handler.removeCallbacks(flashBlinkRunnable);
        if (cam != null)
        {
            cam.stopPreview();
            cam.release();
            cam = null;
        }
    }
}
4

3 に答える 3

1

このようには機能しません。コードに重大な欠陥があります。BroadcastReceiver問題は、この方法を使用できないことです。のドキュメントからBroadcastReceiver:

BroadcastReceiver オブジェクトは、onReceive(Context, Intent) への呼び出しの間のみ有効です。コードがこの関数から戻ると、システムはオブジェクトが終了し、アクティブではなくなったと見なします。

また、ドキュメントのアプリの基礎からこれに注意してください。

ただし、より一般的には、ブロードキャスト レシーバは他のコンポーネントへの単なる「ゲートウェイ」であり、最小限の作業を行うことを目的としています。たとえば、イベントに基づいて何らかの作業を実行するサービスを開始する場合があります。

そのため、放送受信機はサービスを開始し、放送受信機自体で行うのではなく、フラッシュの点滅を開始または停止するように指示する必要があります。

于 2013-01-26T11:47:35.180 に答える
0

問題はサービスで解決されます。

public class FlashBlinkService extends Service 
{
    private static Camera cam = null;
    private Handler handler = new Handler();

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

    @Override
    public void onCreate()
    {
        super.onCreate();
        startFlashBlink();      
    }

    //for simulating flash blink
    Runnable flashBlinkRunnable = new Runnable()
    {
        public void run() 
        {   
            cam = Camera.open();
            Parameters p = cam.getParameters();
            p.setFlashMode(Parameters.FLASH_MODE_TORCH);
            cam.setParameters(p);
            cam.startPreview();
            cam.stopPreview();
            cam.release();
            cam = null;
            handler.post(flashBlinkRunnable);
        }       
    };

    //start flash blink light
    public void startFlashBlink()
    {
        flashBlinkRunnable.run();
    }

    //stop flash blink light
    public void stopFlashBlink()
    {
        handler.removeCallbacks(flashBlinkRunnable);
        stopCamera(cam);
    }

    //stop camera
    private void stopCamera(Camera cam)
    {
        if (cam != null)
        {
            cam.stopPreview();
            cam.release();
            cam = null;
        }
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        handler.removeCallbacks(flashBlinkRunnable);
        stopCamera(cam);
    }
}


public class CallReceiver extends BroadcastReceiver 
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        //device is ringing
        if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING))
        {
            if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) 
            {
                startFlashBlinkService(context);
            }
        }
        //call was answered or canceled
        else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE) 
                || intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
        {
            stopFlashBlinkService(context);
        }
    }

    //start flash blink light
    public void startFlashBlinkService(Context context)
    {
        if (!isBlinkServiceRunning(context))
        {
            Intent iService = new Intent(context, FlashBlinkService.class);
            context.startService(iService);
        }
    }

    //stop flash blink light
    public void stopFlashBlinkService(Context context)
    {
        if (isBlinkServiceRunning(context))
        {
            Intent iService = new Intent(context, FlashBlinkService.class);
            context.stopService(iService);
        }
    }


    //check if the blink service is running
    public boolean isBlinkServiceRunning(Context context)
    {
        ActivityManager manager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
        {
            if ("path.to.package.FlashBlinkService".equals(service.service.getClassName()))
            {
                return true;
            }
        }
        return false;
    }
}

(:

于 2013-01-26T19:55:26.820 に答える
0

ブロードキャスト レシーバーは、OS がその意図を解決するアプリを見つけるよりも、何かを行う意図があることを OS に伝える方法です。あなたの場合、コードはすべて放送受信機にあります。ブロードキャスト レシーバーで解決する代わりに、問題を解決するサービスを作成してみてください。

于 2013-01-26T12:06:33.397 に答える