0

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

[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 !!

M410
  • 301
  • 3
  • 15
  • 2
    what does the stack trace say – tyczj Oct 14 '13 at 16:43
  • 3
    In onSTartCommand() before using the last known location, check it whether it is null or not. Also provide the output/stacktrace in Logcat – ahsanul_k Oct 14 '13 at 16:47
  • I edit my post and add LogCat – M410 Oct 14 '13 at 16:51
  • 2
    `mlocation` is put null check before calling `getLatitude()` and `getLongitude()` methods – ρяσѕρєя K Oct 14 '13 at 16:56
  • 1
    As two of the previous comments have indicated, the last known location WILL be null until such time as the GPS has had a fix, hence the null pointer. – NickT Oct 14 '13 at 17:01
  • so what should i do if its null ? @ahsanul_k – M410 Oct 14 '13 at 17:43
  • 1
    For your current purpose, you can send the SMS from onLocationChange() function. In that case as soon as the location becomes available. To send only once when location is available use a flag to keep track whether you have already sent an SMS. My advice is that you should use the new Location API provided instead of framework location API. The new Location API gives fast access using Fused location provider and drains less power. Check this: http://www.youtube.com/watch?v=Bte_GHuxUGc – ahsanul_k Oct 14 '13 at 18:28
  • i use location updater and solve it tnx – M410 Oct 14 '13 at 20:17

1 Answers1

3

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;
        }
    }
}
}
cYrixmorten
  • 7,110
  • 3
  • 25
  • 33
  • 1
    Hi @NoumanCh. This answer is a bit out of date and today I would recommend using a library such as https://github.com/mcharmas/Android-ReactiveLocation to make use of fused location updates – cYrixmorten Oct 19 '17 at 14:03