2012-03-30 67 views
0

我有一個運行webview作爲服務的應用程序,因此音頻可以在屏幕鎖定時連續播放。該應用程序與音頻流,如播客效果很好。但我也希望它能夠與Flash視頻一起工作。我能夠在網頁視圖中加載Flash視頻流,並使其播放流暢穩定,但一旦屏幕熄滅或鎖定,音頻就會變得波濤洶涌。 3g和WiFi的行爲是相同的。我試圖用使用喚醒鎖與this帖子建議:當屏幕關閉時停止CPU睡眠

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Tag"); 
wl.acquire(); 
//do what you need to do 
wl.release(); 

但是這沒有任何影響。我不確定在我的代碼中完全放置它的位置,但是我已將它放置在服務的創建中,這沒有任何效果,並且將它放在我的主要活動的創建者中,獲得了相同的結果。

但後來在帖子中提問的人說WIFI_MODE_FULL_HIGH_PERF能夠解決這個問題。但正如我所說,我在3g上測試了它,當屏幕關閉時音頻結結實實。

任何想法,我可以阻止這種行爲?

另外我知道這是一個CPU密集型和電池豬應用程序,但我只是開發它的個人使用。

這是我服務全碼:

public class MyService extends Service { 
    private NotificationManager nm; 
    private static boolean isRunning = false; 

    ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current registered clients. 
    int mValue = 0; // Holds last value set by a client. 
    static final int MSG_REGISTER_CLIENT = 1; 
    static final int MSG_UNREGISTER_CLIENT = 2; 
    static final int MSG_SET_INT_VALUE = 3; 
    static final int MSG_SET_STRING_VALUE = 4; 
    PowerManager.WakeLock wl; 


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

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     Log.i("MyService", "Service Started."); 
     showNotification(); 
     isRunning = true; 
     PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
     wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Tag"); 
    } 
    private void showNotification() { 
     nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 
     // In this sample, we'll use the same text for the ticker and the expanded notification 
     CharSequence text = getText(R.string.service_started); 
     // Set the icon, scrolling text and timestamp 
     Notification notification = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis()); 
     notification.flags = Notification.FLAG_ONGOING_EVENT; 
     // The PendingIntent to launch our activity if the user selects this notification 
     PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0); 
     // Set the info for the views that show in the notification panel. 
     notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent); 
     // Send the notification. 
     // We use a layout id because it is a unique number. We use it later to cancel. 
     nm.notify(R.string.service_started, notification); 
    } 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     Log.i("MyService", "Received start id " + startId + ": " + intent); 
     return START_STICKY; // run until explicitly stopped. 
    } 

    public static boolean isRunning() 
    { 
     return isRunning; 
    } 


    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     nm.cancelAll(); 
     wl.release(); 
     nm.cancel(R.string.service_started); // Cancel the persistent notification. 
     Log.i("MyService", "Service Stopped."); 
     isRunning = false; 
    } 
} 

我的主要代碼:

public class MainActivity extends Activity { 
    Button btnStart, btnStop, btnBind, btnUnbind, btnUpby1, btnUpby10; 
    Messenger mService = null; 
    boolean mIsBound; 
    WebView mWebView; 

    private ServiceConnection mConnection = new ServiceConnection() { 
     public void onServiceConnected(ComponentName className, IBinder service) { 
      mService = new Messenger(service); 
      try { 
       Message msg = Message.obtain(null, MyService.MSG_REGISTER_CLIENT); 
        mService.send(msg); 
      } catch (RemoteException e) { 
       // In this case the service has crashed before we could even do anything with it 
      } 
     } 

     public void onServiceDisconnected(ComponentName className) { 
      // This is called when the connection with the service has been unexpectedly disconnected - process crashed. 
      mService = null; 
     } 
    }; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     btnStart = (Button)findViewById(R.id.btnStart); 
     btnStop = (Button)findViewById(R.id.btnStop); 
     btnBind = (Button)findViewById(R.id.btnBind); 
     btnUnbind = (Button)findViewById(R.id.btnUnbind); 

     btnStart.setOnClickListener(btnStartListener); 
     btnStop.setOnClickListener(btnStopListener); 
     btnBind.setOnClickListener(btnBindListener); 
     CheckIfServiceIsRunning(); 



