如何从 Android 服务访问 GPS?
How do I access GPS from Android Service?
我正在尝试从后台服务获取位置信息。我使用以下代码从 Activity 启动服务。
Intent serviceIntent = new Intent(this, LocationService.class);
startService(serviceIntent);
这是我的服务代码。
public class LocationService extends Service {
private Thread t;
Looper threadLooper = null;
public int onStartCommand(Intent intent, int flags, int startId){
Log.i("Imp", "Inside service.");
new LooperThread().start();
return Service.START_NOT_STICKY;
}
private void logLocation(String lat, String lng){
//write to database.
}
class LooperThread extends Thread {
public void run() {
Log.i("Imp", "inside thread");
Looper.prepare();
Context context = getApplicationContext();
String svcName = Context.LOCATION_SERVICE;
LocationManager locationManager = (LocationManager) context.getSystemService(svcName);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setSpeedRequired(false);
criteria.setCostAllowed(false);
Log.i("Imp", "Regestring event.");
locationManager.requestSingleUpdate(criteria, locationListener, Looper.myLooper());
Log.i("Imp", "event reg.");
Looper.loop();
stopSelf();
}
}
final LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.i("Imp", "Inside event");
if(location != null){
String lat = Double.toString(location.getLatitude());
String lng = Double.toString(location.getLongitude());
Log.i("Imp", "Lat " + lat);
Log.i("Imp", "lng " + lng);
logLocation(lat, lng);
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
};
}
最初我使用得到错误,因为我为 Looper 对象传递了 null 参数。但是在传递了 looper 对象之后,我没有得到任何错误,但我什至没有得到任何坐标。
我每次 运行 代码时都会收到 event reg.
消息,但由于某种原因它从不调用监听器。
PS :我 运行 在我的 phone 上而不是模拟器上编写代码。
可能您还没有在清单文件中注册该服务。
所有服务都必须由清单文件中的元素表示。任何未在此处声明的内容都不会被系统看到,并且永远不会 运行.
<service android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:isolatedProcess=["true" | "false"]
android:label="string resource"
android:name="string"
android:permission="string"
android:process="string" >
</service>
推荐的方法是使用 Google 播放服务中的位置 API。
添加 google 播放服务依赖。
compile 'com.google.android.gms:play-services:+'
以及以下代码。
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class FusedLocationProvider implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener,
ArchitectViewHolderInterface.ILocationProvider {
private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private LocationListener listener;
private String TAG = "FusedLocationProvider";
public FusedLocationProvider(Context ctx, LocationListener locationListener){
mGoogleApiClient = new GoogleApiClient.Builder(ctx)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
Log.i(TAG, "Connecting...");
this.listener = locationListener;
}
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "onConnected");
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(1000); // Update location every second
try{
if(mGoogleApiClient.isConnected()) {
Log.i(TAG, "requestLocationUpdates");
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}catch (SecurityException se){
Log.i(TAG, se.toString());
}catch (Exception e){
Log.i(TAG, e.toString());
}
}
@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "onConnectionSuspended");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "onConnectionFailed");
}
@Override
public void onLocationChanged(Location recentLoc) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Log.i(TAG, Double.toString(recentLoc.getLongitude()));
listener.onLocationChanged(recentLoc);
}
public void onPause() {
Log.i(TAG, "onPause");
if(mGoogleApiClient.isConnected()) {
Log.i(TAG, "removeLocationUpdates");
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
}
@Override
public void onResume() {
Log.i(TAG, "onResume");
try{
if(mGoogleApiClient.isConnected()){
Log.i(TAG, "requestLocationUpdates");
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}catch (SecurityException se){
Log.i(TAG, se.toString());
}catch (Exception e){
Log.i(TAG, e.toString());
}
}
public void onStop(){
Log.i(TAG, "onStop");
if(mGoogleApiClient.isConnected()) {
Log.i(TAG, "disconnect");
mGoogleApiClient.disconnect();
}
}
}
以及 android 清单文件中的以下权限。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
我正在尝试从后台服务获取位置信息。我使用以下代码从 Activity 启动服务。
Intent serviceIntent = new Intent(this, LocationService.class);
startService(serviceIntent);
这是我的服务代码。
public class LocationService extends Service {
private Thread t;
Looper threadLooper = null;
public int onStartCommand(Intent intent, int flags, int startId){
Log.i("Imp", "Inside service.");
new LooperThread().start();
return Service.START_NOT_STICKY;
}
private void logLocation(String lat, String lng){
//write to database.
}
class LooperThread extends Thread {
public void run() {
Log.i("Imp", "inside thread");
Looper.prepare();
Context context = getApplicationContext();
String svcName = Context.LOCATION_SERVICE;
LocationManager locationManager = (LocationManager) context.getSystemService(svcName);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setSpeedRequired(false);
criteria.setCostAllowed(false);
Log.i("Imp", "Regestring event.");
locationManager.requestSingleUpdate(criteria, locationListener, Looper.myLooper());
Log.i("Imp", "event reg.");
Looper.loop();
stopSelf();
}
}
final LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.i("Imp", "Inside event");
if(location != null){
String lat = Double.toString(location.getLatitude());
String lng = Double.toString(location.getLongitude());
Log.i("Imp", "Lat " + lat);
Log.i("Imp", "lng " + lng);
logLocation(lat, lng);
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
};
}
最初我使用得到错误,因为我为 Looper 对象传递了 null 参数。但是在传递了 looper 对象之后,我没有得到任何错误,但我什至没有得到任何坐标。
我每次 运行 代码时都会收到 event reg.
消息,但由于某种原因它从不调用监听器。
PS :我 运行 在我的 phone 上而不是模拟器上编写代码。
可能您还没有在清单文件中注册该服务。 所有服务都必须由清单文件中的元素表示。任何未在此处声明的内容都不会被系统看到,并且永远不会 运行.
<service android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:isolatedProcess=["true" | "false"]
android:label="string resource"
android:name="string"
android:permission="string"
android:process="string" >
</service>
推荐的方法是使用 Google 播放服务中的位置 API。
添加 google 播放服务依赖。
compile 'com.google.android.gms:play-services:+'
以及以下代码。
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class FusedLocationProvider implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener,
ArchitectViewHolderInterface.ILocationProvider {
private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private LocationListener listener;
private String TAG = "FusedLocationProvider";
public FusedLocationProvider(Context ctx, LocationListener locationListener){
mGoogleApiClient = new GoogleApiClient.Builder(ctx)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
Log.i(TAG, "Connecting...");
this.listener = locationListener;
}
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "onConnected");
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(1000); // Update location every second
try{
if(mGoogleApiClient.isConnected()) {
Log.i(TAG, "requestLocationUpdates");
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}catch (SecurityException se){
Log.i(TAG, se.toString());
}catch (Exception e){
Log.i(TAG, e.toString());
}
}
@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "onConnectionSuspended");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "onConnectionFailed");
}
@Override
public void onLocationChanged(Location recentLoc) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Log.i(TAG, Double.toString(recentLoc.getLongitude()));
listener.onLocationChanged(recentLoc);
}
public void onPause() {
Log.i(TAG, "onPause");
if(mGoogleApiClient.isConnected()) {
Log.i(TAG, "removeLocationUpdates");
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
}
@Override
public void onResume() {
Log.i(TAG, "onResume");
try{
if(mGoogleApiClient.isConnected()){
Log.i(TAG, "requestLocationUpdates");
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}catch (SecurityException se){
Log.i(TAG, se.toString());
}catch (Exception e){
Log.i(TAG, e.toString());
}
}
public void onStop(){
Log.i(TAG, "onStop");
if(mGoogleApiClient.isConnected()) {
Log.i(TAG, "disconnect");
mGoogleApiClient.disconnect();
}
}
}
以及 android 清单文件中的以下权限。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_GPS" />