我需要在一定的时间间隔之后将用户的位置发送到Web服务器,目前每两分钟发送一次。除非应用正在运行,否则它工作正常。当应用程序处于后台位置时,停止更新,一次又一次地发送相同的位置。我有点困惑。如果有人建议替代我的方法,那将会很棒。我点击按钮开始发送位置并且不会停止,除非并且直到用户点击按钮停止。以下是我的代码。我想将用户的当前位置发送到Web服务器,无论应用程序是否正在运行。任何帮助表示赞赏。问题是在一定间隔后没有发送位置,问题是位置停止更新如果我杀死应用程序坐标保持不变。如果应用程序在前台运行,那么即使设备轻微倾斜也会使坐标发生变化。我之前使用firebaseJobDispatcher来调用此服务。问题不在于调用服务。问题是位置停止更新并且每次我调用服务时都保持相同,如果我已经杀死了应用程序。
我使用闹钟管理器每2分钟拨打一次此服务。
public class GPSTracker_DUP extends Service implements LocationListener {
private Context mContext=null;
RetrofitAPI retrofitAPI;
// flag for GPS status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
// flag for GPS status
boolean canGetLocation = false;
SaveData objSaveData;
Location location; // location
double latitude; // latitude
double longitude; // longitude
private String provider;
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
// Declaring a Location Manager
protected LocationManager locationManager;
public GPSTracker_DUP(Context context) {
this.mContext = context;
//getLocation();
}
public GPSTracker_DUP(){}
public Location getLocation() {
try {
locationManager = (LocationManager) mContext
.getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return null;
}
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(!isGPSEnabled)
{
showSettingsAlert();
}
else
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000*60*2,0,this);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
Log.e("Provider ", provider + " has been selected."+location.getLatitude()+"==="+location.getLongitude());
saveLocation(location.getLatitude(),location.getLongitude());
//onLocationChanged(location);
}
}
// getting network status
// isNetworkEnabled = locationManager
// .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
public static boolean isConnected(Context context){
NetworkInfo info = getNetworkInfo(context);
return (info != null && info.isConnected());
}
public static NetworkInfo getNetworkInfo(Context context){
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo();
}
/**
* Stop using GPS listener
* Calling this function will stop using GPS in your app
* */
public void stopUsingGPS(){
if(locationManager != null){
locationManager.removeUpdates(GPSTracker_DUP.this);
}
}
/**
* Function to get latitude
* */
public double getLatitude(){
if(location != null){
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
* */
public double getLongitude(){
if(location != null){
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
/**
* Function to check GPS/wifi enabled
* @return boolean
* */
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* Function to show settings alert dialog
* On pressing Settings button will lauch Settings Options
* */
public void showSettingsAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
@Override
public void onLocationChanged(Location location) {
latitude = location.getLatitude();
longitude = location.getLongitude();
Log.e("onlocation","changed");
}
public void saveLocation(Double latitude,Double longitude){
objSaveData = new SaveData(mContext);
Log.e("Saving Coordinates", latitude + " " + longitude);
AudioDbHelper audioDbHelper= new AudioDbHelper(mContext);
UserCoordinates userCoordinates = new UserCoordinates();
userCoordinates.setLatitude(String.valueOf(latitude));
userCoordinates.setLongitude(String.valueOf(longitude));
userCoordinates.setUploaded("no");
SaveData objSaveData = new SaveData(mContext);
userCoordinates.setUserEmail(objSaveData.getString("LoginId"));
String time = new SimpleDateFormat("hh:mm: aa").format(Calendar.getInstance().getTime());
userCoordinates.setLocationTime(time);
audioDbHelper.addCoordinates(userCoordinates);
}
@Override
public void onDestroy() {
super.onDestroy();
stopUsingGPS();
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
答案 0 :(得分:0)
由于您需要在一段时间后发送位置,因此最好使用在一段时间后启动服务的Job Scheduler,获取位置并进行API调用。
最好的是Job Scheduler,这是Google推荐的,但Android版本限制了它的使用,最好使用Evernote Android Job。根据Android版本,使用JobScheduler,GcmNetworkManager或AlarmManager。
您不必担心服务被杀,因为现在操作系统有责任启动服务
还要提取位置,使用Google Play位置来获取位置。它的作用是从您的设备中获取Google Play服务的位置,该位置会不时更新。
看一下我在我的一个项目中用来从正在运行的服务中获取位置的Util类。它在Kotlin并使用Dagger2,但你会得到这个想法。它有一个回调界面,可以通过Google Play位置服务
回复当前位置和地址答案 1 :(得分:0)
默认情况下,您需要为此Start_Sticky
创建START_STICKY_COMPATIBILITY
服务。覆盖onStartCommand()
。
@Override
public int onStartCommand(Intent intent, int flags, int startId){
// Do your Stuff
return START_STICKY;
}
然而由于背景限制,这在最新版本的android中不起作用。因此,您可能希望结帐Background Location Limits和Android 8.0 Behavior Changes。
如果您需要在一段时间后发送位置,建议您使用JobShedular。有一些可用,例如Evernote android-job,Firebase JobDispatcher。
答案 2 :(得分:0)
您应将WorkManager或FirebaseJobDispatcher用于后台进程。但是Android Q不支持FirebaseJobDispatcher。
这是我使用WorkManager在后台获取位置的解决方案
在活动或片段中定义
private fun startTaskWithWorkManager() {
val constraints: Constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val locationWorker =
PeriodicWorkRequest.Builder(LocationWorker::class.java, MIN_PERIODIC_INTERVAL_MILLIS, TimeUnit.MILLISECONDS)
.setConstraints(constraints)
.addTag(LOCATION_WORKER_TAG)
.setInputData(createInputData())
.build()
WorkManager.getInstance()
.enqueueUniquePeriodicWork(LOCATION_WORKER_TAG, ExistingPeriodicWorkPolicy.KEEP, locationWorker)
}
之后,您应该创建一个将从ListenableWorker扩展的类。就我而言,我必须使用ListenableWorker而不是Worker。您可以找到here和here的不同之处。
class LocationWorker(context: Context, private val workerParams: WorkerParameters) :
ListenableWorker(context, workerParams) {
lateinit var mFuture: SettableFuture<ListenableWorker.Result>
private var fusedLocationProviderClient = FusedLocationProviderClient(context)
@SuppressLint("RestrictedApi", "MissingPermission")
override fun startWork(): ListenableFuture<Result> {
val uniqueId = workerParams.inputData.getString(UNIQUE_ID_KEY)
mFuture = SettableFuture.create()
Timber.d("mFutureStart")
fusedLocationProviderClient.lastLocation.addOnSuccessListener { location ->
Timber.d("location == $location")
if (location != null) {
mFuture.set(Result.success())
} else mFuture.set(Result.failure())
}
return mFuture
}
}
就这样:) 像魅力一样工作