Я пытаюсь узнать местоположение пользователя в режиме реального времени, используя сервис. Проблема возникает, когда я пытаюсь сделать это ниже Android 8.0 из-за службы переднего плана, я искал несколько способов сделать это, но я не нашел ни одного, который работает ниже Android 8.0.
Код что я использовал:
MainActivity
public class MainActivity extends AppCompatActivity {
@BindView(R.id.btn_start_tracking)
Button btnStartTracking;
@BindView(R.id.btn_stop_tracking)
Button btnStopTracking;
@BindView(R.id.txt_status)
TextView txtStatus;
public BackgroundService gpsService;
public boolean mTracking = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
final Intent intent = new Intent(this.getApplication(), BackgroundService.class);
this.getApplication().startService(intent);
this.getApplication().startForegroundService(intent);
this.getApplication().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
@OnClick(R.id.btn_start_tracking)
public void startLocationButtonClick() {
Dexter.withActivity(this)
.withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.withListener(new PermissionListener() {
@Override
public void onPermissionGranted(PermissionGrantedResponse response) {
gpsService.startTracking();
mTracking = true;
toggleButtons();
}
@Override
public void onPermissionDenied(PermissionDeniedResponse response) {
if (response.isPermanentlyDenied()) {
openSettings();
}
}
@Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
token.continuePermissionRequest();
}
}).check();
}
@OnClick(R.id.btn_stop_tracking)
public void stopLocationButtonClick() {
mTracking = false;
gpsService.stopTracking();
toggleButtons();
}
private void toggleButtons() {
btnStartTracking.setEnabled(!mTracking);
btnStopTracking.setEnabled(mTracking);
txtStatus.setText( (mTracking) ? "TRACKING" : "GPS Ready" );
}
private void openSettings() {
Intent intent = new Intent();
intent.setAction( Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
String name = className.getClassName();
if (name.endsWith("BackgroundService")) {
gpsService = ((BackgroundService.LocationServiceBinder) service).getService();
btnStartTracking.setEnabled(true);
txtStatus.setText("GPS Ready");
}
}
public void onServiceDisconnected(ComponentName className) {
if (className.getClassName().equals("BackgroundService")) {
gpsService = null;
}
}
};
}
Фоновый класс обслуживания
public class BackgroundService extends Service {
private final LocationServiceBinder binder = new LocationServiceBinder();
private final String TAG = "BackgroundService";
private LocationListener mLocationListener;
private LocationManager mLocationManager;
private NotificationManager notificationManager;
private final int LOCATION_INTERVAL = 500;
private final int LOCATION_DISTANCE = 10;
@Override
public IBinder onBind(Intent intent) {
return binder;
}
private class LocationListener implements android.location.LocationListener {
private Location lastLocation = null;
private final String TAG = "LocationListener";
private Location mLastLocation;
public LocationListener(String provider)
{
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location)
{
mLastLocation = location;
Log.i(TAG, "LocationChanged: "+location);
}
@Override
public void onProviderDisabled(String provider)
{
Log.e(TAG, "onProviderDisabled: " + provider);
}
@Override
public void onProviderEnabled(String provider)
{
Log.e(TAG, "onProviderEnabled: " + provider);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.e(TAG, "onStatusChanged: " + status);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onCreate()
{
Log.i(TAG, "onCreate");
startForeground(12345678, getNotification());
}
@Override
public void onDestroy()
{
super.onDestroy();
if (mLocationManager != null) {
try {
mLocationManager.removeUpdates(mLocationListener);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
}
private void initializeLocationManager() {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
public void startTracking() {
initializeLocationManager();
mLocationListener = new LocationListener(LocationManager.GPS_PROVIDER);
try {
mLocationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, mLocationListener );
} catch (java.lang.SecurityException ex) {
// Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
// Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
public void stopTracking() {
this.onDestroy();
}
private Notification getNotification() {
NotificationChannel channel = new NotificationChannel("channel_01", "My Channel", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
Notification.Builder builder = new Notification.Builder(getApplicationContext(), "channel_01").setAutoCancel(true);
return builder.build();
}
public class LocationServiceBinder extends Binder {
public BackgroundService getService() {
return BackgroundService.this;
}
}
}
Манифест
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ac.myapp">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".maps"></activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:enabled="true"
android:name=".BootUpReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name=".BackgroundService"/>
</application>