【问题标题】:How to Keep the CPU of android phone always awake?如何让安卓手机的 CPU 始终处于唤醒状态?
【发布时间】:2015-05-19 19:11:31
【问题描述】:

我已经坚持了好几天了。我需要每分钟执行一个函数。此功能正在从应用程序向服务器发出 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();

  }
 }

这就是我的 Alarm 类的样子:

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 并按照答案之一的建议添加了所需的更改。事情在几个小时内运行良好,但是,几个小时后,该服务被自动终止。我相信这些服务并不是要被杀死的。谁能解释一下? 简单唤醒服务:

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

}

}

【问题讨论】:

  • 我相信我会尽快卸载这样的应用程序,因为它会很快耗尽我的电池。
  • 我还能做些什么来每分钟获取用户的位置?

标签: android android-intent broadcastreceiver alarmmanager intentservice


【解决方案1】:

首先,您的 SimpleWakefulService 看起来不是很唤醒,它应该 aqurie WakeLock 但它没有。此类服务的示例请看这里:

https://github.com/commonsguy/cwac-wakeful/blob/master/wakeful/src/com/commonsware/cwac/wakeful/WakefulIntentService.java

接下来,是更新功能。它在获取 PARTIAL_WAKE_LOCK 的上下文中调用,但其中的线程是异步执行的,这也意味着在唤醒锁被释放之后。这就是导致问题的原因。

解决方案是将您的线程代码从更新功能(不需要线程)移动到 WakefulIntentService,如上面的链接。

【讨论】:

  • 非常感谢您的回复 marcinj。我只会执行它。
  • 你会非常好,如果你能看一下编辑(在问题的底部)并进一步指导我。
  • @User11012 android 可能会终止你的服务,你的实现非常耗费资源——你一直保持唤醒锁,一旦不再需要你就应该释放唤醒锁。这就是为什么你应该遵循github.com/commonsguy/cwac-wakeful 指南,这意味着使用AlarmManager 每隔几分钟发出一次广播,然后从这个广播调用WakefulIntentService。
  • 我应该进行哪些更改,以便每 1 分钟发出一次广播(发出 POST 调用)?另外,我是否只需要使用 AlarmReceiver.java 和 WakefulIntentService.java,还是还需要包含您在“demo”文件夹中编写的三个类。此外,需要每分钟执行一次的代码,我应该在哪里添加该代码。最重要的是,请原谅我提出这样的基本问题,我是一名新手开发人员,请尝试向像您这样的好人学习开发。
  • @User11012 对不起,我不太明白 - 你应该遵循 Demo 中的代码,即。时间间隔在 AppListener.java 中设置。
猜你喜欢
  • 1970-01-01
  • 2018-04-25
  • 2014-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
  • 2011-08-12
  • 1970-01-01
相关资源
最近更新 更多