簡體   English   中英

適用於GPS服務的Android Wakelock

[英]Android Wakelock for GPS Service

我正在開發一個每十分鍾獲取一次GPS位置並將其發送到服務器的應用程序,為此,我使用了Timer,requestLocationUpdates和Android異步Http客戶端庫。 每十分鍾最多需要保存12個小時的職位。

為了保持應用程序的生命力,我在Service內部的onCreate中使用了喚醒鎖

    PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
    wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "whatever");
    wl.acquire();

和onDestroy()

    wl.release();

該服務通過MainActivity中的按鈕啟動和停止。 我的主要問題是,如果用戶按下主屏幕按鈕並將應用程序移回原位,我只會獲得兩次位置(在開始時和10分鍾后,在20分鍾后沒有位置更新)。 只要鎖定應用程序上的屏幕似乎還可以,但是鎖定主屏幕后幾分鍾,該過程似乎被終止。

這是我的GPS服務的完整代碼:

public class UpdatePositionService extends Service {

    private PowerManager.WakeLock wl;
    private Handler mHandler = new Handler(Looper.getMainLooper());
    private AsyncHttpClient client = new AsyncHttpClient();
    private SharedPreferences preferences;
    public static final String USER_PREFERENCES = "userPreferences";
    private Timer updatingTimer;
    private TimerTask task = new TimerTask() {
        @Override
        public void run() {
            mHandler.post(new Runnable() {
                public void run() {
                    preferences = getSharedPreferences(USER_PREFERENCES, MODE_PRIVATE);
                    final String uid = preferences.getString("userid", "");
                    final String pause = readFromFile("pause.txt");
                    final String userState = readFromFile("user.txt");
                    final String workid = readFromFile("work.txt");
                    final String consid = readFromFile("cons.txt");
                    if (!pause.equals("1") && !userState.equals("0")) {
                        Log.e("mmd:test:123", "dochodzi  " + userState);
                        final LocationManager[] lm = {(LocationManager)
                            getSystemService(Context.LOCATION_SERVICE)};
                        Criteria criteria = new Criteria();
                        criteria.setAccuracy(Criteria.ACCURACY_FINE);
                        criteria.setPowerRequirement(Criteria.POWER_HIGH);
                        _if();
                        lm[0].requestLocationUpdates(LocationManager
                            .GPS_PROVIDER, 6000, 10, new LocationListener() {
                            @Override
                            public void onLocationChanged(Location location) {
                                String updatedPause = readFromFile("pause.txt");

                                _if();
                                lm[0].removeUpdates(this);
                                lm[0] = null;
                                if (!updatedPause.equals("1")) {
                                    RequestParams params = new RequestParams();
                                    params.put("uid", uid);
                                    params.put("lat", location.getLatitude());
                                    params.put("long", location.getLongitude());
                                    params.put("workid", workid);
                                    params.put("type", userState);
                                    params.put("cons", consid);
                                    String url = "http://example.com/api/event/add";
                                    client.post(url, params,
                                      new AsyncHttpResponseHandler() {
                                        @Override
                                        public void onSuccess(int statusCode,
                                        Header[] headers, byte[] responseBody) {
                                            String response = new String(
                                                responseBody);
                                            if (!response.equals("ERROR")) {
                                            } else {
                                            }
                                        }

                                        @Override
                                        public void onFailure(
                                            int statusCode, Header[] headers,
                                            byte[] responseBody,
                                            Throwable error) {}
                                    });
                                }
                            }

                            @Override
                            public void onStatusChanged(String provider, int
                                status, Bundle extras) {}

                            @Override
                            public void onProviderEnabled(String provider) {}

                            @Override
                            public void onProviderDisabled(String provider) {}
                        });
                    }
                }
            });
        }
    };

    private void _if() {
        if (ActivityCompat.checkSelfPermission(UpdatePositionService.this,
            Manifest.permission.ACCESS_FINE_LOCATION) !=
            PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(UpdatePositionService.this,
                Manifest.permission.ACCESS_COARSE_LOCATION) !=
                PackageManager.PERMISSION_GRANTED) {}
    }

