0

IP カメラからの MJPEG ストリームを表示するための surfaceview があります。1つのケースを除いて、うまく機能しています。

surfaceview を表示するアクティビティには、次のフラグがあります。

WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON

(アプリから)通常どおりアクティビティを開始すると、カメラの画像が表示されます。しかし、電話がスリープ状態のときにバックグラウンド サービスからアクティビティを開始すると、アクティビティが開始され、電話のロックが解除され、画面がオンになり、表面ビューに何も描画されていないことを除いて、すべてが正常に表示されます。MJPEGストリームが正常に受信できるようになり、キャンバスに描画したように見えますが、何も表示されません。電話を回転させると、画像が表示され、この時点からすべてが正常に機能します。

関連するコードをここに置くようにしていますが、他に何か必要な場合は、ここにも置きます。MjpegView.class は、ネット上で見つかったクラスです (コードは Stackoverflow にもあります)。少し変更を加えました (主に MjpegInputStream 内)。

別のスレッドの描画コード:

while (mRun && mIn != null)
{
    if (surfaceDone)
    {
        try
        {

            try
            {
                bm = mIn.readMjpegFrame();
            }
            catch (IOException e1)
            {
                bm = null;
            }

            if (bm == null) continue;

            c = mSurfaceHolder.lockCanvas();

            synchronized (mSurfaceHolder)
            {

                destRect = destRect(bm.getWidth(), bm.getHeight());

                c.drawColor(Color.BLACK);

                c.drawBitmap(bm, null, destRect, p);

                if (requestscreenshot)
                {
                    requestscreenshot = false;

                    try
                    {
                        FileOutputStream out = new FileOutputStream(requestfile);
                        bm.compress(Bitmap.CompressFormat.PNG, 90, out);
                    }
                    catch (Exception ex)
                    {
                        // ignore
                    }

                    requestfile = "";
                }

                if (showFps)
                {

                    p.setXfermode(mode);

                    if (ovl != null)
                    {

                        // false indentation to fix forum layout

                        height = ((ovlPos & 1) == 1) ? destRect.top : destRect.bottom - ovl.getHeight();

                        width = ((ovlPos & 8) == 8) ? destRect.left : destRect.right - ovl.getWidth();

                        c.drawBitmap(ovl, width, height, null);

                    }

                    p.setXfermode(null);

                    frameCounter++;

                    if ((System.currentTimeMillis() - start) >= 1000)
                    {

                        fps = String.valueOf(frameCounter) + "fps";

                        frameCounter = 0;

                        start = System.currentTimeMillis();

                        ovl = makeFpsOverlay(overlayPaint);
                    }

                }

            }

        }
        finally
        {
            if (c != null) mSurfaceHolder.unlockCanvasAndPost(c);
        }

    }
    else
    {
        try
        {
            Thread.sleep(100);
        }
        catch (Exception ex)
        {
        }
    }
}

次に、サーフェスビューでコールバック:

public void surfaceChanged(SurfaceHolder holder, int f, int w, int h)
{
    Log.d(Constants.TAG, "MjpegView.surfaceChanged");
    if (thread != null)
    {
        thread.mSurfaceHolder = holder;
        thread.setSurfaceSize(w, h);
    }
}

public void surfaceDestroyed(SurfaceHolder holder)
{
    Log.d(Constants.TAG, "MjpegView.surfaceDestroyed");

    surfaceDone = false;

    stopPlayback();
}

public void surfaceCreated(SurfaceHolder holder)
{
    Log.d(Constants.TAG, "MjpegView surfaceCreated");
    surfaceDone = true;
}

public void startPlayback()
{
    if (thread == null)
    {
        thread = new MjpegViewThread(getHolder(), context);
        if (URL != null)
        {
            mRun = true;
            thread.start();
        }
    }
    else
    {
        thread.mSurfaceHolder = getHolder();
    }
}

public void stopPlayback()
{

    mRun = false;

    boolean retry = true;

    while (retry && thread != null)
    {

        try
        {

            thread.join();

            retry = false;

        }
        catch (InterruptedException e)
        {
        }

    }

    thread = null;
}

アクティビティでは、onCreate でいくつかの初期化を使用します。

mv.setSource(device.getCameraURL());
mv.setMessageHandler(messageHandler);

mv.setDisplayMode(MjpegView.SIZE_BEST_FIT);

mv.showFps(false);

(mv は MjpegView です)

そして onResume で MjpegView の startPlayback メソッドを呼び出します

それだけだと思います。

どんな助けにも感謝します!ありがとう!

アップデート:

回避策が見つかるかもしれません:

PowerManager pm = (PowerManager) MjpegtestActivity.this.getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE | PowerManager.ACQUIRE_CAUSES_WAKEUP, Constants.TAG);
wl.acquire(); 

Intent intent = new Intent(MjpegtestActivity.this, Camera.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("PLAYSOUND", false);
intent.putExtra("DEVICEID", "a73d3ffd-bebb-aae4-f133-39a81eba6e");
MjpegtestActivity.this.startActivity(intent);

wl.release();
wl = null;

ウェイクロックを取得してからアクティビティを開始すると、SurfaceView に IP カメラの画像が正しく表示されます。

しかし、理由はわかりません:)

4

1 に答える 1

0

OK、これは解決策になる可能性があります。バックグラウンド サービスからも機能します。

// start the activity in new thread to allow sleep times
new Thread(new Runnable()
{
    @Override
    public void run()
    {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE | PowerManager.ACQUIRE_CAUSES_WAKEUP, Constants.TAG);
        wl.acquire(); 

        try
        {
            // give 500ms for device to wake up
            Thread.sleep(500);
        }
        catch (InterruptedException e)
        {
        }


        // start the activity
        Intent intent = new Intent(context, EntryPhoneControl.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra("PLAYSOUND", true);
        intent.putExtra("DEVICEID", dev.getId());
        context.startActivity(intent);

        // wait 5 sec to start the activity before releasing wakelock
        // within 5 sec the activity should be displayed already
        try
        {
            Thread.sleep(5000);
        }
        catch (InterruptedException e)
        {
        }

        wl.release();
        wl = null;
    }
}).start();

したがって、これは非常に安定したソリューションだと思います。

于 2012-07-20T06:14:41.217 に答える