[英]Stop CPU from sleeping when screen is off
我有一個將Webview作為服務運行的應用程序,因此可以在屏幕鎖定時繼續播放音頻。 該應用程序非常適合音頻流,例如播客。 但是我也希望它能與Flash視頻一起使用。 我能夠將Flash視頻流加載到Webview中,並使其流暢穩定地播放,但是一旦屏幕關閉或被鎖定,音頻就會變得斷斷續續。 3g和WiFi上的行為相同。 我試圖將這篇文章的建議與喚醒鎖一起使用:
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();
但是,這沒有效果。 我不確定將其確切放置在代碼中的哪個位置,但已將其放置在服務的oncreate中,這無效,並且我將其放置在主要活動的oncreate中,結果相同。
但是在帖子的后面,詢問該問題的人說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();
}
}
根據您的描述,聽起來您太早釋放了WakeLock。 如果您只是將該代碼塊放入服務的onCreate中,那么在運行流式代碼時,實際上並沒有得到WakeLock。 在后台工作期間,您必須獲取鎖。
我用於這樣的服務的模式是:
問題可能與WebView的工作方式有關。 也就是說,由於這不是生產代碼,因此您可以嘗試通過刪除發行版來“釋放”喚醒鎖,以查看是否有幫助。 只需在活動開始時創建並獲取鎖,而不必理會服務。
該服務並沒有真正給您帶來太多好處。 當前代碼的結構方式仍然會遇到問題。 即使您有服務,在后台仍然可以刪除您的活動,只是擁有服務並不能阻止它。 此外,由於WebView是視圖,因此它確實需要活動和視圖層次結構。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.