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>
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.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With