如何让应用程序在后台运行? 不断收集数据?

更新在底部

我已经写了一个应用程序,logging用户的位置,当前速度,平均速度和最高速度。 我想知道如何使应用程序做以下事情:

  1. 防止屏幕在屏幕上打开时closures屏幕
  2. 如果用户打开另一个应用程序或返回到主屏幕,获得一个电话等等,应用程序应该继续收集数据(或者每次更新位置时将所有数据写入数据库会更好吗?也许有一个button表示何时开始和停止收集数据?)

这里是我写的代码。 (如果你愿意,可随意使用,如果你有任何build议,我可以改进它,我非常乐意进行build设性的批评:D)

package Hartford.gps; import java.math.BigDecimal; import android.app.Activity; import android.content.Context; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.widget.TextView; public class GPSMain extends Activity implements LocationListener { LocationManager locationManager; LocationListener locationListener; //text views to display latitude and longitude TextView latituteField; TextView longitudeField; TextView currentSpeedField; TextView kmphSpeedField; TextView avgSpeedField; TextView avgKmphField; //objects to store positional information protected double lat; protected double lon; //objects to store values for current and average speed protected double currentSpeed; protected double kmphSpeed; protected double avgSpeed; protected double avgKmph; protected double totalSpeed; protected double totalKmph; //counter that is incremented every time a new position is received, used to calculate average speed int counter = 0; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); run(); } @Override public void onResume() { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, this); super.onResume(); } @Override public void onPause() { locationManager.removeUpdates(this); super.onPause(); } private void run(){ final Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setSpeedRequired(true); criteria.setAltitudeRequired(false); criteria.setBearingRequired(false); criteria.setCostAllowed(true); criteria.setPowerRequirement(Criteria.POWER_LOW); //Acquire a reference to the system Location Manager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); // Define a listener that responds to location updates locationListener = new LocationListener() { public void onLocationChanged(Location newLocation) { counter++; //current speed fo the gps device currentSpeed = round(newLocation.getSpeed(),3,BigDecimal.ROUND_HALF_UP); kmphSpeed = round((currentSpeed*3.6),3,BigDecimal.ROUND_HALF_UP); //all speeds added together totalSpeed = totalSpeed + currentSpeed; totalKmph = totalKmph + kmphSpeed; //calculates average speed avgSpeed = round(totalSpeed/counter,3,BigDecimal.ROUND_HALF_UP); avgKmph = round(totalKmph/counter,3,BigDecimal.ROUND_HALF_UP); //gets position lat = round(((double) (newLocation.getLatitude())),3,BigDecimal.ROUND_HALF_UP); lon = round(((double) (newLocation.getLongitude())),3,BigDecimal.ROUND_HALF_UP); latituteField = (TextView) findViewById(R.id.lat); longitudeField = (TextView) findViewById(R.id.lon); currentSpeedField = (TextView) findViewById(R.id.speed); kmphSpeedField = (TextView) findViewById(R.id.kmph); avgSpeedField = (TextView) findViewById(R.id.avgspeed); avgKmphField = (TextView) findViewById(R.id.avgkmph); latituteField.setText("Current Latitude: "+String.valueOf(lat)); longitudeField.setText("Current Longitude: "+String.valueOf(lon)); currentSpeedField.setText("Current Speed (m/s): "+String.valueOf(currentSpeed)); kmphSpeedField.setText("Cuttent Speed (kmph): "+String.valueOf(kmphSpeed)); avgSpeedField.setText("Average Speed (m/s): "+String.valueOf(avgSpeed)); avgKmphField.setText("Average Speed (kmph): "+String.valueOf(avgKmph)); } //not entirely sure what these do yet public void onStatusChanged(String provider, int status, Bundle extras) {} public void onProviderEnabled(String provider) {} public void onProviderDisabled(String provider) {} }; // Register the listener with the Location Manager to receive location updates locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, locationListener); } //Method to round the doubles to a max of 3 decimal places public static double round(double unrounded, int precision, int roundingMode) { BigDecimal bd = new BigDecimal(unrounded); BigDecimal rounded = bd.setScale(precision, roundingMode); return rounded.doubleValue(); } @Override public void onLocationChanged(Location location) { // TODO Auto-generated method stub } @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 } } 

由Marco Grassi和Marcovena的答案所解决的两个问题都解决了。

新代码:

 package Hartford.gps; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.PowerManager; import android.widget.TextView; public class GPSMain extends Activity { //text views to display latitude and longitude static TextView latituteField; static TextView longitudeField; static TextView currentSpeedField; static TextView kmphSpeedField; static TextView avgSpeedField; static TextView avgKmphField; static TextView topSpeedField; static TextView topKmphField; //objects to store positional information protected static double lat; protected static double lon; //objects to store values for current and average speed protected static double currentSpeed; protected static double kmphSpeed; protected static double avgSpeed; protected static double avgKmph; protected static double totalSpeed; protected static double totalKmph; protected static double topSpeed=0; protected static double topKmph=0; //counter that is incremented every time a new position is received, used to calculate average speed static int counter = 0; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wL = powerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,"My Tag"); wL.acquire(); startService(new Intent(this, Calculations.class)); latituteField = (TextView) findViewById(R.id.lat); longitudeField = (TextView) findViewById(R.id.lon); currentSpeedField = (TextView) findViewById(R.id.speed); kmphSpeedField = (TextView) findViewById(R.id.kmph); avgSpeedField = (TextView) findViewById(R.id.avgspeed); avgKmphField = (TextView) findViewById(R.id.avgkmph); topSpeedField = (TextView) findViewById(R.id.topspeed); topKmphField = (TextView) findViewById(R.id.topkmph); } static void run(){ latituteField.setText("Current Latitude: "+String.valueOf(lat)); longitudeField.setText("Current Longitude: "+String.valueOf(lon)); currentSpeedField.setText("Current Speed (m/s): "+String.valueOf(currentSpeed)); kmphSpeedField.setText("Cuttent Speed (kmph): "+String.valueOf(kmphSpeed)); avgSpeedField.setText("Average Speed (m/s): "+String.valueOf(avgSpeed)); avgKmphField.setText("Average Speed (kmph): "+String.valueOf(avgKmph)); topSpeedField.setText("Top Speed (m/s): "+String.valueOf(topSpeed)); topKmphField.setText("Top Speed (kmph): "+String.valueOf(topKmph)); } } 

 package Hartford.gps; import java.math.BigDecimal; import android.app.Service; import android.content.Context; 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.util.Log; import android.widget.Toast; public class Calculations extends Service implements LocationListener { static LocationManager locationManager; LocationListener locationListener; private static final String TAG = "Calculations"; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show(); Log.d(TAG, "onCreate"); run(); } private void run(){ final Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setSpeedRequired(true); criteria.setAltitudeRequired(false); criteria.setBearingRequired(false); criteria.setCostAllowed(true); criteria.setPowerRequirement(Criteria.POWER_LOW); //Acquire a reference to the system Location Manager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); // Define a listener that responds to location updates locationListener = new LocationListener() { public void onLocationChanged(Location newLocation) { GPSMain.counter++; //current speed for the GPS device GPSMain.currentSpeed = round(newLocation.getSpeed(),3,BigDecimal.ROUND_HALF_UP); GPSMain.kmphSpeed = round((GPSMain.currentSpeed*3.6),3,BigDecimal.ROUND_HALF_UP); if (GPSMain.currentSpeed>GPSMain.topSpeed) { GPSMain.topSpeed=GPSMain.currentSpeed; } if (GPSMain.kmphSpeed>GPSMain.topKmph) { GPSMain.topKmph=GPSMain.kmphSpeed; } //all speeds added together GPSMain.totalSpeed = GPSMain.totalSpeed + GPSMain.currentSpeed; GPSMain.totalKmph = GPSMain.totalKmph + GPSMain.kmphSpeed; //calculates average speed GPSMain.avgSpeed = round(GPSMain.totalSpeed/GPSMain.counter,3,BigDecimal.ROUND_HALF_UP); GPSMain.avgKmph = round(GPSMain.totalKmph/GPSMain.counter,3,BigDecimal.ROUND_HALF_UP); //gets position GPSMain.lat = round(((double) (newLocation.getLatitude())),3,BigDecimal.ROUND_HALF_UP); GPSMain.lon = round(((double) (newLocation.getLongitude())),3,BigDecimal.ROUND_HALF_UP); GPSMain.run(); } //not entirely sure what these do yet public void onStatusChanged(String provider, int status, Bundle extras) {} public void onProviderEnabled(String provider) {} public void onProviderDisabled(String provider) {} }; // Register the listener with the Location Manager to receive location updates locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, locationListener); } //Method to round the doubles to a max of 3 decimal places public static double round(double unrounded, int precision, int roundingMode) { BigDecimal bd = new BigDecimal(unrounded); BigDecimal rounded = bd.setScale(precision, roundingMode); return rounded.doubleValue(); } public void onLocationChanged(Location location) { // TODO Auto-generated method stub } public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } } 

更新为shababhsiddique

 import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.NumberFormat; import android.app.Service; import android.content.Context; 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.util.Log; import android.widget.Toast; public class Calculations extends Service{ static LocationManager locationManager; static LocationListener locationListener; private static long timerTime = 1; private static float timerFloatValue = 1.0f; private Context context; private int counter = 0; @Override public IBinder onBind(Intent intent) {return null;} @Override public void onCreate() { context = this; update(); } protected void update(){ final Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setSpeedRequired(true); criteria.setAltitudeRequired(false); criteria.setBearingRequired(false); criteria.setCostAllowed(true); criteria.setPowerRequirement(Criteria.POWER_LOW); //Acquire a reference to the system Location Manager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); // Define a listener that responds to location updates locationListener = new LocationListener() { public void onLocationChanged(Location newLocation) { counter++; if(GPSMain.GPSHasStarted==0){ GPSMain.previousLocation = newLocation; //gets position GPSMain.lat = round(((double) (GPSMain.previousLocation.getLatitude())),3,BigDecimal.ROUND_HALF_UP); GPSMain.lon = round(((double) (GPSMain.previousLocation.getLongitude())),3,BigDecimal.ROUND_HALF_UP); GPSMain.startingLocation = GPSMain.previousLocation; GPSMain.routeLat.add(Double.toString(GPSMain.startingLocation.getLatitude())); GPSMain.routeLon.add(Double.toString(GPSMain.startingLocation.getLongitude())); GPSMain.startTime = System.currentTimeMillis(); GPSMain.GPSHasStarted++; Toast.makeText(context, "GPS Connection Established", Toast.LENGTH_LONG).show(); startService(new Intent(context, AccelerometerReader.class)); Toast.makeText(context, "Accelerometer Calculating", Toast.LENGTH_LONG).show(); Toast.makeText(context, "Have A Safe Trip!", Toast.LENGTH_LONG).show(); } //gets position GPSMain.lat = round(((double) (newLocation.getLatitude())),3,BigDecimal.ROUND_HALF_UP); GPSMain.lon = round(((double) (newLocation.getLongitude())),3,BigDecimal.ROUND_HALF_UP); if (newLocation.distanceTo(GPSMain.previousLocation)>2.0f){ GPSMain.distanceBetweenPoints = GPSMain.distanceBetweenPoints + newLocation.distanceTo(GPSMain.previousLocation); } //current speed for the GPS device GPSMain.mpsSpeed = newLocation.getSpeed(); if (GPSMain.mpsSpeed>GPSMain.topMps) {GPSMain.topMps=GPSMain.mpsSpeed;} //store location in order to calculate distance during next iteration. GPSMain.previousLocation = newLocation; if (counter % 20 == 0){ GPSMain.routeLat.add(Double.toString(GPSMain.previousLocation.getLatitude())); GPSMain.routeLon.add(Double.toString(GPSMain.previousLocation.getLongitude())); } } //not entirely sure what these do yet public void onStatusChanged(String provider, int status, Bundle extras) {} public void onProviderEnabled(String provider) {} public void onProviderDisabled(String provider) {} }; // Register the listener with the Location Manager to receive location updates locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 20, locationListener); } //Method to round the doubles to a max of 3 decimal places public static double round(double unrounded, int precision, int roundingMode){ BigDecimal bd = new BigDecimal(unrounded); BigDecimal rounded = bd.setScale(precision, roundingMode); return rounded.doubleValue(); } //formats the time taken in milliseconds into hours minutes and seconds public static String getTimeTaken(long end, long start){ @SuppressWarnings("unused") String formattedTime = "", hourHour = "", hourMin = ":", minSec = ":"; long timeTaken = end-start, hour = 0, min = 0, sec = 0; timerTime = timeTaken; timeTaken = (end-start)/1000; if (timeTaken>9 ){ hourHour = "0"; hourMin = ":0"; if (timeTaken>=60){ if (timeTaken>= 3200){ hour = timeTaken/3200; timeTaken = timeTaken%3200; if (hour>9){ hourHour = ""; } } min = timeTaken/60; timeTaken = timeTaken%60; if (min >9){ hourMin = ":"; } } sec = timeTaken; if(sec%60<10){ minSec = ":0"; } return formattedTime = (hourHour+hour+hourMin+min+minSec+sec); } sec = timeTaken; minSec = ":0"; hourMin = ":0"; hourHour = "0"; return formattedTime = (hourHour+hour+hourMin+min+minSec+sec); } public static double averageSpeed(){ //calculates average speed if (timerTime==0){timerTime=1;} timerFloatValue = (float) timerTime; timerFloatValue = timerFloatValue/1000; return GPSMain.avgMps = GPSMain.distanceBetweenPoints/timerFloatValue; } //rounds the float values from the accelerometer static String roundTwoDecimalFloat(float a){ float b = a/9.8f; String formattedNum; NumberFormat nf = new DecimalFormat(); nf.setMaximumFractionDigits(2); nf.setMinimumFractionDigits(2); formattedNum = nf.format(b); return formattedNum; } } 

问题1:您必须获得一个WakeLock 。 有多种types的wakelock,取决于你是否只想要CPU或屏幕。

问题2:您应该在服务内部收集数据内容,并将graphics界面与收集数据分开。 该服务将继续收集数据,直到您停止它,如果您正确实施。