Please apologize me if my question is repeated or simple. Struggling in this issue for a long time.
I need to track user's location even when my app is switched to background. On surfing I found that the location processor code can be written as a service, so that the service will not be killed and we can get the user's location (in both status - app in foreground and when app runs in background).
When my app is in foreground, I was able to track user's location continuously. However, when I switched the app to background, I feel my location service dies and I was not able to track user's location. Please find my code below:
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testmylocation"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService"/>
</application>
</manifest>
MainActivity.java:
package com.example.testmylocation;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.Window;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
startService(new Intent(this, MyService.class));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
MyService.java:
package com.example.testmylocation;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
public class MyService extends Service
{
private static final String TAG = "TestMyLocation";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 0;
private static final float LOCATION_DISTANCE = 0;
long itsBatchId = 0;
private class LocationListener implements android.location.LocationListener
{
Location mLastLocation;
public LocationListener(String provider)
{
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location)
{
Thread aThread = new Thread(new Runnable() {
#Override
public void run() {
sendLocationValues(location);
}
});
aThread.start();
}
#Override
public void onProviderDisabled(String provider)
{
Log.e(TAG, "onProviderDisabled: " + provider);
}
#Override
public void onProviderEnabled(String provider)
{
Log.e(TAG, "onProviderEnabled: " + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.e(TAG, "onStatusChanged: " + provider);
}
}
private void sendLocationValues(Location theLocation)
{
//A web service will be called and the user's current location will be stored in server
}
LocationListener[] mLocationListeners = new LocationListener[]
{
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onCreate()
{
initializeLocationManager();
itsLocationHandler.sendEmptyMessage(1);
}
private Handler itsLocationHandler = new Handler()
{
#Override
public void handleMessage(Message theMessage)
{
if(theMessage.what == 1)
{
try
{
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, mLocationListeners[1]);
}
catch (java.lang.SecurityException ex)
{
Log.i(TAG, "fail to request location update, ignore", ex);
}
catch (IllegalArgumentException ex)
{
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
}
}
};
#Override
public void onDestroy()
{
super.onDestroy();
}
private void initializeLocationManager()
{
if (mLocationManager == null)
{
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
}
Can anyone please correct what I am doing wrong.
Thank you.
Since Android 4.0, the OS has gotten much more agressive about killing off unnecessary processes. If you need to track the user's location even when your app is in the background, then you need to declare your service as a foreground service. This raises the priority of your service so that Android is unlikely to kill it unless it really needs the resources. See Running a service in the foreground for details about how to do this.
location processor code can be written as a service, so that the service will not be killed
There is nothing can guarntee that the service will never be killed, however you can increase the likelihood that your service will continue running by obtaining WakeLock and start it as Foreground service
I would recommend you check few open source projects such as Open GPS Tracker and Traceper
Related
I'm trying to run startService() in my android app, but it is not working.
Here is the code from the call to start the service:
Intent mPositioningIntent = new Intent(this, MyGeoloqiPositioning.class);
stopService(mPositioningIntent);
startService(mPositioningIntent);
Here is the code from MyGeoloqiPositioning.java (note, this is taken with minor modifications from the source code of MapAttack)
package com.example.manhunttwopointoh;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.util.Pair;
import android.widget.Toast;
import com.example.manhunttwopointoh.MyFix;
import com.example.manhunttwopointoh.MyGeoloqiFixSocket;
import com.example.manhunttwopointoh.MyUDPClient;
public class MyGeoloqiPositioning extends Service implements LocationListener {
public static final String TAG = "GeoloqiPositioning";
private int batteryLevel = 0;
MyGeoloqiFixSocket fixSocket;
#Override
public void onCreate() {
android.os.Debug.waitForDebugger();
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onCreate()", Toast.LENGTH_LONG).show();
if (isConnected()) {
fixSocket = MyUDPClient.getApplicationClient(this);
} else {
// TODO: This is a crude check. Should probably be rolled into UDPClient class directly.
Log.w(TAG, "Network unavailable! Stopping positioning service.");
stopSelf();
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onStart()", Toast.LENGTH_LONG).show();
registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
for (String provider : ((LocationManager) getSystemService(LOCATION_SERVICE)).getAllProviders()) {
if (!provider.equals("passive")) {
MyADB.log("Registering for updates with " + provider);
((LocationManager) getSystemService(LOCATION_SERVICE)).requestLocationUpdates(provider, 0, 0, this);
}
}
}
public void onStop() {
unregisterReceiver(batteryReceiver);
((LocationManager) getSystemService(LOCATION_SERVICE)).removeUpdates(this);
}
#Override
public void onDestroy() {
unregisterReceiver(batteryReceiver);
((LocationManager) getSystemService(LOCATION_SERVICE)).removeUpdates(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startid) {
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onStartCommand()", Toast.LENGTH_LONG).show();
onStart(intent, startid);
return Service.START_REDELIVER_INTENT;
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onLocationChanged()", Toast.LENGTH_LONG).show();
#SuppressWarnings("unchecked")
MyFix lqLocation = new MyFix(location, new Pair<String, String>("battery", "" + batteryLevel));
if (isConnected()) {
fixSocket.pushFix(lqLocation);
} else {
// TODO: This is a crude check. Should probably be rolled into UDPClient class directly.
Log.w(TAG, "Network unavailable, failed to push location fix!");
}
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
batteryLevel = intent.getIntExtra("level", 0);
}
};
/** Determine if the network is connected and available. */
private boolean isConnected() {
ConnectivityManager manager = (ConnectivityManager) getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
return (activeNetwork != null && activeNetwork.isConnected());
}
}
I tried inserting a breakpoint in MyGeoloqiPositioning, but nothing ever comes of it. I also put various Toast() calls, but still no dice. My GeoloqiPositioning.java is never called. What am I doing wrong?
EDIT:
Here is the new code from the manifest file:
<service
android:name="com.manhunttwopointoh.MyGeoloqiPositioning"
android:enabled="true"
android:exported="false"
android:process=":lqRemote" >
<intent-filter>
<action android:name="com.manhunttwopointoh.MyGeoloqiPositioning" />
</intent-filter>
</service>
I tried adding the intent-filter tags, but still nothing. I also have nothing registering on the logs. Here is the code (commented out stopService()):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_geoloqi);
Intent mPositioningIntent = new Intent(this, MyGeoloqiPositioning.class);
//stopService(mPositioningIntent);
startService(mPositioningIntent);
Toast.makeText(PreyGeoloqi.this, "testing mPositioningIntent: " + mPositioningIntent.toString(), Toast.LENGTH_LONG).show();
}
I still get nothing. Do I need to explicitly call methods in MyPreyGeoloqi.java? I am fairly confused...
Try adding an intent filter your service definition in the AndroidManifest:
<!-- snippet from Android Manifest file -->
<service android:name="com.manhunttwopointoh.MyGeoloqiPositioning" android:enabled="true" android:process=":lqRemote" >
<intent-filter>
<action android:name="com.manhunttwopointoh.MyGeoloqiPositioning" />
</intent-filter>
</service>
This allows your service to receive the intent sent from your Activity.
I have created a very basic program to track GPS coordinates. The program has a button that turns a service on and off. The service simple installs a LocationListener. On each onLocationChanged the location coordinates are dumped on sd card.
The application works fine. But when I push the sleep button, the application logs data for sometime and then causes Google Nexus One to reboot.
Below I am posting the MINIMUM code that is required to reproduce this bug. I have striped extra code to avoid confusion.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.phonetracker"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".PhoneTrackerActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyGPSService" android:process=":my_gps_service" />
</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<Button
android:id="#+id/on_button_click"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="#string/on_button_click"
android:onClick="onButtonClick" />
</LinearLayout>
values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, PhoneTrackerActivity!</string>
<string name="app_name">PhoneTracker</string>
<string name="on_button_click">Start Service</string>
</resources>
PhoneTrackerActivity.java
package com.phonetracker;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class PhoneTrackerActivity extends Activity
{
private static final String TAG = "MyGPSServiceDemoActivity";
private Intent intent = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button = (Button)findViewById(R.id.on_button_click);
if (isMyServiceRunning())
{
button.setText("Stop Service");
}
else
{
button.setText("Start Service");
}
if (intent == null)
intent = new Intent(this, MyGPSService.class);
}
public void onButtonClick(View view)
{
Log.e(TAG, "onButtonClick");
Button button = (Button)view;
if (isMyServiceRunning())
{
stopService(intent);
button.setText("Start Service");
}
else
{
startService(intent);
button.setText("Stop Service");
}
}
private boolean isMyServiceRunning()
{
Log.e(TAG, "isMyServiceRunning");
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
{
if ("com.gpsservicedemo.MyGPSService".equals(service.service.getClassName()))
{
return true;
}
}
return false;
}
}
MyGPSService.java
package com.phonetracker;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.os.IBinder;
import android.util.Log;
public class MyGPSService extends Service
{
private static final String TAG = "Hx2MyGPSService";
private LocationManager locationManager = null;
private GPSLocationListener gpsLocationListener = null;
#Override
public IBinder onBind(Intent arg0)
{
Log.e(TAG, "onBind");
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onCreate()
{
Log.e(TAG, "onCreate");
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
gpsLocationListener = new GPSLocationListener();
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsLocationListener);
}
}
#Override
public void onDestroy()
{
Log.e(TAG, "onDestroy");
super.onDestroy();
if (locationManager != null)
{
try
{
locationManager.removeUpdates(gpsLocationListener);
}
catch (Exception ex)
{
Log.e(TAG, "fail to remove location listners, ignore", ex);
}
}
gpsLocationListener.closeOperations();
}
}
GPSLocationListener.java
package com.phonetracker;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.util.Log;
public class GPSLocationListener implements LocationListener
{
private static final String TAG = "Hx2GPSLocationListener";
public GPSLocationListener ()
{
Log.e(TAG, "GPSLocationListener");
}
#Override
public void onLocationChanged(Location location)
{
Log.e(TAG, "onLocationChanged");
}
#Override
public void onProviderDisabled(String provider)
{
Log.e(TAG, "onProviderDisabled");
}
#Override
public void onProviderEnabled(String provider)
{
Log.e(TAG, "onProviderEnabled");
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.e(TAG, "onStatusChanged");
}
public void closeOperations()
{
Log.e(TAG, "closeOperations");
}
}
Please see if I am missing out something.
I want to pop up the alert dialog on location change through service. Here i have attached my manifest , Service and broadcastReciever codes.
In the console it is giving that .apk has been installed.
But i'm not getting any toast or alertdialog.
PLease correct me if i'm wrong.
Thanks.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ser"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="3" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<receiver android:name="com.ser.Myreceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<service android:enabled="true"
android:name="com.ser.RunService">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</service>
</application>
</manifest>`
package com.ser;
import android.app.AlertDialog;
import android.app.Service;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.os.IBinder;
import android.widget.Toast;
public class RunService extends Service implements LocationListener{
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
System.out.println("**inside onCreate");
super.onCreate();
Toast.makeText(this, "Service Created", Toast.LENGTH_LONG).show();
//Intent call = new Intent(Intent.ACTION_CALL,Uri.parse("tel:+5555"));
//startActivity(call);
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("ALERT")
.setTitle("Location")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
}
#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
}
}
//Reciver
package com.ser;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
//import android.widget.Toast;
//import android.util.Log;
public class Myreceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println("MYRECEIVER");
//Toast.makeText(Myreceiver.this, "MyReciver", Toast.LENGTH_SHORT).show();
Intent serviceLauncher = new Intent(context, RunService.class);
context.startService(serviceLauncher);
//Log.v("TEST", "Service loaded at start");
}
}
create an Activity and and register receiver in this activity and start service from this activity and use alert dialog in activity class
i have modified your code and its working fine with my testing mobile device (sony xperia)
Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ser"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<application android:icon="#drawable/icon" android:label="#string/app_name" android:debuggable="true">
<service android:enabled="true" android:name=".MyService">
<intent-filter>
<action android:name="com.ser.MyService">
</action>
</intent-filter>
</service>
<receiver android:enabled="true" android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED">
</action></intent-filter>
</receiver>
</application>
MyReceiver.java
package com.ser;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "MyReceiver Started..",Toast.LENGTH_SHORT).show();
Log.v("Debug", "MyReceiver Started..");
Intent myIntent=new Intent(context,MyService.class);
context.startService(myIntent);
}
}
MyService.java
package com.ser;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
private LocationManager locManager;
private LocationListener locListener = new myLocationListener();
private boolean gps_enabled = false;
private boolean network_enabled = false;
#Override
public IBinder onBind(Intent intent) {return null;}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
Toast.makeText(getBaseContext(), "Service Started..", Toast.LENGTH_SHORT).show();
Log.v("Debug", "Service Started..");
locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
try{
gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
catch(Exception ex){}
try{
network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
catch(Exception ex){}
if (gps_enabled) {
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener);
Log.v("Debug", "gps_enabled..");
}
if (network_enabled) {
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
Log.v("Debug", "network_enabled..");
}
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
private class myLocationListener implements LocationListener{
#Override
public void onLocationChanged(Location location) {
if(location!=null){
Toast.makeText(getBaseContext(),"on location changed called..",Toast.LENGTH_SHORT).show();
Log.v("Debug", "on location changed method called..");
}
}
#Override
public void onProviderDisabled(String provider) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
}//service closed
still have any doubts for Receiver,Service and GPS classes let me know!!
or even your can check Start Service from Broadcast Receiver and Get Current Location links for details. hope it helps!!
I am trying to log a GPS location while the screen is off.
Here is my manifest file (note the WAKE_LOCK and GPS permissions as well as the LocationService definition):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.joshuajwitter.backgroundgpstest"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk android:minSdkVersion="10" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".BackgroundGPSTestActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".service.LocationService" >
<intent-filter>
<action android:name="com.joshuajwitter.backgroundgpstest.service.LocationService" />
</intent-filter>
</service>
</application>
</manifest>
Here is my background service:
package com.joshuajwitter.backgroundgpstest.service;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
public class LocationService extends Service {
private static final String TAG = "LocationService";
// the location manager and listener
LocationManager m_locationManager;
GPSLocationListener m_gpsLocationListener;
// the dreaded wakelock
WakeLock m_wakeLock;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onStart(Intent intent, int startId) {
Log.d(TAG, "Starting the LocationService");
// acquire the wakelock
Log.d(TAG, "Acquiring the wake lock");
m_wakeLock.acquire();
}
#Override
public void onCreate() {
// get the wakelock
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
m_wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"String Wake Lock");
// instantiate the gps listener
m_gpsLocationListener = new GPSLocationListener();
// get the location manager
m_locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// request location updates every 5 seconds
m_locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
5000, 0, m_gpsLocationListener);
}
#Override
public void onDestroy() {
Log.d(TAG, "Stopping the LocationService");
// if the wakelock is held
if (m_wakeLock.isHeld()) {
// release it
Log.d(TAG, "Releasing the wake lock");
m_wakeLock.release();
}
// remove the listener
m_locationManager.removeUpdates(m_gpsLocationListener);
}
private class GPSLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Got a new location frome the LocationManager [" + location.getLatitude()
+ ", " + location.getLongitude() + "]");
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
}
..and here is the activity that starts and stops the service:
package com.joshuajwitter.backgroundgpstest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.joshuajwitter.backgroundgpstest.service.LocationService;
public class BackgroundGPSTestActivity extends Activity {
private boolean m_serviceRunning = false;
private Button m_mainButton;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// get the main button
m_mainButton = ((Button) findViewById(R.id.mainButton));
// set the main button listener
m_mainButton
.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// if the service is not running
if (!m_serviceRunning) {
// start the service
startService();
}
else {
// start the service
stopService();
}
}
});
}
private void startService() {
m_serviceRunning = true;
startService(new Intent(this, LocationService.class));
m_mainButton.setText("Stop Background GPS Service");
}
private void stopService() {
m_serviceRunning = false;
stopService(new Intent(this, LocationService.class));
m_mainButton.setText("Start Background GPS Service");
}
}
When I run the service and keep the screen on, I get the correct GPS latitude and longitude for my position. When I turn the screen off, however, I get the same repeating output:
01-31 15:48:58.467: D/LocationService(11752): Got a new location frome the LocationManager [-36.879621, -7.734375]
01-31 15:48:59.467: D/LocationService(11752): Got a new location frome the LocationManager [-36.879621, -7.734375]
01-31 15:49:00.467: D/LocationService(11752): Got a new location frome the LocationManager [-36.879621, -7.734375]
01-31 15:49:01.467: D/LocationService(11752): Got a new location frome the LocationManager [-36.879621, -7.734375]
01-31 15:49:02.477: D/LocationService(11752): Got a new location frome the LocationManager [-36.879621, -7.734375]
01-31 15:49:03.477: D/LocationService(11752): Got a new location frome the LocationManager [-36.879621, -7.734375]
01-31 15:49:04.467: D/LocationService(11752): Got a new location frome the LocationManager [-36.879621, -7.734375]
When I turn the screen back on, I get correct GPS values once more. Here's the kicker: Google Maps Navigation runs on my phone with the screen off. If I run it at the same time as my test program, the same behavior occurs... the Navigation app gets notified of the correct coordinates while my test app repeats the same lat/long over and over.
This is on an Android phone running 2.3.3 Gingerbread. Thanks for any input!
I'm trying to create a program for android that constantly (every minute) gets the gps location and then sends it to my server at home (so that i always know where my phone is).
I created a gui with a start-button which starts the service:
start.setOnClickListener(new View.OnClickListener() {
synchronized public void onClick(View v) {
startService(new Intent(GpsTest2.this, GTService.class));
}
});
Then my service is declared like this:
public class GTService extends Service implements LocationListener {
}
This GTService has a method for retrieving the data:
public void onLocationChanged(Location location) {
}
#Override
public void onCreate() {
super.onCreate();
LocationManager locMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, interval * 1000, minDist, this);
}
In AndroidManifest.xml I have:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<service android:name=".GTService">
</service>
This doesn't seem to work: no data is logged.
What am I doing wrong here?
Your code seems to be working fine except this,
You are using LocationManager.NETWORK_PROVIDER
locMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, interval * 1000, minDist, this);
Where as it should be LocationManager.GPS_PROVIDER
locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2 * 1000, 10, locationListener);
Hope this will surely do for you. Thanks.
The location from Network provider is not accurate. PLease use GPS instead. If you really want to user Network only then I would recomond to set minDistance param as 0
The following should work fine,
Manifest :
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.smartconcept.locationmonitor.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".GTService" />
</application>
GTService :
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.widget.Toast;
public class GTService extends Service implements LocationListener {
LocationManager locMgr;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
locMgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1 * 1000, 0, this);
}
#Override
public void onDestroy(){
super.onDestroy();
locMgr.removeUpdates(this);
}
#Override
public void onLocationChanged(Location loc) {
Toast.makeText(getBaseContext(), String.valueOf(loc.getLatitude()) + "\n" + String.valueOf(loc.getLongitude()), Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
}
MainActivity:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnStart = (Button)findViewById(R.id.btnStart);
btnStart.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
startService(new Intent(MainActivity.this,GTService.class));
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
Hope this helps.