Android 定位后台服务在其他手机上不起作用
Posted
技术标签:
【中文标题】Android 定位后台服务在其他手机上不起作用【英文标题】:Android background service for location is not working in other phones 【发布时间】:2017-04-13 12:35:03 【问题描述】:位置检测的后台服务会在一段时间后关闭。我在onTaskRemoved
中有代码来设置挂起撤消的警报。我仍然无法解决问题。下面是我的后台服务类的代码:
public class MyService extends Service
public static final String BROADCAST_ACTION = "Hello World";
private static final int TWO_MINUTES = 1000 * 60 *5;
public LocationManager locationManager;
public MyLocationListener listener;
public Location previousBestLocation = null;
double latitude; // latitude
double longitude; // longitude
Intent intent;
private static final String POST_URL = "http://api.url.com/oauth/api/v1/location/update";
int counter = 0;
public static boolean isRunning = false;
@Override
public void onCreate()
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
@Override
public void onStart(Intent intent, int startId)
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listener = new MyLocationListener();
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.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;
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
@Override
public IBinder onBind(Intent intent)
super.onCreate();
return (IBinder) intent;
protected boolean isBetterLocation(Location location, Location currentBestLocation)
if (currentBestLocation == null)
return true;
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
if (isSignificantlyNewer)
return true;
else if (isSignificantlyOlder)
return false;
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate)
return true;
else if (isNewer && !isLessAccurate)
return true;
else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider)
return true;
return false;
/**
* Checks whether two providers are the same
*/
private boolean isSameProvider(String provider1, String provider2)
if (provider1 == null)
return provider2 == null;
return provider1.equals(provider2);
@Override
public void onDestroy()
super.onDestroy();
Toast.makeText(getApplicationContext(),"onDestroy",Toast.LENGTH_LONG).show();
Log.d("onDestroy","onDestroy");
Intent myIntent = new Intent(getApplicationContext(), MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, myIntent, 0);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 1);
alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10, pendingIntent);
@Override
public void onTaskRemoved(Intent rootIntent)
super.onTaskRemoved(rootIntent);
Toast.makeText(getApplicationContext(),"onTaskRemoved",Toast.LENGTH_LONG).show();
Log.d("onTaskRemoved", "onTaskRemoved");
Intent myIntent = new Intent(getApplicationContext(), MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, myIntent, 0);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 1);
alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10, pendingIntent) ;
public class MyLocationListener implements LocationListener
public void onLocationChanged(final Location loc)
if (isBetterLocation(loc, previousBestLocation))
latitude = loc.getLatitude();
longitude = loc.getLongitude();
intent.putExtra("Latitude", loc.getLatitude());
intent.putExtra("Longitude", loc.getLongitude());
intent.putExtra("Provider", loc.getProvider());
sendBroadcast(intent);
SharedPreferences check = getApplicationContext().getSharedPreferences("Access_token", Context.MODE_PRIVATE);
final String access_token = check.getString("access_token", "N/A");
StringRequest stringRequest = new StringRequest(Request.Method.POST, POST_URL,
new Response.Listener<String>()
@Override
public void onResponse(String response)
Toast.makeText(getApplicationContext(),""+response,Toast.LENGTH_LONG).show();
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
Toast.makeText(getApplicationContext(),""+error,Toast.LENGTH_LONG).show();
)
@Override
protected Map<String, String> getParams()
Map<String, String> params = new HashMap<String, String>();
params.put("access_token", access_token);
params.put("latitude", String.valueOf(latitude));
params.put("longitude", String.valueOf(longitude));
return params;
;
stringRequest.setRetryPolicy(new DefaultRetryPolicy(1 * 500000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(stringRequest);
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
@Override
public void onProviderEnabled(String provider)
@Override
public void onProviderDisabled(String provider)
【问题讨论】:
我发现您的代码存在一些问题。您不能从onBind()
呼叫super.onCreate()
。不要使用onStart()
,因为它在 100 年前已被弃用。实现onStartCommand()
并返回START_STICKY
。
你知道哪些设备有这个问题吗?
【参考方案1】:
在 onbind 方法中返回 null 因为返回某些内容意味着您希望将其绑定到组件,这可能导致关闭该组件时停止服务。也使用 onStartCommand 代替 onStart。如果您需要 OnStartCommand 方法中的意图,则返回 START_REDELIVER_INTENT 标志,否则使用 START_STICKY 重新启动服务。
public class MyService extends Service
public static final String BROADCAST_ACTION = "Hello World";
private static final int TWO_MINUTES = 1000 * 60 *5;
public LocationManager locationManager;
public MyLocationListener listener;
public Location previousBestLocation = null;
double latitude; // latitude
double longitude; // longitude
Intent intent;
private static final String POST_URL = "http://api.url.com/oauth/api/v1/location/update";
int counter = 0;
public static boolean isRunning = false;
@Override
public int onStartCommand(Intent intent, int flags, int startId)
this.intent = new Intent(BROADCAST_ACTION);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listener = new MyLocationListener();
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.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.
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
return START_STICKY;
protected boolean isBetterLocation(Location location, Location currentBestLocation)
if (currentBestLocation == null)
return true;
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
if (isSignificantlyNewer)
return true;
else if (isSignificantlyOlder)
return false;
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate)
return true;
else if (isNewer && !isLessAccurate)
return true;
else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider)
return true;
return false;
/**
* Checks whether two providers are the same
*/
private boolean isSameProvider(String provider1, String provider2)
if (provider1 == null)
return provider2 == null;
return provider1.equals(provider2);
@Override
public void onDestroy()
super.onDestroy();
Toast.makeText(getApplicationContext(),"onDestroy", Toast.LENGTH_LONG).show();
Log.d("onDestroy","onDestroy");
Intent myIntent = new Intent(getApplicationContext(), MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, myIntent, 0);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 1);
alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10, pendingIntent);
@Nullable
@Override
public IBinder onBind(Intent intent)
return null;
@Override
public void onTaskRemoved(Intent rootIntent)
super.onTaskRemoved(rootIntent);
Toast.makeText(getApplicationContext(),"onTaskRemoved",Toast.LENGTH_LONG).show();
Log.d("onTaskRemoved", "onTaskRemoved");
Intent myIntent = new Intent(getApplicationContext(), MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, myIntent, 0);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 1);
alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10, pendingIntent) ;
public class MyLocationListener implements LocationListener
public void onLocationChanged(final Location loc)
if (isBetterLocation(loc, previousBestLocation))
latitude = loc.getLatitude();
longitude = loc.getLongitude();
intent.putExtra("Latitude", loc.getLatitude());
intent.putExtra("Longitude", loc.getLongitude());
intent.putExtra("Provider", loc.getProvider());
sendBroadcast(intent);
SharedPreferences check = getApplicationContext().getSharedPreferences("Access_token", Context.MODE_PRIVATE);
final String access_token = check.getString("access_token", "N/A");
StringRequest stringRequest = new StringRequest(Request.Method.POST, POST_URL,
new Response.Listener<String>()
@Override
public void onResponse(String response)
Toast.makeText(getApplicationContext(),""+response,Toast.LENGTH_LONG).show();
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
Toast.makeText(getApplicationContext(),""+error,Toast.LENGTH_LONG).show();
)
@Override
protected Map<String, String> getParams()
Map<String, String> params = new HashMap<String, String>();
params.put("access_token", access_token);
params.put("latitude", String.valueOf(latitude));
params.put("longitude", String.valueOf(longitude));
return params;
;
stringRequest.setRetryPolicy(new DefaultRetryPolicy(1 * 500000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(stringRequest);
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
@Override
public void onProviderEnabled(String provider)
@Override
public void onProviderDisabled(String provider)
【讨论】:
以上是关于Android 定位后台服务在其他手机上不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Cordova 地理定位插件在 android 设备上不起作用