2012-07-19 99 views
0

我有一個表面視圖來顯示來自IP攝像機的MJPEG流。除了一種情況,它工作得很好。SurfaceView內容與FLAG_TURN_SCREEN_ON活動不可見

在我的活動,顯示了surfaceview我有以下標誌:

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

如果我正常啓動活動(從應用程序),它顯示的攝像機圖像。但是,如果我在手機處於睡眠狀態時從後臺服務開始活動,則會啓動活動,手機已解鎖,屏幕已打開,一切都看起來不錯,除非Surfaceview上沒有繪製任何內容。 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) 
     { 
     } 
    } 
} 

然後在surfaceview回調:

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攝像機圖像。

但我不知道爲什麼:)

回答

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

所以我覺得這是一個非常穩定的解決方案。