定位服务 GPS 强制关闭
Posted
技术标签:
【中文标题】定位服务 GPS 强制关闭【英文标题】:Location service GPS Force closed 【发布时间】:2013-10-22 07:14:46 【问题描述】:您好,我开发了一个应用程序来定位最佳位置并将其发送到一个号码。它在网络位置上工作正常,但是当我想用 GPS 或 Criteria 类定位时,它会强制关闭! 真好,你帮我 tnx。
package ir.M410.toolkit;
import android.app.Service;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.telephony.SmsManager;
import android.util.Log;
public class LocationFinder extends Service implements LocationListener
double lat ,lon ;
@Override
public IBinder onBind(Intent arg0)
return null;
@Override
public int onStartCommand(Intent intent, int flags, int startId)
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
LocationManager mlocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_MEDIUM);
String locationprovider = mlocationManager.getBestProvider(criteria, true);
Location mlocation = mlocationManager.getLastKnownLocation(locationprovider);
lat = mlocation.getLatitude ();
lon = mlocation.getLongitude ();
Log.i("Geo_Location", "Latitude: " + lat + ", Longitude: " + lon);
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage("+11231233213", null,"https://maps.google.com/maps?q="+lat+","+lon, null, null);
// SmsManager sms = SmsManager.getDefault();
//sms.sendTextMessage(MainActivity.senderNum, null," "+"lat:"+lat+" "+"lon:"+lon, null, null);
//stopSelf();
return START_NOT_STICKY;
@Override
public void onLocationChanged(Location location)
// TODO Auto-generated method stub
lat= location.getLatitude();
lon =location.getLongitude();
Log.i("Geo_Location", "Latitude: " + lat + ", Longitude: " + lon);
// stopSelf();
@Override
public void onProviderDisabled(String provider)
// TODO Auto-generated method stub
@Override
public void onProviderEnabled(String provider)
// TODO Auto-generated method stub
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
// TODO Auto-generated method stub
@Override
public void onDestroy()
super.onDestroy();
这是我的清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ir.M410.toolkit"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.RECEIVE_SMS" >
</uses-permission>
<uses-permission android:name="android.permission.READ_SMS" >
</uses-permission>
<uses-permission android:name="android.permission.SEND_SMS" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" >
</uses-permission>
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name="ir.M410.toolkit.Broadcast_Receiver" >
<intent-filter android:priority="2147483647" >
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="ir.M410.toolkit.android.action.broadcast" />
</intent-filter>
</receiver>
<service android:name="ir.M410.toolkit.LocationFinder" />
<activity
android:name="ir.M410.toolkit.PasswordCheck"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="ir.M410.toolkit.MainActivity"
android:label="@string/title_activity_main"
android:screenOrientation="portrait" >
</activity>
<activity
android:name="ir.M410.toolkit.Teturial"
android:label="@string/title_activity_teturial" >
</activity>
<activity
android:name="ir.M410.toolkit.CallDivertActivity"
android:label="@string/title_activity_call_divert" >
</activity>
</application>
</manifest>
[已编辑]这里是 LogCat 定义:
10-14 19:58:37.823: E/AndroidRuntime(2685): FATAL EXCEPTION: main
10-14 19:58:37.823: E/AndroidRuntime(2685): java.lang.RuntimeException: Unable to start service ir.M410.toolkit.LocationFinder@4482e4a8 with Intent cmp=ir.M410.toolkit/.LocationFinder : java.lang.NullPointerException
10-14 19:58:37.823: E/AndroidRuntime(2685): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3260)
10-14 19:58:37.823: E/AndroidRuntime(2685): at android.app.ActivityThread.access$3600(ActivityThread.java:135)
10-14 19:58:37.823: E/AndroidRuntime(2685): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2205)
10-14 19:58:37.823: E/AndroidRuntime(2685): at android.os.Handler.dispatchMessage(Handler.java:99)
10-14 19:58:37.823: E/AndroidRuntime(2685): at android.os.Looper.loop(Looper.java:143)
10-14 19:58:37.823: E/AndroidRuntime(2685): at android.app.ActivityThread.main(ActivityThread.java:4914)
10-14 19:58:37.823: E/AndroidRuntime(2685): at java.lang.reflect.Method.invokeNative(Native Method)
10-14 19:58:37.823: E/AndroidRuntime(2685): at java.lang.reflect.Method.invoke(Method.java:521)
10-14 19:58:37.823: E/AndroidRuntime(2685): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
10-14 19:58:37.823: E/AndroidRuntime(2685): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
10-14 19:58:37.823: E/AndroidRuntime(2685): at dalvik.system.NativeStart.main(Native Method)
10-14 19:58:37.823: E/AndroidRuntime(2685): Caused by: java.lang.NullPointerException
10-14 19:58:37.823: E/AndroidRuntime(2685): at ir.M410.toolkit.LocationFinder.onStartCommand(LocationFinder.java:38)
10-14 19:58:37.823: E/AndroidRuntime(2685): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3246)
10-14 19:58:37.823: E/AndroidRuntime(2685): ... 10 more
[编辑] 代码检查不为空:
@Override
public int onStartCommand(Intent intent, int flags, int startId)
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
LocationManager mlocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_MEDIUM);
String locationprovider = mlocationManager.getBestProvider(criteria, true);
if(mlocationManager.getLastKnownLocation(locationprovider)!=null)
Location mlocation = mlocationManager.getLastKnownLocation(locationprovider);
lat = mlocation.getLatitude ();
lon = mlocation.getLongitude ();
Log.i("Geo_Location", "Latitude: " + lat + ", Longitude: " + lon);
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage("+11231233213", null,"https://maps.google.com/maps?q="+lat+","+lon, null, null);
它没问题,没有强制关闭,但没有收到数据,它总是为空!!
【问题讨论】:
堆栈跟踪说明了什么 在 onSTartCommand() 使用最后一个已知位置之前,检查它是否为空。还要在 Logcat 中提供输出/堆栈跟踪mlocation
在调用 getLatitude()
和 getLongitude()
方法之前进行空检查
正如前面两个 cmets 所指出的,在 GPS 定位之前,最后一个已知位置将为空,因此是空指针。
为了您当前的目的,您可以通过 onLocationChange() 函数发送短信。在这种情况下,只要该位置可用。要在位置可用时仅发送一次,请使用标志来跟踪您是否已经发送了 SMS。我的建议是您应该使用提供的新位置 API 而不是框架位置 API。新的位置 API 使用 Fused 位置提供程序提供快速访问并消耗更少的电量。检查这个:youtube.com/watch?v=Bte_GHuxUGc
【参考方案1】:
我已经从http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial/实现了我自己版本的 GPSTracker 类
使用此功能,您可以打开 GPS 并在有效位置可用时立即接收回叫。这可能需要一点时间,具体取决于设备的位置,但会提供更精确和可靠的位置。
通过我的实现,您可以执行以下操作:
private GPSTracker gps;
private FirstFixListener firstFixListener;
private LocationUpdateListener locationUpdateListener;
private void sendGPStoSMS()
gps = GPSTracker.getInstance(context);
firstFixListener = new MyFirstFixListener();
locationUpdateListener = new MyLocationUpdateListener();
gps.startUsingGPS(firstFixListener, locationUpdateListener);
private class MyFirstFixListener implements FirstFixListener
@Override
public void onFirsFixChanged(boolean hasGPSfix)
if (hasGPSfix == true)
Location position = gps.getLocation();
// send SMS with position
// stop the gps and unregister callbacks
gps.stopUsingGPS(firstFixListener, locationUpdateListener);
private class MyLocationUpdateListener implements LocationUpdateListener
@Override
public void onLocationChanged(Location location)
// hand you each new location from the GPS
// you do not need this as you only want to send a single position
这是我的 GPSTracker 实现:
public class GPSTracker extends Service implements LocationListener
private static final String TAG = "GPSTracker";
/**
* Register to receive callback on first fix status
*
* @author Morten
*
*/
public interface FirstFixListener
/**
* Is called whenever gps register a change in first-fix availability
* This is valuable to prevent sending invalid locations to the server.
*
* @param hasGPSfix
*/
public void onFirsFixChanged(boolean hasGPSfix);
/**
* Register to receive all location updates
*
* @author Morten
*
*/
public interface LocationUpdateListener
/**
* Is called every single time the GPS unit register a new location
* The location param will never be null, however, it can be outdated if hasGPSfix is not true.
*
* @param location
*/
public void onLocationChanged(Location location);
private Context mContext;
// flag for GPS status
private List<FirstFixListener> firstFixListeners;
private List<LocationUpdateListener> locationUpdateListeners;
boolean isGPSFix = false;
boolean isGPSEnabled = false;
private GPSFixListener gpsListener;
// flag for GPS status
boolean canGetLocation = false;
Location location; // location
double latitude; // latitude
double longitude; // longitude
long mLastLocationMillis;
private boolean logLocationChanges;
// Declaring a Location Manager
protected LocationManager locationManager;
/** removed again as we need multiple instances with different callbacks **/
private static GPSTracker instance;
public static GPSTracker getInstance(Context context)
if (instance != null)
return instance;
return instance = new GPSTracker(context);
private GPSTracker(Context context)
this.mContext = context;
gpsListener = new GPSFixListener();
firstFixListeners = new ArrayList<GPSTracker.FirstFixListener>();
locationUpdateListeners = new ArrayList<GPSTracker.LocationUpdateListener>();
public boolean hasGPSFirstFix()
return isGPSFix;
private void addFirstFixListener(FirstFixListener firstFixListener)
this.firstFixListeners.add(firstFixListener);
private void addLocationUpdateListener(
LocationUpdateListener locationUpdateListener)
this.locationUpdateListeners.add(locationUpdateListener);
private void removeFirstFixListener(FirstFixListener firstFixListener)
this.firstFixListeners.remove(firstFixListener);
private void removeLocationUpdateListener(
LocationUpdateListener locationUpdateListener)
this.locationUpdateListeners.remove(locationUpdateListener);
public void setLogLocationChanges(boolean logLocationChanges)
this.logLocationChanges = logLocationChanges;
public Location getLocation()
return location;
private Location startLocationListener()
canGetLocation = false;
try
locationManager = (LocationManager) mContext
.getSystemService(Service.LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isGPSEnabled)
if (location == null)
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, this);
locationManager.addGpsStatusListener(gpsListener);
if (locationManager != null)
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null)
latitude = location.getLatitude();
longitude = location.getLongitude();
else
showSettingsAlert();
catch (Exception e)
e.printStackTrace();
return location;
public void stopUsingGPS(FirstFixListener firstFixListener,
LocationUpdateListener locationUpdateListener)
if (firstFixListener != null)
removeFirstFixListener(firstFixListener);
if (locationUpdateListener != null)
removeLocationUpdateListener(locationUpdateListener);
stopUsingGPS();
/**
* Stop using GPS listener Calling this function will stop using GPS in your
* app
* */
public void stopUsingGPS()
Log.d("DEBUG", "GPS stop");
if (locationManager != null)
locationManager.removeUpdates(GPSTracker.this);
location = null;
if (gpsListener != null)
locationManager.removeGpsStatusListener(gpsListener);
isGPSFix = false;
location = null;
public void startUsingGPS(FirstFixListener firstFixListener,
LocationUpdateListener locationUpdateListener)
Log.d("DEBUG", "GPS start");
if (firstFixListener != null)
addFirstFixListener(firstFixListener);
if (locationUpdateListener != null)
addLocationUpdateListener(locationUpdateListener);
startLocationListener();
/**
* Function to get latitude
* */
public double getLatitude()
if (location != null)
latitude = location.getLatitude();
else
Log.e("GPSTracker", "getLatitude location is null");
// return latitude
return latitude;
/**
* Function to get longitude
* */
public double getLongitude()
if (location != null)
longitude = location.getLongitude();
else
Log.e("GPSTracker", "getLongitude location is null");
// return longitude
return longitude;
/**
* Function to check GPS/wifi enabled
*
* @return boolean
* */
public boolean canGetLocation()
return this.canGetLocation;
/**
* Function to show settings alert dialog On pressing Settings button will
* lauch Settings Options
* */
public void showSettingsAlert()
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS settings");
// Setting Dialog Message
alertDialog
.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings",
new DialogInterface.OnClickListener()
public void onClick(DialogInterface dialog, int which)
Intent intent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
);
// on pressing cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener()
public void onClick(DialogInterface dialog, int which)
dialog.cancel();
);
// Showing Alert Message
alertDialog.show();
@Override
public void onLocationChanged(Location location)
if ( location == null)
return;
this.location = location;
mLastLocationMillis = SystemClock.elapsedRealtime();
canGetLocation = true;
if (isGPSFix)
if (locationUpdateListeners != null)
for (LocationUpdateListener listener : locationUpdateListeners)
listener.onLocationChanged(location);
@Override
public void onProviderDisabled(String provider)
canGetLocation = false;
@Override
public void onProviderEnabled(String provider)
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
@Override
public IBinder onBind(Intent arg0)
return null;
private boolean wasGPSFix = false;
// http://***.com/questions/2021176/how-can-i-check-the-current-status-of-the-gps-receiver
// answer from soundmaven
private class GPSFixListener implements GpsStatus.Listener
public void onGpsStatusChanged(int event)
switch (event)
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;
if (isGPSFix != wasGPSFix) // only notify on changes
wasGPSFix = isGPSFix;
for (FirstFixListener listener : firstFixListeners)
listener.onFirsFixChanged(isGPSFix);
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
// Do something.
break;
【讨论】:
嗨@NoumanCh。这个答案有点过时了,今天我建议使用诸如github.com/mcharmas/Android-ReactiveLocation 之类的库来利用融合位置更新以上是关于定位服务 GPS 强制关闭的主要内容,如果未能解决你的问题,请参考以下文章