在android中的位置监听器的后台服务

Nil*_*hal 71 android android-service android-location

我正在创建一个将在自己的进程中运行的后台服务.它应该允许我听设备位置是否已更改.我应该能够在通知用户界面之前更改移动距离等标准.

我怎么能这样做?我对服务和LocationListener实现有一点了解.任何围绕网络的教程将不胜感激.

我从堆栈溢出中获得了一个反向链接,但我对此并不了解.

Usm*_*urd 112

首先你需要创建一个Service.在那里Service,创建一个扩展类LocationListener.为此,请使用以下代码段Service:

public class LocationService extends Service {
public static final String BROADCAST_ACTION = "Hello World";
private static final int TWO_MINUTES = 1000 * 60 * 2;
public LocationManager locationManager;
public MyLocationListener listener;
public Location previousBestLocation = null;

Intent intent;
int counter = 0;

@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, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 4000, 0, (LocationListener) listener);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 4000, 0, listener);
}

@Override
public IBinder onBind(Intent intent)
{
    return null;
}

protected boolean isBetterLocation(Location location, Location currentBestLocation) {
    if (currentBestLocation == null) {
        // A new location is always better than no location
        return true;
    }

    // Check whether the new location fix is newer or older
    long timeDelta = location.getTime() - currentBestLocation.getTime();
    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
    boolean isNewer = timeDelta > 0;

    // If it's been more than two minutes since the current location, use the new location
    // because the user has likely moved
    if (isSignificantlyNewer) {
        return true;
        // If the new location is more than two minutes older, it must be worse
    } 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() {
    // handler.removeCallbacks(sendUpdatesToUI);     
    super.onDestroy();
    Log.v("STOP_SERVICE", "DONE");
    locationManager.removeUpdates(listener);
}

public static Thread performOnBackgroundThread(final Runnable runnable) {
    final Thread t = new Thread() {
        @Override
        public void run() {
            try {
                runnable.run();
            } finally {

            }
        }
    };
    t.start();
    return t;
}
public class MyLocationListener implements LocationListener
{

    public void onLocationChanged(final Location loc)
    {
        Log.i("*****", "Location changed");
        if(isBetterLocation(loc, previousBestLocation)) {
            loc.getLatitude();
            loc.getLongitude();
            intent.putExtra("Latitude", loc.getLatitude());
            intent.putExtra("Longitude", loc.getLongitude());
            intent.putExtra("Provider", loc.getProvider());
            sendBroadcast(intent);

        }
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    public void onProviderDisabled(String provider)
    {
        Toast.makeText( getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT ).show();
    }


    public void onProviderEnabled(String provider)
    {
        Toast.makeText( getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
    }
}
Run Code Online (Sandbox Code Playgroud)

Service在您的项目中的任何位置添加此项,您想要的方式!:)

  • 什么是"performOnBackgroundThread"函数?它用在某个地方吗? (11认同)
  • 请注意:该代码看起来可能来自[GPL项目](https://code.google.com/p/chataround-dto/source/browse/chataround-client/src/com/service/ chataround/listener/MyLocationListener.java?r = 101)(或者,它可能来自[this](https://code.google.com/p/apk/source/browse/trunk/src/com/vouov/listener /MyLocationListener.java?r=5)MIT许可项目.有人知道上述代码的许可证状态吗? (4认同)
  • 使用onStartCommand()而不是onStart()并返回START_STICKY.上面的代码也不会在单独的进程中运行(对于这些有不同的解决方案),因此每当Android系统将杀死应用程序(主要是在后台运行之后)时,服务将停止 - 尽管如果有可用资源它将再次启动感谢START_STICKY.当应用程序在后台时,还有不同的解决方案可以使Service保持活动状态. (3认同)
  • 由于Google Play服务包含位置服务,因此建议您使用它:https://github.com/nickfox/GpsTracker/blob/master/phoneClients/android/app/src/main/java/com/websmithing/gpstracker/LocationService的.java (2认同)

Kun*_*unu 11

我知道我发布这个答案的时间不多,但我觉得值得使用谷歌的保险丝位置提供商服务来获取当前位置.

这个api的主要特点是:

1.简单的API:让您选择准确度和功耗.

2.立即可用:让您的应用程序立即访问最佳,最新的位置.

3.功率效率:它选择最有效的方式来获得更少功耗的位置

4.Versatility:满足广泛的需求,从需要高度精确定位的前台使用到需要定期更新位置且功率影响可忽略不计的后台使用.

在更新位置时也很灵活.如果您只想在应用启动时想要当前位置,那么您可以使用getLastLocation(GoogleApiClient)方法.

如果您想要不断更新您的位置,那么您可以使用 requestLocationUpdates(GoogleApiClient,LocationRequest, LocationListener)

你可以在这里找到一个关于保险丝位置的非常好的博客,也可以在这里找到保险丝位置的谷歌doc .

更新

根据从Android O开始的开发人员文档,他们在背景位置上添加了新的限制.

如果您的应用在后台运行,则位置系统服务每小时仅为您的应用计算一次新位置.即使您的应用要求更频繁的位置更新,情况也是如此.但是,如果您的应用程序在前台运行,则与Android 7.1.1(API级别25)相比,位置采样率没有变化.

  • 如果您只是想知道您在某个时间的大致位置,或者对于不太准确的跟踪,那么`FusedLocationProvider`就可以了,但对于需要高精度跟踪的应用来说,它还不够好 (2认同)
  • 这些Custom Roms的解决方案是使用Mapzen的[LOST](https://github.com/mapzen/LOST).使用Google的FusedLocationProviderAPI提供相同的功能,无需注册Google Play服务 (2认同)

tej*_*hah 6

后台位置服务.即使在杀死应用程序后它也会重新启动.

MainActivity.java

public class MainActivity extends AppCompatActivity {
    AlarmManager alarmManager;
    Button stop;
    PendingIntent pendingIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (alarmManager == null) {
            alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent(this, AlarmReceive.class);
            pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
            alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 30000,
                    pendingIntent);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

BookingTrackingService.java

public class BookingTrackingService extends Service implements LocationListener {

    private static final String TAG = "BookingTrackingService";
    private Context context;
    boolean isGPSEnable = false;
    boolean isNetworkEnable = false;
    double latitude, longitude;
    LocationManager locationManager;
    Location location;
    private Handler mHandler = new Handler();
    private Timer mTimer = null;
    long notify_interval = 30000;

    public double track_lat = 0.0;
    public double track_lng = 0.0;
    public static String str_receiver = "servicetutorial.service.receiver";
    Intent intent;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        mTimer = new Timer();
        mTimer.schedule(new TimerTaskToGetLocation(), 5, notify_interval);
        intent = new Intent(str_receiver);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        this.context = this;


        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy <<");
        if (mTimer != null) {
            mTimer.cancel();
        }
    }

    private void trackLocation() {
        Log.e(TAG, "trackLocation");
        String TAG_TRACK_LOCATION = "trackLocation";
        Map<String, String> params = new HashMap<>();
        params.put("latitude", "" + track_lat);
        params.put("longitude", "" + track_lng);

        Log.e(TAG, "param_track_location >> " + params.toString());

        stopSelf();
        mTimer.cancel();

    }

    @Override
    public void onLocationChanged(Location location) {

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    /******************************/

    private void fn_getlocation() {
        locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
        isGPSEnable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetworkEnable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!isGPSEnable && !isNetworkEnable) {
            Log.e(TAG, "CAN'T GET LOCATION");
            stopSelf();
        } else {
            if (isNetworkEnable) {
                location = null;
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, this);
                if (locationManager != null) {
                    location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                    if (location != null) {

                        Log.e(TAG, "isNetworkEnable latitude" + location.getLatitude() + "\nlongitude" + location.getLongitude() + "");
                        latitude = location.getLatitude();
                        longitude = location.getLongitude();
                        track_lat = latitude;
                        track_lng = longitude;
//                        fn_update(location);
                    }
                }
            }

            if (isGPSEnable) {
                location = null;
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
                if (locationManager != null) {
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                    if (location != null) {
                        Log.e(TAG, "isGPSEnable latitude" + location.getLatitude() + "\nlongitude" + location.getLongitude() + "");
                        latitude = location.getLatitude();
                        longitude = location.getLongitude();
                        track_lat = latitude;
                        track_lng = longitude;
//                        fn_update(location);
                    }
                }
            }

            Log.e(TAG, "START SERVICE");
            trackLocation();

        }
    }

    private class TimerTaskToGetLocation extends TimerTask {
        @Override
        public void run() {

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    fn_getlocation();
                }
            });

        }
    }

//    private void fn_update(Location location) {
//
//        intent.putExtra("latutide", location.getLatitude() + "");
//        intent.putExtra("longitude", location.getLongitude() + "");
//        sendBroadcast(intent);
//    }
}
Run Code Online (Sandbox Code Playgroud)

AlarmReceive.java(BroadcastReceiver)

public class AlarmReceive extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e("Service_call_"  , "You are in AlarmReceive class.");
        Intent background = new Intent(context, BookingTrackingService.class);
//        Intent background = new Intent(context, GoogleService.class);
        Log.e("AlarmReceive ","testing called broadcast called");
        context.startService(background);
    }
}
Run Code Online (Sandbox Code Playgroud)

AndroidManifest.xml中

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

 <service
            android:name=".ServiceAndBroadcast.BookingTrackingService"
            android:enabled="true" />

        <receiver
            android:name=".ServiceAndBroadcast.AlarmReceive"
            android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
Run Code Online (Sandbox Code Playgroud)