    @Override
    public void onCreate() {
        super.onCreate();
        updatingTimer = new Timer();
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager
            .ACQUIRE_CAUSES_WAKEUP, "whatever");
        wl.acquire();
    }

    @Override
    public void onDestroy() {
        updatingTimer.cancel();
        mHandler.removeCallbacksAndMessages(null);
        wl.release();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int time = 1000 * 60 * 10; // 10 mins
        updatingTimer.scheduleAtFixedRate(task, 3000, time);
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    private String readFromFile(String filename) {
        String ret = "";
        try {
            InputStream inputStream = openFileInput(filename);
            if (inputStream != null) {
                InputStreamReader inputStreamReader = new InputStreamReader
                    (inputStream);
                BufferedReader bufferedReader = new BufferedReader
                    (inputStreamReader);
                String receiveString = "";
                StringBuilder stringBuilder = new StringBuilder();
                while ((receiveString = bufferedReader.readLine()) != null) {
                    stringBuilder.append(receiveString);
                }
                inputStream.close();
                ret = stringBuilder.toString();
            }
        } catch (FileNotFoundException e) {
            Log.e("login activity", "File not found: " + e.toString());
        } catch (IOException e) {
            Log.e("login activity", "Can not read file: " + e.toString());
        }
        return ret;
    }
}

擴展@CommonsWare 評論 為此設置服務不是一個好主意-而且也無法正常工作。 Android殺死了它,聚會結束了。 要執行任何定期任務,您必須使用警報管理器設置警報。 為此,請注冊一個警報-在某些設置為在啟動時接收的接收器中更好-在重新啟動所有警報時會再見:

private void setupAlarm(Context context, boolean setup) {
    am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    pi = PendingIntent.getBroadcast(context, NOT_USED, yourIntent,
                                    PendingIntent.FLAG_UPDATE_CURRENT);
    if (setup) { // setup the alarms
        try {
            am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime() + SOME_DELAY, THE_INTERVAL_BETWEEN_ALARMS, pi);
        } catch (InstantiationException e) {
            // should not happen
            throw new RuntimeException(UNABLE_TO_SET_ALARMS, e);
        } catch (IllegalAccessException e) {
            // should not happen
            throw new RuntimeException(UNABLE_TO_SET_ALARMS, e);
        }
    } else { // teardown the alarms
        // send message to the monitors that the party is over
        Intent i = new Intent(YOUR_ABORTING_ACTION, Uri.EMPTY, context, YOUR_SERVICE_CLASS);
        WakefulIntentService.sendWakefulWork(context, i);
        // cancel the alarms
        am.cancel(pi);
    }
    d("alarms " + (setup ? "enabled" : "disabled"));
}

然后在注冊為從AlarmManager接收廣播的接收器的onReceive中(它們為您保持永不失敗的喚醒鎖 )委托給WakefulIntentService

@Override
final public void onReceive(Context context, Intent intent) {
    final String action = intent.getAction();
    if (ac_setup_alarm.equals(action) || ac_cancel_alarm.equals(action)) {
        monitoringIntent = new Intent(context, this.getClass());
        monitoringIntent.setAction(ac_monitor.toString());
        final boolean enable = ac_setup_alarm.equals(action);
        setupAlarm(context, enable);
    } else if (ac_monitor.equals(action)) {
        // monitoring - got broadcast from ALARM
        WakefulIntentService.sendWakefulWork(context, YOUR_SERVICE_CLASS);
    } else if (ac_reschedule_alarm.equals(action)) {
        monitoringIntent = new Intent(context, this.getClass());
        monitoringIntent.setAction(ac_monitor.toString());
        rescheduleAlarm(context);
    } else {
        w("Received bogus intent : " + intent);
    }
}

另外,要使用喚醒意圖服務,可以使用WakefulBroadcastReceiver-但必須編寫服務。 (我的)代碼在這里 -有效!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM