android

listener

location

gps

service

Hi i develop an app to locate best location and SMS it to a number . its work fine with network location , but when i want to locating with GPS or Criteria class its become force closed !! its so kind of you to help me 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();

}
}

and this is my manifest:

<?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>

[Edited]and here is LogCat definition :

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 [email protected] 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

[Edited] code to check not be 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);
    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);

    }

and its ok and not get force close but no data received its always is null !!

Solution 1

I have implemented my own version of the GPSTracker class from http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial/

Using this you can turn on the GPS and receive a callback as soon as a valid location is available. This might take a little while depending on the location of the device but will give a much more precise and reliable position.

With my implementation you can do something like this:

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

    }

}

And here is my implementation of 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://stackoverflow.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;
        }
    }
}
}