Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Background service needs to send GPS location on server

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>
like image 701
Mihael Meklav Avatar asked Nov 11 '11 14:11

Mihael Meklav


People also ask

Why does your app need access to location in the background?

If your app uses location in the background, your privacy policy must contain appropriate related disclosures, reference location data, and provide information about the app's usage of location data. Ensure your privacy policy page is clearly labeled as such in the title or URL and within the body of the page.

How do I turn on GPS background?

In order to enable background location access, users must set the Allow all the time option for your app's location permission on a settings page, as described in the guide on how to Request background location.


1 Answers

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

like image 90
SERPRO Avatar answered Sep 22 '22 14:09

SERPRO