FusedLocationProviderClient 后台服务适用于 Android 9 及更高版本。

huangapple go评论130阅读模式
英文:

FusedLocationProviderClient Background Service for Android 9 and Later

问题

以下是你提供的代码的翻译:

package com.example.locationupdate;

import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import com.example.locationupdate.db.Realm$Helper;
import com.example.locationupdate.shared_pref.SaveInSharedPreference;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;

import java.util.List;

import static com.google.android.gms.location.LocationServices.getFusedLocationProviderClient;

public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener  {

    private long UPDATE_INTERVAL = 10 * 1000;  /* 10 seconds */
    private long FASTEST_INTERVAL = 2000;
    int count = 0;

    List<FilterData> datafromDB;
    FusedLocationProviderClient mFusedLocationClient;
    LocationRequest mLocationRequest;

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

    LocationCallback mLocationCallback = new LocationCallback(){
        @Override
        public void onLocationResult(LocationResult locationResult) {

            for (Location location : locationResult.getLocations()) {

                if (SaveInSharedPreference.getInSharedPreference(LocationService.this).getLat() == 0.0 &&
                        SaveInSharedPreference.getInSharedPreference(LocationService.this).getLng() == 0.0) {
                    SaveInSharedPreference.getInSharedPreference(LocationService.this).setLatLong(location.getLatitude(), location.getLongitude());
                }
                SaveInSharedPreference.getInSharedPreference(LocationService.this).setCurrentLatLong(location.getLatitude(), location.getLongitude());

                count = count + 1;

                Log.e("mLocationCallbackLat", String.valueOf(location.getLatitude()));
                Log.e("mLocationCallbackLong", String.valueOf(location.getLongitude()));
            }
        }
    };

    public void onResume() {
        Log.e("OnResume", "OnResumeEvent");
        if (mFusedLocationClient != null) {
            requestLocationUpdates();
        }
    }

    public void requestLocationUpdates() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);

        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
        }
    }

    public void onPause() {
        Log.e("ONPause", "OnPauseEvent");
        if (mFusedLocationClient != null) {
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
        }
    }

    // The rest of the code remains unchanged...

    @Override
    public void onConnected(@Nullable Bundle bundle) {
    }

    @Override
    public void onConnectionSuspended(int i) {
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    }
}
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent startIntent = new Intent(this, LocationService.class);
    startService(startIntent);

    // The rest of the code remains unchanged...
}
英文:

I am trying to get location after every 10 second using FusedLocationProviderClient, However when i minimize the app or terminate it the location updates stops. Below is my code. Right now i am using android 9.0. I have no idea why this is happening any help will be grateful

Android Menifest

        &lt;service android:enabled=&quot;true&quot; android:name=&quot;.LocationService&quot;&gt;
&lt;/service&gt;

LocationService.java

package com.example.locationupdate;
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.example.locationupdate.db.Realm$Helper;
import com.example.locationupdate.shared_pref.SaveInSharedPreference;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import java.util.List;
import static com.google.android.gms.location.LocationServices.getFusedLocationProviderClient;
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener  {
//private LocationRequest mLocationRequest;
private long UPDATE_INTERVAL = 10 * 1000;  /* 10 secs */
private long FASTEST_INTERVAL = 2000;
int count = 0;
List&lt;FilterData&gt; datafromDB;
FusedLocationProviderClient mFusedLocationClient;
LocationRequest mLocationRequest;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
LocationCallback mLocationCallback = new LocationCallback(){
@Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
//Log.e(&quot;MainActivity&quot;, &quot;Location: &quot; + location.getLatitude() + &quot; &quot; + location.getLongitude());
if (SaveInSharedPreference.getInSharedPreference(LocationService.this).getLat() == 0.0 &amp;&amp; SaveInSharedPreference.getInSharedPreference(LocationService.this).getLng() == 0.0) {
SaveInSharedPreference.getInSharedPreference(LocationService.this).setLatLong(location.getLatitude(), location.getLongitude());
}
SaveInSharedPreference.getInSharedPreference(LocationService.this).setCurrentLatLong(location.getLatitude(), location.getLongitude());
count = count + 1;
Log.e(&quot;mLocationCallbackLat&quot;, String.valueOf(location.getLatitude()));
Log.e(&quot;mLocationCallbackLong&quot;, String.valueOf(location.getLongitude()));
//LocationMatch(location);
}
/* datafromDB = Realm$Helper.getLocation$Module(LocationService.this).getAllData();
for (FilterData str : datafromDB) {
String name = str.getName();
}*/
};
};
public void onResume() {
Log.e(&quot;OnResume&quot;, &quot;OnResumeEvent&quot;);
if (mFusedLocationClient != null) {
requestLocationUpdates();
}
}
public void requestLocationUpdates() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL); // two minute interval
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
}
public void onPause() {
//super.onPause();
Log.e(&quot;ONPause&quot;, &quot;OnPauseEvent&quot;);
if (mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
}
protected void startLocationUpdates() {
// Create the location request to start receiving updates
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
// Create LocationSettingsRequest object using location request
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// Check whether location settings are satisfied
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
settingsClient.checkLocationSettings(locationSettingsRequest);
// new Google API SDK v11 uses getFusedLocationProviderClient(this)
getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
// do work here
onLocationChanged(locationResult.getLastLocation());
}
},
Looper.myLooper());
}
public void onLocationChanged(Location location) {
if (SaveInSharedPreference.getInSharedPreference(LocationService.this).getLat() == 0.0 &amp;&amp; SaveInSharedPreference.getInSharedPreference(LocationService.this).getLng() == 0.0) {
SaveInSharedPreference.getInSharedPreference(LocationService.this).setLatLong(location.getLatitude(), location.getLongitude());
}
SaveInSharedPreference.getInSharedPreference(LocationService.this).setCurrentLatLong(location.getLatitude(), location.getLongitude());
Toast.makeText(this,&quot;onLocationChanged&quot;,Toast.LENGTH_LONG);
// New location has now been determined
String msg = &quot;Updated Location: &quot; +
Double.toString(location.getLatitude()) + &quot;,&quot; +
Double.toString(location.getLongitude());
Log.e (&quot;onLocationChangedLat&quot;, String.valueOf(location.getLatitude()));
Log.e (&quot;onLocationChangedLong&quot;, String.valueOf(location.getLongitude()));
// You can now create a LatLng Object for use with maps
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
/*loc1.setLatitude(location.getLatitude());
loc1.setLongitude(location.getLongitude());
loc2.setLatitude(str.getLat());
loc2.setLongitude(str.getlng());
double distanceInMeters = loc1.distanceTo(loc2);
Log.e(&quot;Name&quot;, name);
Log.e(&quot;Distance&quot;, &quot;&quot; + distanceInMeters);*/
}
public void getLastLocation() {
// Get last known recent location using new Google Play Services SDK (v11+)
FusedLocationProviderClient locationClient = getFusedLocationProviderClient(this);
locationClient.getLastLocation()
.addOnSuccessListener(new OnSuccessListener&lt;Location&gt;() {
@Override
public void onSuccess(Location location) {
// GPS location can be null if GPS is switched off
if (location != null) {
onLocationChanged(location);
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d(&quot;MapDemoActivity&quot;, &quot;Error trying to get last GPS location&quot;);
e.printStackTrace();
}
});
}
@Override
public void onConnected(@Nullable Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
}

MainActitvity.java

    protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//locationTv = findViewById(R.id.location);
Intent startIntent = new Intent(this, LocationService.class);
startService(startIntent);

答案1

得分: 4

以下是翻译好的内容:

通过设置处理程序并向 Android 应用添加所需的权限,您可以实现此目标。显然,根据Android 后台定位,在后台请求位置的次数是有限的,但我没有看到这一点。我每秒请求一次新的位置。

首先在清单中添加以下内容:

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

然后,您可以像这样创建一个处理程序。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    createLocationHandler();
    ...
}

