为啥在 API > 23 中不调用 FusedLocationApi (onLocationChanged)?
Posted
技术标签:
【中文标题】为啥在 API > 23 中不调用 FusedLocationApi (onLocationChanged)?【英文标题】:Why FusedLocationApi (onLocationChanged) is not called in API > 23?为什么在 API > 23 中不调用 FusedLocationApi (onLocationChanged)? 【发布时间】:2017-08-04 20:39:49 【问题描述】:我有一个获取位置的服务,该服务在 API 23 上无法通过网络获取任何位置。它只是通过 gps 获取位置。
public class TrackLocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener
private static final long SYNCHRONIZATION_INTERVAL = 60 * 60 * 1000;
private static boolean isServiceRunning;
private static final String TAG = "SADASDQWREQWRwerwer";
private int notificationId = 9999;
private GoogleApiClient googleApiClient;
private TrackLocationApplication app;
private DataHelper dataHelper;
public static boolean isServiceRunning()
return isServiceRunning;
private static void setIsServiceRunning(boolean isServiceRunning)
TrackLocationService.isServiceRunning = isServiceRunning;
EventBus.getDefault().post(AppEvent.SERVICE_STATE_CHANGED);
public TrackLocationService()
@Override
public void onCreate()
super.onCreate();
Log.d(TAG, "onCreate");
app = (TrackLocationApplication) getApplication();
dataHelper = DataHelper.getInstance(getApplicationContext());
@Override
public int onStartCommand(Intent intent, int flags, int startId)
Log.d(TAG, "onStartCommand");
createGoogleApiClient();
connectGoogleApiClient();
TrackLocationService.setIsServiceRunning(true);
return super.onStartCommand(intent, flags, startId);
@Override
public void onDestroy()
super.onDestroy();
Log.d(TAG, "onDestroy");
stopLocationUpdates();
cancelNotification();
app.setStartLocation(null);
TrackLocationService.setIsServiceRunning(false);
@Override
public IBinder onBind(Intent intent)
throw new UnsupportedOperationException("Not yet implemented");
@Override
public void onLocationChanged(Location location)
Log.d(TAG, "onLocationChanged");
if (app.getStartLocation() == null)
app.setStartLocation(location);
Log.i("ASDASDASDASDA", location.getLatitude() + "" + location.getLongitude());
updateLocationData(location);
@Override
public void onConnected(Bundle bundle)
Log.d(TAG, "onConnected");
startLocationUpdates();
@Override
public void onConnectionSuspended(int i)
Log.d(TAG, "onConnectionSuspended");
@Override
public void onConnectionFailed(ConnectionResult result)
Log.d(TAG, "onConnectionFailed");
@Override
public void onTaskRemoved(Intent rootIntent)
super.onTaskRemoved(rootIntent);
Log.d(TAG, "onTaskRemoved");
private void createGoogleApiClient()
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
private void connectGoogleApiClient()
if (googleApiClient != null)
if (!(googleApiClient.isConnected() || googleApiClient.isConnecting()))
googleApiClient.connect();
else
Log.d(TAG, "Client is connected");
startLocationUpdates();
else
Log.d(TAG, "Client is null");
private void startLocationUpdates()
Log.i("ASDASDASDASDA", "1");
LocationRequest locationRequest = app.createLocationRequest();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, 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;
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
scheduleDataSynchronization();
private void stopLocationUpdates()
LocationServices.FusedLocationApi.removeLocationUpdates(
googleApiClient, this);
stopDataSynchronization();
private void scheduleDataSynchronization()
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, TrackLocationSyncReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
SYNCHRONIZATION_INTERVAL, alarmIntent);
private void stopDataSynchronization()
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, TrackLocationSyncReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.cancel(alarmIntent);
private void updateLocationData(Location location)
Location startLocation = app.getStartLocation();
double latitude = location.getLatitude();
double longitude = location.getLongitude();
float distance = Utils.distFromCoordinates((float) startLocation.getLatitude(),
(float) startLocation.getLongitude(),
(float) latitude,
(float) longitude);
String timeText = Utils.formatTime(System.currentTimeMillis());
long date = System.currentTimeMillis();
dataHelper.saveLocation(LocationData.getInstance(latitude, longitude, "2"));
updateNotification(timeText);
private void updateNotification(String text)
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.qomGardy))
.setContentText(text);
Intent resultIntent = new Intent(this, GetNumberActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(GetNumberActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = mBuilder.build();
mNotificationManager.notify(notificationId, notification);
private void cancelNotification()
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(notificationId);
private void synchronizeData()
new AsyncTask<Void, Void, TrackLocationResponse>()
private List<LocationData> locations;
@Override
protected TrackLocationResponse doInBackground(Void[] params)
TrackLocationResponse response = null;
//locations = dataHelper.getLocationsToSync();
if (locations != null && locations.size() > 0)
String deviceId = TrackLocationPreferencesManager.getDeviceId(getApplicationContext());
String userName = TrackLocationPreferencesManager.getUserName(getApplicationContext());
TrackLocationRequest request = TrackLocationRequest.getInstance(locations, deviceId, userName);
ITrackLocationClient client = new TrackLocationClient();
response = client.addTrack(request);
if (response != null && response.getStatus() == TrackLocationResponse.RESPONSE_CODE_OK)
Log.d("TrackLocationSync", "Synced " + locations.size() + " items");
//dataHelper.markLocationsSynced(locations);
else
Log.d("TrackLocationSync", "No data to be synced");
return response;
@Override
protected void onPostExecute(TrackLocationResponse response)
super.onPostExecute(response);
if (response != null && response.getStatus() == TrackLocationResponse.RESPONSE_CODE_OK)
String message = null;
List<FriendResult> results = response.getResult();
if (results != null && results.size() > 0)
StringBuilder messageBuilder = new StringBuilder();
messageBuilder.append("Hi from ");
for (FriendResult r : results)
messageBuilder.append(" ");
messageBuilder.append(r.getTitle());
messageBuilder.append(",");
messageBuilder.deleteCharAt(messageBuilder.length() - 1);
message = messageBuilder.toString();
else
message = "Sync " + locations.size() + " items at " + Utils.formatTime(System.currentTimeMillis());
updateNotification(message);
.execute();
我在 API > 23 的清单中添加了这些权限:
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
不要打电话给onLocationChanged()
!
在我的活动中,我获得了所有权限。
【问题讨论】:
【参考方案1】:在 API 23+ 上,您需要在运行时请求权限,而不是在清单中: Requesting Permissions at Run Time
编辑:在您发布的代码中,您不执行ActivityCompat.requestPermissions
仅检查权限,正如我在 23+ 中所说,您必须在运行时请求权限,如果您在其他地方执行此操作,请将代码添加为好吧。
PS:你只需要实现 TODO:你有
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, 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;
【讨论】:
在我的活动中,我获得了所有权限。以上是关于为啥在 API > 23 中不调用 FusedLocationApi (onLocationChanged)?的主要内容,如果未能解决你的问题,请参考以下文章
setLayoutParams() 在 API <= 23 中不起作用
为啥 DirectX Device Present 钩子在弯路中不起作用?