如何让androidphone的CPU一直保持清醒?
How to Keep the CPU of android phone always awake?
我已经坚持了好几天了。我需要每分钟执行一个函数。此功能正在从应用程序向服务器发出 POST 调用,并且每分钟传输一次用户的位置。位置坐标会传输几个小时,但是,几个小时后,位置坐标向服务器的传输会自行停止。我正在使用 WakefulBroadcastReceiver 和 IntentService 来确保 CPU 保持清醒。我还使用 Alarm 来确保该功能每分钟执行一次。
这是我的 WakefulBroadcastReceiver 的样子:
public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// This is the Intent to deliver to our service.
Intent service = new Intent(context, SimpleWakefulService.class);
// Start the service, keeping the device awake while it is launching.
Log.i("SimpleWakefulReceiver", "Starting service @ " +
SystemClock.elapsedRealtime());
startWakefulService(context, service);
}
}
这是我的 IntentService 的样子:
public class SimpleWakefulService extends IntentService {
public MainActivity obj;
public Alarm alarm;
public SimpleWakefulService() {
super("SimpleWakefulService");
}
@Override
protected void onHandleIntent(Intent intent) {
boolean flag = true;
while(flag){
Log.i("SimpleWakefulService", "Running service ");
alarm = new Alarm();
alarm.SetAlarm(SimpleWakefulService.this);
Log.i("Called alarm.SetAlarm","Called alarm.SetAlarm");
}
SimpleWakefulReceiver.completeWakefulIntent(intent);
// wl.release();
}
}
这就是我的闹钟 class 的样子:
public class Alarm extends BroadcastReceiver
{
public MainActivity obj;
@Override
public void onReceive(Context context, Intent intent)
{
PowerManager pm = (PowerManager)
context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl =
pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
obj = new MMMainActivity();
obj.UpdateData();
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show();
wl.release();
}
public void SetAlarm(Context context)
{
Log.i("Inside SetAlarm","Inside SetAlarm");
AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 1, pi); // Millisec * Second * Minute
}
public void CancelAlarm(Context context)
{
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
每分钟需要执行的函数(名为 UpdataData())如下所示:
public void UpdateData() {
final boolean flag = true;
Log.i("Inside Update Data", "Inside Update Data");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<1; i++){
try {
// Your code goes here
if (locationclient != null
&& locationclient.isConnected()) {
loc = locationclient.getLastLocation();
lat = loc.getLatitude();
lng = loc.getLongitude();
}
try { // Updating the latest location in the UI, just
// for convinience.
HttpClient httpClient = new DefaultHttpClient();
// Creating HTTP Post
HttpPost httpPost = new HttpPost(
"http://www.mywebsite.com/update");
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(
3);
// Building post parameters//
// key and value pair
Log.i("token", "token" + token);
Log.i("Latitude for III POST Call",
"Latitude for III POST Call" + lat);
Log.i("Longitude for III POST Call",
"Longitude for III POST Call" + lng);
nameValuePair.add(new BasicNameValuePair("token",
token));
nameValuePair.add(new BasicNameValuePair("lat",
Double.toString(lat)));
nameValuePair.add(new BasicNameValuePair("lng",
Double.toString(lng)));
Log.i("Made UpdateData Post Call",
"Made UpdateData Post Call");
// Url Encoding the POST parameters
try {
httpPost.setEntity(new UrlEncodedFormEntity(
nameValuePair));
} catch (UnsupportedEncodingException e) {
// writing error to Log
e.printStackTrace();
}
// Making HTTP Request
try {
HttpResponse response = httpClient
.execute(httpPost);
// writing response to log
Log.d("Http Response:", response.toString());
// Your code goes here
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}// loop closed
}
});
thread.start();
}// UpdateData closed
为什么即使使用了所有这些,UpdateData() 也不能无限执行,每 60 秒执行一次?在这方面的任何帮助将不胜感激。另请注意,UpdateData() 在几个小时内每 60 秒执行一次,但一段时间后,它的执行会自行停止,因此位置坐标从应用程序传输到服务器。
编辑:我已经编辑了 SimpleWakefulService 并根据其中一个答案的建议添加了所需的更改。事情在几个小时内运行良好,但是,post 几个小时后,该服务被自动终止。我相信服务不会被杀死。有人可以解释一下吗?
SimpleWakefulService:
public class SimpleWakefulService extends IntentService implements
OnClickListener,ConnectionCallbacks, OnConnectionFailedListener,
LocationListener,GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
public static Location loc;
public static LocationClient locationclient;
public static double lat = 10, lng = 10;
public static String token;
public Alarm alarm;
public SimpleWakefulService() {
super("SimpleWakefulService");
}
@Override
protected void onHandleIntent(Intent intent) {
//Getting the value of token from another Class
token = ConfirmToken.uvalue;
Log.i("WakefulServiceutoken", "WakefulServicutoken" + token);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
final boolean flag = true;
while (flag) {
try {
// Your code goes here
if (locationclient != null
&& locationclient.isConnected()) {
loc = locationclient.getLastLocation();
lat = loc.getLatitude();
lng = loc.getLongitude();
}
try { // Updating the latest location in the UI, just
// for convinience.
HttpClient httpClient = new DefaultHttpClient();
// Creating HTTP Post
HttpPost httpPost = new HttpPost(
"http://www.mywebsite.com/update");
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(
3);
// Building post parameters//
// key and value pair
Log.i("token", "token" + token);
Log.i("Latitude for III POST Call",
"Latitude for III POST Call" + lat);
Log.i("Longitude for III POST Call",
"Longitude for III POST Call" + lng);
nameValuePair.add(new BasicNameValuePair("token",
token));
nameValuePair.add(new BasicNameValuePair("lat",
Double.toString(lat)));
nameValuePair.add(new BasicNameValuePair("lng",
Double.toString(lng)));
// Url Encoding the POST parameters
try {
httpPost.setEntity(new UrlEncodedFormEntity(
nameValuePair));
} catch (UnsupportedEncodingException e) {
// writing error to Log
e.printStackTrace();
}
// Making HTTP Request
try {
HttpResponse response = httpClient
.execute(httpPost);
// writing response to log
Log.d("Http Response:", response.toString());
// Your code goes here
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(10000);
} catch (Exception e) {
}
}// While closed
//SimpleWakefulReceiver.completeWakefulIntent(intent);
//wl.release();
}
@Override
public void onDisconnected() {
// TODO Auto-generated method stub
}
@Override
public void onLocationChanged(Location arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
@Override
public void onConnectionFailed(ConnectionResult result) {
// TODO Auto-generated method stub
}
@Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
}
@Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
首先,你的 SimpleWakefulService 看起来不是很清醒,它应该有 WakeLock 但它没有。此类服务的示例请看这里:
接下来是更新功能。它在获取 PARTIAL_WAKE_LOCK 的上下文中调用,但其中的线程是异步执行的,这意味着在释放唤醒锁之后也是如此。这就是问题所在。
解决方案是将您的线程代码从更新函数(不需要线程)移动到 WakefulIntentService,如上 link。
我已经坚持了好几天了。我需要每分钟执行一个函数。此功能正在从应用程序向服务器发出 POST 调用,并且每分钟传输一次用户的位置。位置坐标会传输几个小时,但是,几个小时后,位置坐标向服务器的传输会自行停止。我正在使用 WakefulBroadcastReceiver 和 IntentService 来确保 CPU 保持清醒。我还使用 Alarm 来确保该功能每分钟执行一次。
这是我的 WakefulBroadcastReceiver 的样子:
public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// This is the Intent to deliver to our service.
Intent service = new Intent(context, SimpleWakefulService.class);
// Start the service, keeping the device awake while it is launching.
Log.i("SimpleWakefulReceiver", "Starting service @ " +
SystemClock.elapsedRealtime());
startWakefulService(context, service);
}
}
这是我的 IntentService 的样子:
public class SimpleWakefulService extends IntentService {
public MainActivity obj;
public Alarm alarm;
public SimpleWakefulService() {
super("SimpleWakefulService");
}
@Override
protected void onHandleIntent(Intent intent) {
boolean flag = true;
while(flag){
Log.i("SimpleWakefulService", "Running service ");
alarm = new Alarm();
alarm.SetAlarm(SimpleWakefulService.this);
Log.i("Called alarm.SetAlarm","Called alarm.SetAlarm");
}
SimpleWakefulReceiver.completeWakefulIntent(intent);
// wl.release();
}
}
这就是我的闹钟 class 的样子:
public class Alarm extends BroadcastReceiver
{
public MainActivity obj;
@Override
public void onReceive(Context context, Intent intent)
{
PowerManager pm = (PowerManager)
context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl =
pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
obj = new MMMainActivity();
obj.UpdateData();
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show();
wl.release();
}
public void SetAlarm(Context context)
{
Log.i("Inside SetAlarm","Inside SetAlarm");
AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 1, pi); // Millisec * Second * Minute
}
public void CancelAlarm(Context context)
{
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
每分钟需要执行的函数(名为 UpdataData())如下所示:
public void UpdateData() {
final boolean flag = true;
Log.i("Inside Update Data", "Inside Update Data");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<1; i++){
try {
// Your code goes here
if (locationclient != null
&& locationclient.isConnected()) {
loc = locationclient.getLastLocation();
lat = loc.getLatitude();
lng = loc.getLongitude();
}
try { // Updating the latest location in the UI, just
// for convinience.
HttpClient httpClient = new DefaultHttpClient();
// Creating HTTP Post
HttpPost httpPost = new HttpPost(
"http://www.mywebsite.com/update");
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(
3);
// Building post parameters//
// key and value pair
Log.i("token", "token" + token);
Log.i("Latitude for III POST Call",
"Latitude for III POST Call" + lat);
Log.i("Longitude for III POST Call",
"Longitude for III POST Call" + lng);
nameValuePair.add(new BasicNameValuePair("token",
token));
nameValuePair.add(new BasicNameValuePair("lat",
Double.toString(lat)));
nameValuePair.add(new BasicNameValuePair("lng",
Double.toString(lng)));
Log.i("Made UpdateData Post Call",
"Made UpdateData Post Call");
// Url Encoding the POST parameters
try {
httpPost.setEntity(new UrlEncodedFormEntity(
nameValuePair));
} catch (UnsupportedEncodingException e) {
// writing error to Log
e.printStackTrace();
}
// Making HTTP Request
try {
HttpResponse response = httpClient
.execute(httpPost);
// writing response to log
Log.d("Http Response:", response.toString());
// Your code goes here
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}// loop closed
}
});
thread.start();
}// UpdateData closed
为什么即使使用了所有这些,UpdateData() 也不能无限执行,每 60 秒执行一次?在这方面的任何帮助将不胜感激。另请注意,UpdateData() 在几个小时内每 60 秒执行一次,但一段时间后,它的执行会自行停止,因此位置坐标从应用程序传输到服务器。
编辑:我已经编辑了 SimpleWakefulService 并根据其中一个答案的建议添加了所需的更改。事情在几个小时内运行良好,但是,post 几个小时后,该服务被自动终止。我相信服务不会被杀死。有人可以解释一下吗? SimpleWakefulService:
public class SimpleWakefulService extends IntentService implements
OnClickListener,ConnectionCallbacks, OnConnectionFailedListener,
LocationListener,GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
public static Location loc;
public static LocationClient locationclient;
public static double lat = 10, lng = 10;
public static String token;
public Alarm alarm;
public SimpleWakefulService() {
super("SimpleWakefulService");
}
@Override
protected void onHandleIntent(Intent intent) {
//Getting the value of token from another Class
token = ConfirmToken.uvalue;
Log.i("WakefulServiceutoken", "WakefulServicutoken" + token);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
final boolean flag = true;
while (flag) {
try {
// Your code goes here
if (locationclient != null
&& locationclient.isConnected()) {
loc = locationclient.getLastLocation();
lat = loc.getLatitude();
lng = loc.getLongitude();
}
try { // Updating the latest location in the UI, just
// for convinience.
HttpClient httpClient = new DefaultHttpClient();
// Creating HTTP Post
HttpPost httpPost = new HttpPost(
"http://www.mywebsite.com/update");
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(
3);
// Building post parameters//
// key and value pair
Log.i("token", "token" + token);
Log.i("Latitude for III POST Call",
"Latitude for III POST Call" + lat);
Log.i("Longitude for III POST Call",
"Longitude for III POST Call" + lng);
nameValuePair.add(new BasicNameValuePair("token",
token));
nameValuePair.add(new BasicNameValuePair("lat",
Double.toString(lat)));
nameValuePair.add(new BasicNameValuePair("lng",
Double.toString(lng)));
// Url Encoding the POST parameters
try {
httpPost.setEntity(new UrlEncodedFormEntity(
nameValuePair));
} catch (UnsupportedEncodingException e) {
// writing error to Log
e.printStackTrace();
}
// Making HTTP Request
try {
HttpResponse response = httpClient
.execute(httpPost);
// writing response to log
Log.d("Http Response:", response.toString());
// Your code goes here
} catch (IOException e) {
// writing exception to log
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(10000);
} catch (Exception e) {
}
}// While closed
//SimpleWakefulReceiver.completeWakefulIntent(intent);
//wl.release();
}
@Override
public void onDisconnected() {
// TODO Auto-generated method stub
}
@Override
public void onLocationChanged(Location arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
@Override
public void onConnectionFailed(ConnectionResult result) {
// TODO Auto-generated method stub
}
@Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
}
@Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
首先,你的 SimpleWakefulService 看起来不是很清醒,它应该有 WakeLock 但它没有。此类服务的示例请看这里:
接下来是更新功能。它在获取 PARTIAL_WAKE_LOCK 的上下文中调用,但其中的线程是异步执行的,这意味着在释放唤醒锁之后也是如此。这就是问题所在。
解决方案是将您的线程代码从更新函数(不需要线程)移动到 WakefulIntentService,如上 link。