createLocationHandler 和 isServiceRunning 函数:

public void createLocationHandler(){
    HandlerThread locationHandler = new HandlerThread("LocationHandler"); // 创建一个新的处理程序线程
    locationHandler.start(); // 启动线程
    Handler handler = new Handler(locationHandler.getLooper()); // 从处理程序线程获取 Looper
    handler.postDelayed(new Runnable() { // 仅在给定的时间之后运行可运行项
        @Override
        public void run() {
            // 检查位置服务是否正在运行,如果没有,让我们启动它!
            if(!isMyServiceRunning(LocationService.class)){
                getApplicationContext().startService(new Intent(getApplicationContext(), LocationService.class));
            }
            // 从位置服务请求新的位置(感觉可以以一种不太静态的方式完成)
            LocationService.requestNewLocation();
            createLocationHandler(); // 再次调用创建位置处理程序,这不会因为 Looper 而添加到堆栈中。
        }
    }, 10000); // 将延迟设置为 10 秒,1 秒 = 1000 毫秒
}

private boolean isMyServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) this.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

在启动服务之前,请记得请求 background_location 权限。

英文:

You can achieve this by setting up a handler and adding the required permissions to the android app. Apperantly there is a limit to how many times you can request the location in the background according to Android Location In Background but i have not seen this. Im requesting a new location every second.

First add these to your manifest:

&lt;uses-permission android:name=&quot;android.permission.ACCESS_BACKGROUND_LOCATION&quot;/&gt;
&lt;uses-permission android:name=&quot;android.permission.ACCESS_COARSE_LOCATION&quot;/&gt;
&lt;uses-permission android:name=&quot;android.permission.ACCESS_FINE_LOCATION&quot;/&gt;

Then you can create a handler like this.

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
createLocationHandler();
...
}

The createLocationHandler and isServiceRunning function:

public void createLocationHandler(){
HandlerThread locationHandler = new HandlerThread(&quot;LocationHandler&quot;); //Creates a new handler thread
locationHandler.start(); //Starts the thread
Handler handler = new Handler(locationHandler.getLooper()); //Get the looper from the handler thread
handler.postDelayed(new Runnable() {//Run the runnable only after the given time
@Override
public void run() {
//Check if the location service is running, if its not. lets start it!
if(!isMyServiceRunning(LocationService.class)){
getApplicationContext().startService(new Intent(getApplicationContext(), LocationService.class));
}
//Requests a new location from the location service(Feel like it could be done in a less static way)
LocationService.requestNewLocation();
createLocationHandler();//Call the create location handler again, this will not be added to the stack because of the looper.
}
}, 10000);//Set the delay to be 10 seconds, 1 second = 1000 milliseconds
}
private boolean isMyServiceRunning(Class&lt;?&gt; serviceClass) {
ActivityManager manager = (ActivityManager) this.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}

Remember to ask for the background_location permission before you want to start the service.

huangapple
  • 本文由 发表于 2020年3月16日 03:42:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/60696903.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定