     //webview 
     mWebView = (WebView) findViewById(R.id.webview); 
     mWebView.getSettings().setJavaScriptEnabled(true); 

     mWebView.getSettings().setPluginsEnabled(true); 
     mWebView.loadUrl(url); 
     mWebView.setWebViewClient(new HelloWebViewClient()); 


    } 


    private void CheckIfServiceIsRunning() { 
     //If the service is running when the activity starts, we want to automatically bind to it. 
     if (MyService.isRunning()) { 
      doBindService(); 
     } 
    } 

    private OnClickListener btnStartListener = new OnClickListener() { 
     public void onClick(View v){ 
      startService(new Intent(MainActivity.this, MyService.class)); 
     } 
    }; 
    private OnClickListener btnStopListener = new OnClickListener() { 
     public void onClick(View v){ 
      doUnbindService(); 
      stopService(new Intent(MainActivity.this, MyService.class)); 
     } 
    }; 
    private OnClickListener btnBindListener = new OnClickListener() { 
     public void onClick(View v){ 

      doBindService(); 
     } 
    }; 
    private OnClickListener btnUnbindListener = new OnClickListener() { 
     public void onClick(View v){ 

      doUnbindService(); 
     } 
    }; 

    void doBindService() { 
     bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE); 
     mIsBound = true; 
    } 
    void doUnbindService() { 
     if (mIsBound) { 
      // If we have received the service, and hence registered with it, then now is the time to unregister. 
      if (mService != null) { 
       try { 
        Message msg = Message.obtain(null, MyService.MSG_UNREGISTER_CLIENT); 
        mService.send(msg); 
       } catch (RemoteException e) { 
        // There is nothing special we need to do if the service has crashed. 
       } 
      } 
      // Detach our existing connection. 
      unbindService(mConnection); 
      mIsBound = false; 
     } 
    } 

    private class HelloWebViewClient extends WebViewClient { 
     @Override 
     public boolean shouldOverrideUrlLoading(WebView view, String url) { 
      view.loadUrl(url); 
      return true; 
     } 
    } 

    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 
     if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) { 
      mWebView.goBack(); 
      return true; 
     } 
     return super.onKeyDown(keyCode, event); 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     try { 
      doUnbindService(); 
     } catch (Throwable t) { 
      Log.e("MainActivity", "Failed to unbind from the service", t); 
     } 
    } 


    @Override 
     protected void onResume() { 
      super.onResume(); 

    } 
} 

回答

3

從你的描述它聽起來像你過早地釋放激活鎖定。 如果您只是將該代碼塊放入服務的onCreate中,那麼當您的流式代碼運行時,您確實沒有獲得WakeLock。您必須擁有在後臺工作期間獲得的鎖定。

我已經用於服務這樣是模式:

  1. 創建的onCreate的激活鎖定(但不獲取它)
  2. 在的onDestroy如果激活鎖定舉行發佈它。 (主要是爲了安全)
  3. 當開始實際的後臺工作時,無論是在onBind還是onStartCommand,獲取鎖。
  4. 完成後臺工作後,釋放喚醒鎖。

該問題可能與WebView的工作方式有關。這就是說,由於這不是生產代碼,你可以通過刪除發佈來簡單地「泄漏」喚醒鎖,以查看是否有幫助。只需在開始活動時創建並獲取鎖定,而不用擔心服務。

該服務並不真的給你很多。你的代碼目前的結構方式仍然會有問題。即使你有一個服務,你的活動在後臺仍然可以被刪除,只是有一個服務不會阻止這個。此外,因爲WebView是一個View,所以它確實需要一個Activity和View層次結構。

+0

我把它放在onBind()和logcat輸出中:'WakeLock最終仍然保持:標籤',音頻仍然結束。如果我正確地做了wakelock,那麼我應該從logcat期待什麼? – Nick 2012-03-30 23:58:40

+0

這意味着WakeLock是一個局部變量。該示例代碼不是簡單的剪切/粘貼。您需要更改它,以便WakeLock對象是類成員。 – cistearns 2012-03-31 01:35:36

+0

我把我的完整代碼放在上面,盡我所能地理解wake wake,但仍然發生口吃。可以解決這個問題嗎? – Nick 2012-04-01 00:29:32

相關問題