私のアプリは、GPS を使用するトラッカー アプリです。15 分ごとに、ユーザーの現在地を検出します。このために、私は を使用していましたAlarmManager
。ごとに実行されるようにスケジュールされているバックグラウンド サービスを介して、現在の場所を取得してい15 minutes
ます。このサービスは、アラーム時に放送受信機によって開始されます。しかし、問題は時間前にアラームが起動することです。つまり、サービスが開始されて作業が終了すると、サービスは 15 分後に呼び出されるはずでした。でも、2~3分間隔で呼び出されています。
活動コード
AlarmManager AlmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Sender = PendingIntent.getBroadcast(GpsTrackActivity.this, 0,
AlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlmMgr.setRepeating(AlarmManager.RTC_WAKEUP, 0, 15 * 60 * 1000,
Sender);
ブロードキャストレシーバー
public class StartServiceReceiver extends BroadcastReceiver
{
private static final String TAG = "StartServiceReceiver";
@Override
public void onReceive(Context context, Intent intent)
{
Intent serviceIntent = new Intent(context, MyLocationService.class);
context.startService(serviceIntent);
Log.v(TAG, "onReceive called");
}
}
サービスクラス
public class MyLocationService extends Service implements
OnLocationReceivedListener {
private LocationManager manager;
private Location location = null;
PowerManager powerManager;
private WakeLock wakeLock;
private String city, time, udid;
private String country;
GPSLocationListener mGPSLocationListener;
NetworkLocationListener mNetworkLocationListener;
private static final int MAX_ATTEMPTS = 250;
private static String TAG = "MyLocationService";
LocTimerTask mTimerTask;
int mSattelites;
Timer myLocTimer;
int i = 0;
boolean isGPS;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand called");
getCurrentLocation();
time = getCurrentTime();
udid = getDeviceId();
return 1;
}
@Override
public void onCreate() {
Log.v(TAG, "onCreate called");
powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"mywakelock");
mGPSLocationListener = new GPSLocationListener();
mNetworkLocationListener = new NetworkLocationListener();
wakeLock.acquire();
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
public String getCurrentTime() {
String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
Locale.getDefault()).format(new Date());
return currentTime;
}
public String getDeviceId() {
TelephonyManager tm = (TelephonyManager) MyLocationService.this
.getSystemService(Context.TELEPHONY_SERVICE);
return tm.getDeviceId();
}
public void getCurrentLocation() {
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
manager.addGpsStatusListener(mGPSStatusListener);
mTimerTask = new LocTimerTask(LocationManager.GPS_PROVIDER);
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.v(TAG, "GPS ENABLED");
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000L,
50.0f, mGPSLocationListener);
} else {
turnGPSOn();
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000L,
50.0f, mGPSLocationListener);
}
myLocTimer = new Timer("LocationRunner", true);
myLocTimer.schedule(mTimerTask, 0, 1000);
}
public String getLong(Location loc) {
String longi = null;
if (loc != null) {
longi = Double.toString(loc.getLongitude());
}
return longi;
}
public String getLat(Location loc) {
String lat = null;
if (loc != null) {
lat = Double.toString(loc.getLatitude());
}
return lat;
}
public class GPSLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location argLocation) {
location = argLocation;
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
class LocTimerTask extends TimerTask {
String provider;
public LocTimerTask(String provider) {
this.provider = provider;
}
final Handler mHandler = new Handler(Looper.getMainLooper());
Runnable r = new Runnable() {
@Override
public void run() {
i++;
Log.v(TAG, "Timer Task run " + i);
location = manager.getLastKnownLocation(provider);
if (location != null) {
Log.v(TAG, "in timer task run in if location not null");
isGPS = true;
onLocationReceived(location);
myLocTimer.cancel();
myLocTimer.purge();
mTimerTask.cancel();
return;
} else {
Log.v(TAG, "in timer task run in else location null");
isGPS = false;
if (location == null && i == MAX_ATTEMPTS) {
Log.v(TAG, "if 1 max attempts done");
turnGPSOff();
location = manager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
Log.v(TAG,
"if 1 max attempts done Location from network not null");
Log.v(TAG,
"if 1 max attempts done Location from network not null coordinates not null");
onLocationReceived(location);
myLocTimer.cancel();
myLocTimer.purge();
mTimerTask.cancel();
i = 0;
return;
} else {
i = 0;
return;
}
} else {
return;
}
}
}
};
public void run() {
mHandler.post(r);
}
}
private GpsStatus.Listener mGPSStatusListener = new GpsStatus.Listener() {
@Override
public synchronized void onGpsStatusChanged(int event) {
switch (event) {
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
Log.v(TAG, "GPS SAtellitestatus");
GpsStatus status = manager.getGpsStatus(null);
mSattelites = 0;
Iterable<GpsSatellite> list = status.getSatellites();
for (GpsSatellite satellite : list) {
if (satellite.usedInFix()) {
mSattelites++;
}
}
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
Toast.makeText(getApplicationContext(), "Got First Fix",
Toast.LENGTH_LONG).show();
break;
case GpsStatus.GPS_EVENT_STARTED:
Toast.makeText(getApplicationContext(), "GPS Event Started",
Toast.LENGTH_LONG).show();
break;
case GpsStatus.GPS_EVENT_STOPPED:
Toast.makeText(getApplicationContext(), "GPS Event Stopped",
Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
};
public void onDestroy() {
super.onDestroy();
if (myLocTimer != null) {
myLocTimer.cancel();
myLocTimer.purge();
}
if (mTimerTask != null) {
if (mTimerTask.r != null) {
mTimerTask.mHandler.removeCallbacks(mTimerTask.r);
}
}
if (manager != null) {
if (mGPSLocationListener != null) {
manager.removeUpdates(mGPSLocationListener);
}
if (mNetworkLocationListener != null) {
manager.removeUpdates(mNetworkLocationListener);
}
if (mGPSStatusListener != null) {
manager.removeGpsStatusListener(mGPSStatusListener);
}
}
Toast.makeText(getApplicationContext(), "Service onDestroy called",
Toast.LENGTH_LONG).show();
}
@Override
public void onLocationReceived(Location mLoc) {
String lat = getLat(mLoc);
String lon = getLong(mLoc);
if (NetworkConnection.isOnline(getApplicationContext())) {
new SendDataAsynctask(lat, lon, "", time, udid, city, country,
wakeLock).execute();
Log.v(TAG, "net available");
} else {
Toast.makeText(getApplicationContext(), "Network unavailable",
Toast.LENGTH_LONG).show();
Log.v(TAG, "net unavailable");
}
}
}
AlarmManager
Timer または TimerTask の影響を受けるのではないかと疑っています。GPSが最初の修正を見つけるのに時間がかかるため、サービス内でタイマーを使用していたため、これを求めています。