13

I have problem with my Android application. I need an application that will send in background GPS location every 10 minutes to the server (here I have WCF service that work). Application needs to send data even if it is closed. So I created a service (for test purposes) that sends to me time on server. But when I insert my code for getting GPS location in my service everything fails (stopped unexpectedly).

I have reed that you need to put some receiver or something but nothing so far works. So I will be very pleased if someone can help me.

  <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.biromatik.GPS"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="4" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".ETMGPSServiceActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:name=".MyApplication" >
    <service
        android:enabled="true"
        android:name=".MonitorService" >
    </service>
    <receiver
        android:enabled="true"
        android:name=".LocationReceiver" >
        <intent-filter >
            <action android:name="com.biromatik.intent.action.LOCATION" />
        </intent-filter>
    </receiver>
</application>


     <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

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




</manifest>
mmBs
  • 8,421
  • 6
  • 38
  • 46
Mihael Meklav
  • 335
  • 2
  • 6
  • 17
  • "my service everything fail (stopped unexpectedly)" -> what's the error you are getting? – Hoff Nov 11 '11 at 14:15
  • In CatLog i get this: 11-11 15:25:49.541: E/AndroidRuntime(229): Uncaught handler: thread main exiting due to uncaught exception – Mihael Meklav Nov 11 '11 at 14:30

1 Answers1

35

I've done this in my app to do the same thing you asked.

In my service I added this:

@Override
public void onStart(Intent intent, int startId) {

    super.onStart(intent, startId);
    addLocationListener();
}

private void addLocationListener()
{
    triggerService = new Thread(new Runnable(){
        public void run(){
            try{
                Looper.prepare();//Initialise the current thread as a looper.
                lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

                Criteria c = new Criteria();
                c.setAccuracy(Criteria.ACCURACY_COARSE);

                final String PROVIDER = lm.getBestProvider(c, true);

                MyLocationListener myLocationListener = new MyLocationListener();
                lm.requestLocationUpdates(PROVIDER, 600000, 0, myLocationListener);
                Log.d("LOC_SERVICE", "Service RUNNING!");
                Looper.loop();
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
    }, "LocationThread");
    triggerService.start();
}

public static void updateLocation(Location location)
{
    Context appCtx = MyApplication.getAppContext();

    double latitude, longitude;

    latitude = location.getLatitude();
    longitude = location.getLongitude();

    Intent filterRes = new Intent();
    filterRes.setAction("xxx.yyy.intent.action.LOCATION");
    filterRes.putExtra("latitude", latitude);
    filterRes.putExtra("longitude", longitude);
    appCtx.sendBroadcast(filterRes);
}


class MyLocationListener implements LocationListener
{

    @Override
    public void onLocationChanged(Location location)
    {
        updateLocation(location);
    }
}

NOTE: See that I use MyApplication.getAppContext(); that's because I'm using my own Application class to add the context. And then I have a BroadcastReceiver with this:

public class LocationReceiver extends BroadcastReceiver {

    double latitude, longitude;

    @Override
    public void onReceive(final Context context, final Intent calledIntent)
    {
        Log.d("LOC_RECEIVER", "Location RECEIVED!");

        latitude = calledIntent.getDoubleExtra("latitude", -1);
        longitude = calledIntent.getDoubleExtra("longitude", -1);

        updateRemote(latitude, longitude);

    }

    private void updateRemote(final double latitude, final double longitude )
    {
        //HERE YOU CAN PUT YOUR ASYNCTASK TO UPDATE THE LOCATION ON YOUR SERVER
    }
}

the Application class:

public class MyApplication extends Application {


    private static Context context;

    /* (non-Javadoc)
     * @see android.app.Application#onCreate()
     */
    @Override
    public void onCreate() {            
        MyApplication.context=getApplicationContext();
    }

    public static Context getAppContext() {
        return MyApplication.context;
    }
}

Also in your manifest you need to add both:

<application
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:name=".MyApplication" >

    //YOUR ACTIVITIES HERE...

    <service
        android:enabled="true"
        android:name=".LocationService" >
    </service>

    <receiver
        android:enabled="true"
        android:name=".LocationReceiver" >
        <intent-filter >
            <action android:name="xxx.yyy.intent.action.LOCATION" />
        </intent-filter>
    </receiver>
</application>

Method to detect if the service is running I do this on my first Activity:

/**
 * Check location service.
 */
private void checkLocationService()
{
    Log.d("CHECK_SERVICE", "Service running: " + (settings.getBoolean("locationService", false)?"YES":"NO"));

    if(settings.getBoolean("locationService", false))
        return;

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

Obviously you need to control the SharedPreferences (settings) to set the locationService variable to true/false if the service is running (onStart) or not (onDestroy).

SERPRO
  • 10,015
  • 8
  • 46
  • 63
  • That looks perfect but i still have problems: this xxx.yyy.intent... what to put instead and i also have problem with that MyApplication.getCOntext(), is there any other way? – Mihael Meklav Nov 11 '11 at 14:52
  • as I said You need to create an class that extends from Application (and add it to your manifest) the xxx.yyy.intent.action.LOCATION can be whatever you want.. like the name of your package and add intent.action.LOCATION to be more specific about it.. I'll edit my answer with the application class – SERPRO Nov 11 '11 at 14:56
  • OK now i get: W/ActivityManager(51): Unable to start service Intent { act=com.biromatik.GPS.MonitorService }: not found. Can you tell me how to start that service now? – Mihael Meklav Nov 11 '11 at 18:33
  • is your service class in the same package as your application? – SERPRO Nov 11 '11 at 19:31
  • post in your question your service class – SERPRO Nov 11 '11 at 23:35
  • Here it is... But as you posted everything is in LocationReciever (for sending GPS location on server). I don't get any error. I just don't know how to turn it on. – Mihael Meklav Nov 12 '11 at 10:51
  • Well you left the xxx.yyy.intent.action.LOCATION on you class if your package is something like com.michael.gpsapp you could call it com.michael.intent.action.LOCATION. That's just to make it more clear.. apart from that.. did you include the service into the Manifest? – SERPRO Nov 14 '11 at 10:04
  • Yes i did. Can you post the part of code where you start that service. – Mihael Meklav Nov 15 '11 at 13:40
  • I added the method I use.. If you want to use the same method.. don't forget to set the value of locationService in your SharedPreferences – SERPRO Nov 15 '11 at 14:03
  • @SERPRO Can you pls tell me how can I start this service? I am not going in for shared preferences nor am I checking if the service is running or not..so apart from the last code section I have taken everything else from your post :D – beerBear Mar 15 '13 at 11:50