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 カメラの画像が正しく表示されます。
しかし、理由はわかりません:)