android - 即使在终止应用程序后仍运行的 Android 服务
问题描述
我正在使用我们通过使用回调方法 onLocation 获取 GPS 位置的服务。Android 服务每 3 秒被调用一次。现在我想运行服务,即使应用程序从后台被清除或杀死。
在 onStartCommand 我们返回 START_STICKY 但服务 onStartCommand 在清除/杀死应用程序后没有被调用。
解决方案
public class GPSBackgroundService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
public static final String POLL_FREQUENCY = "frequency";
public static final String INITIATED_BY = "initiatedBy";
public static final String INITIATED_SCREEN = "initiated_screen";
ServiceComponent serviceComponent;
//public LocationManager locationManager;
GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
static Location previousPosition = null;
double preLatitude, preLongitude;
boolean haveLocationPermissionAccess = false, trackStoredLocally = false;
String presentLat = "", presentLon = "";
float totalDistTravelled = 0f;
String dist_travelled = "0", previousDist = "", currentDate = "";
int pollFrequency = 10000;
String speed_calculated = "0.0";
PreferencesHelper mPreferenceHelper;
long preLongTime = 0L;
//handler to update bunch of points in interval seq.
Handler bulkLatLngThroughputManager;
Runnable bulkLatLngThroughputEmployee;
SimpleDateFormat mdformat;
int notificationId = 5173;
NotificationManager notificationManager = null;
/*NotificationManagerCompat notificationManager = null;*/
Notification notification = null;
NotificationCompat.Builder notificationBuilder = null;
String dist = "0.0", text = "";
int count = 0, countForTrackPoints = 0;
static Location currentLocation;
boolean allowForAnotherTrackCall= true;// =true for allowance and =false for dis allowance
int success = 0,fail = 0,init = 0,dbs = 0,dbf = 0, rls=0;
Intent requirementsOfListFragment,requirementsOfMapFragment;
String initiatedBy = "";
static String initiatedScreen = "";
String channelId = "",channelName = "";
Double dist_temp = 0d;
public static boolean allowNetworkCall = true;
@Override
public void onCreate() {
super.onCreate();
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " onCreate called=" + totalDistTravelled, "abc.txt");
ConfigPersistentComponent configPersistentComponent = DaggerConfigPersistentComponent.builder()
.applicationComponent(SuprabhatApplication.get(getApplicationContext()).getComponent())
.build();
serviceComponent = configPersistentComponent.serviceComponent(new ServiceModule(this));
serviceComponent.inject(this);
mPresenter.attachView(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " onStartCOMMAND called=" + totalDistTravelled, "abc.txt");
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? createNotificationChannel(notificationManager) : "";
notificationBuilder = new NotificationCompat.Builder(this);
notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(PRIORITY_MAX)
.setContentText("Live tracking in progress...!")
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setChannelId(channelId)
.build();
notification.flags = Notification.FLAG_ONLY_ALERT_ONCE;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(notificationId, notification);
}
notificationManager.notify(notificationId, notification);
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " onStartCOMMAND Leaving=" + totalDistTravelled, "abc.txt");
return START_STICKY;
}
@RequiresApi(Build.VERSION_CODES.O)
private String createNotificationChannel(NotificationManager notificationManager) {
channelId = "my_service_channelid";
channelName = "My Foreground Service";
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
// omitted the LED color
channel.setImportance(NotificationManager.IMPORTANCE_LOW);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
notificationManager.createNotificationChannel(channel);
return channelId;
}
@Override
public void onStart(Intent intent, int startId) {
Log.i("onStart","onStart called");
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " onStart called=" + totalDistTravelled, "abc.txt");
pollFrequency = intent.getIntExtra(POLL_FREQUENCY, pollFrequency);
initiatedBy = intent.getStringExtra(INITIATED_BY);
initiatedScreen = intent.getStringExtra(INITIATED_SCREEN);
countForTrackPoints = mPresenter.getTrackLastCount();
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " onStart FieldStaffTrans Count="+String.valueOf(countForTrackPoints), "abc.txt");
// Create the Foreground Service
currentDate = CommonUtils.getCurrentDate();
bulkLatLngThroughputManager = new Handler();
bulkLatLngThroughputEmployee = new Runnable() {
@Override
public void run() {
sendTrackedPointsToRemoteLoc(initiatedScreen);
allowForAnotherTrackCall = false;
bulkLatLngThroughputManager.postDelayed(bulkLatLngThroughputEmployee, pollFrequency);
}
};
mdformat = new SimpleDateFormat("HH:mm:ss");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
// stopSelf();
return;
}
haveLocationPermissionAccess = true;
if (mPresenter != null) {
totalDistTravelled = mPresenter.getTrackDistanceTravelled();
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " onStart Started SHREDPREF totalDistTravelled="+String.valueOf(countForTrackPoints),"abcDistance.txt");
dist_travelled = mPresenter.getTrackDistanceCalculated();
}
buildGoogleApiClient();
/*locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);*/
bulkLatLngThroughputManager.postDelayed(bulkLatLngThroughputEmployee, pollFrequency);
requirementsOfListFragment = new Intent(CustomersInListFragment.GET_UPDATED_LOCATION_INFO);
requirementsOfMapFragment = new Intent(CustomersOnMapFragment.GET_UPDATED_LOCATION_INFO);
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " onStart after buildGoogleApiClient called=" + totalDistTravelled, "abc.txt");
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(3000);
mLocationRequest.setFastestInterval(3000 / 2);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mGoogleApiClient.connect();
}
public void sendTrackedPointsToRemoteLoc(String initiatedScreenLocal) {
//Toast.makeText(SuprabhatApplication.getInstance(), "sendTrackedPointsToRemoteLoc called " + CommonUtils.getCurrentDateInYYYYMMDDFormat(), Toast.LENGTH_SHORT).show();
initiatedScreen = initiatedScreenLocal;
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " sendTrackedPointsToRemoteLoc called InitiatedScr=" + initiatedScreenLocal + " totalDistTravelled=" + totalDistTravelled, "abc.txt");
if (allowNetworkCall) {
ArrayList<LatLngHolder> latLngHolderArrayList = new ArrayList<>();
ArrayList<LatLngHolder> trackedPoints = mPresenter.getAllFSRTrackedRecords(currentDate);
if (trackedPoints.size() > 0) {
trackStoredLocally = true;
latLngHolderArrayList.addAll(trackedPoints);
rls = trackedPoints.size();
}
if (presentLat != null && presentLon != null && !presentLat.isEmpty() && !presentLon.isEmpty()) {
if(countForTrackPoints > mPresenter.getTrackLastCount())
countForTrackPoints += 1;
else {
countForTrackPoints = mPresenter.getTrackLastCount();
countForTrackPoints += 1;
}
//dist_temp += 100;
LatLngHolder holder = new LatLngHolder(presentLat, presentLon, dist_travelled, speed_calculated, "", String.valueOf(countForTrackPoints), "Live");
//LatLngHolder holder = new LatLngHolder(presentLat, presentLon, String.valueOf(dist_temp), speed_calculated, "", String.valueOf(countForTrackPoints), "Live");
latLngHolderArrayList.add(holder);
if (latLngHolderArrayList.size() > 1) {
mPresenter.sendTrackedPoints(latLngHolderArrayList, initiatedBy);
} else if (latLngHolderArrayList.size() > 0) {
String strServerSentLattitude = mPresenter.getServerSentLattitude();
String strServerSentLongitude = mPresenter.getServerSentLongitude();
Double serverSentLatt,serverSentLong;
if (strServerSentLattitude ==null || strServerSentLongitude == null) {
serverSentLatt = currentLocation.getLatitude();
serverSentLong = currentLocation.getLongitude();
mPresenter.setServerSentLattitude(String.valueOf(serverSentLatt));
mPresenter.setServerSentLongitude(String.valueOf(serverSentLong));
mPresenter.sendTrackedPoints(latLngHolderArrayList, initiatedBy);
} else {
serverSentLatt = Double.parseDouble(mPresenter.getServerSentLattitude());
serverSentLong = Double.parseDouble(mPresenter.getServerSentLongitude());
float[] results = new float[1];
Location.distanceBetween(
serverSentLatt, serverSentLong,
currentLocation.getLatitude(), currentLocation.getLongitude(), results);
float difference = results[0];
/* mPresenter.sendTrackedPoints(latLngHolderArrayList,initiatedBy);
/* mPresenter.sendTrackedPoints(latLngHolderArrayList,initiatedBy);
previousLocation = currentLocation;*/
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " sendTrackedPoints serverSentLatt="+serverSentLatt, "abc.txt");
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " sendTrackedPoints serverSentLong="+serverSentLong, "abc.txt");
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " sendTrackedPoints currentPosition.getLatitude()="+currentLocation.getLatitude(), "abc.txt");
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " sendTrackedPoints currentPosition.getLongitude()="+currentLocation.getLongitude(), "abc.txt");
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " sendTrackedPoints calulated distanceDiff=" + difference, "abc.txt");
if (difference >= 40) {//40
mPresenter.setServerSentLattitude(String.valueOf(currentLocation.getLatitude()));
mPresenter.setServerSentLongitude(String.valueOf(currentLocation.getLongitude()));
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " InitiatingToHitServer>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + difference, "abc.txt");
mPresenter.sendTrackedPoints(latLngHolderArrayList, initiatedBy);
//preLatitude = currentLocation.getLatitude();
//preLongitude = currentLocation.getLongitude();
} else {
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " sendTrackedPointsToRemoteLoc distanceLesssThen40=" + initiatedScreenLocal + " totalDistTravelled=" + totalDistTravelled, "abc.txt");
countForTrackPoints -= 1;
}
//mPresenter.sendTrackedPoints(latLngHolderArrayList);
}
}
/*++init;
notificationBuilder.setContentText("i: " + init + " s: " + success + " f: " + fail + " dbs: " + dbs+" dbf: "+dbf+" rls "+rls);
notificationManager.notify(notificationId, notificationBuilder.build());*/
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
// n/w calls status illuminators
@Override
public void onSendingBulkTrackedPoints(FieldStaffPositionBackgroundPresenter.FieldNotesStartOrStopResultsCarrier resultsCarrier) {
int tempTrackedPointsStrd = mPresenter.getTrackLastCount();
if (tempTrackedPointsStrd < countForTrackPoints)
mPresenter.storeTrackCurrentCount(countForTrackPoints);
count++;
if (trackStoredLocally) {
//clear all local storage tracks
mPresenter.deleteAllFsrStoredTracks();
trackStoredLocally = false;
}
if (resultsCarrier.getStopLiveTracking().equalsIgnoreCase("Y")) {
mPresenter.storeTrackDistanceCalculated("0");
mPresenter.storeTrackDistanceTravelled(0f);
bulkLatLngThroughputManager.removeCallbacks(bulkLatLngThroughputEmployee);
// this.stopSelf();
} else {
}
allowForAnotherTrackCall = true;
/*++success;
notificationBuilder.setContentText("i: "+init+" s: "+success+" f: "+fail+" dbs: "+dbs+" dbf: "+dbf+" rls "+rls);
notificationManager.notify(notificationId,notificationBuilder.build());*/
}
@Override
public void onTrackPointsSendingError(String exception) {
mPresenter.storeTrackCurrentCount(countForTrackPoints);
mPresenter.storeFailedTrackInLocal(presentLat, presentLon, dist_travelled, speed_calculated, currentDate, mdformat.format(new Time(System.currentTimeMillis())), String.valueOf(countForTrackPoints));
//bulkLatLngThroughputManager.postDelayed(bulkLatLngThroughputEmployee,pollFrequency);
allowForAnotherTrackCall = true;
//FieldStaffPositionBackgroundTransmitter.writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " onTrackPointsSendingError " + exception,"respnse.txt");
/*++fail;
notificationBuilder.setContentText("i: "+init+" s: "+success+" f: "+fail+" dbs: "+dbs+" dbf: "+dbf+" rls "+rls);
notificationManager.notify(notificationId,notificationBuilder.build());*/
}
@Override
public void onTrackPointsSendingFailure(int statusCode, String message) {
mPresenter.storeTrackCurrentCount(countForTrackPoints);
mPresenter.storeFailedTrackInLocal(presentLat, presentLon, dist_travelled, speed_calculated, currentDate, mdformat.format(new Time(System.currentTimeMillis())), String.valueOf(countForTrackPoints));
//bulkLatLngThroughputManager.postDelayed(bulkLatLngThroughputEmployee,pollFrequency);
allowForAnotherTrackCall = true;
/*++fail;
notificationBuilder.setContentText("i: "+init+" s: "+success+" f: "+fail+" dbs: "+dbs+" dbf: "+dbf+" rls "+rls);
notificationManager.notify(notificationId,notificationBuilder.build());*/
//FieldStaffPositionBackgroundTransmitter.writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " onTrackPointsSendingFailure " + message,"respnse.txt");
}
@Override
public void onLocalStorageOfTrackSuccess() {
/*++dbs;
notificationBuilder.setContentText("i: "+init+" s: "+success+" f: "+fail+" dbs: "+dbs+" dbf: "+dbf+" rls "+rls);
notificationManager.notify(notificationId,notificationBuilder.build());*/
}
@Override
public void onLocalStorageOfTrackFailed(String exception) {
/*++dbf;
notificationBuilder.setContentText("i: "+init+" s: "+success+" f: "+fail+" dbs: "+dbs+" dbf: "+dbf+" rls "+rls);
notificationManager.notify(notificationId,notificationBuilder.build());*/
}
public void writeDataToFile(String highestScore, String fileName) {
try {
// if (mPresenter.getFFAEnableLogging().equals("Y")) {
File data = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator);
File file = new File(data, fileName);
BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));
bw.write(String.valueOf(highestScore));
//bw.append(String.valueOf(highestScore));
bw.close();
// }
} catch (IOException e) {
e.printStackTrace();
}
}
//location related predefined helpers
@Override
public void onLocationChanged(Location location) {
if (location != null ) {
currentLocation = location;
requirementsOfListFragment.putExtra(CustomersInListFragment.PLOFS, presentLon);
requirementsOfListFragment.putExtra(CustomersInListFragment.DCFS, dist_travelled);
requirementsOfListFragment.putExtra(CustomersInListFragment.SCFS, speed_calculated);
requirementsOfListFragment.putExtra(CustomersInListFragment.TDTFS,totalDistTravelled);
LocalBroadcastManager.getInstance(this).sendBroadcast(requirementsOfListFragment);
requirementsOfMapFragment.putExtra(CustomersOnMapFragment.PLAFS, presentLat);
requirementsOfMapFragment.putExtra(CustomersOnMapFragment.PLOFS, presentLon);
requirementsOfMapFragment.putExtra(CustomersOnMapFragment.DCFS, dist_travelled);
requirementsOfMapFragment.putExtra(CustomersOnMapFragment.SCFS, speed_calculated);
requirementsOfMapFragment.putExtra(CustomersOnMapFragment.PLADFS,lat);
requirementsOfMapFragment.putExtra(CustomersOnMapFragment.PLODFS,lon);
requirementsOfMapFragment.putExtra(CustomersOnMapFragment.TDTFS,totalDistTravelled);
requirementsOfMapFragment.putExtra(CustomersOnMapFragment.CLBR,location.getBearing());
LocalBroadcastManager.getInstance(this).sendBroadcast(requirementsOfMapFragment);
//++dbs;
//notificationBuilder.setContentText("i: "+init+" s: "+success+" f: "+fail+" dbs: "+dbs);
//notificationManager.notify(notificationId,notificationBuilder.build());
} catch (Exception e) {
e.printStackTrace();
}
} else {
}
}
/*@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
*//*Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);*//*
}*/
public void adamantForceCloseOfService()
{
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
if (bulkLatLngThroughputManager != null && bulkLatLngThroughputEmployee != null) {
bulkLatLngThroughputManager.removeCallbacks(bulkLatLngThroughputEmployee);
}
/*if (locationManager!=null)
{
locationManager.removeUpdates(this);
}*/
if (notificationManager != null) {
notificationManager.cancel(notificationId);
}
// stopSelf();
}
@Override
public void onDestroy() {
/* writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " Service On onDestroyCalled", "abc.txt");
if (bulkLatLngThroughputManager != null && bulkLatLngThroughputEmployee != null) {
bulkLatLngThroughputManager.removeCallbacks(bulkLatLngThroughputEmployee);
}
*//*if (locationManager!=null)
{
locationManager.removeUpdates(this);
}*//*
if (notificationManager != null) {
notificationManager.cancel(notificationId);
notificationManager.cancelAll();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.deleteNotificationChannel(channelId);
}
}
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
stopSelf();
super.onDestroy();*/
//stopSelf();
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " Service On onDestroyCalled", "abc.txt");
Log.i("onDestroy","onDestroy Called");
Intent broadcastIntent = new Intent(this, FieldStaffRestartBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
super.onDestroy();
}
@Override
public void onTaskRemoved(Intent rootIntent) {
writeDataToFile("\n" + CommonUtils.getCurrentDateInDDMMYYYFormat() + " Service On onTaskRemoved called", "abc.txt");
Log.i("EXIT", "onTaskRemoved!");
Intent broadcastIntent = new Intent(this, FieldStaffRestartBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
//stoptimertask();
}
/* @Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
if (bulkLatLngThroughputManager != null && bulkLatLngThroughputEmployee != null) {
bulkLatLngThroughputManager.removeCallbacks(bulkLatLngThroughputEmployee);
}
*//*if (locationManager!=null)
{
locationManager.removeUpdates(this);
}*//*
if (notificationManager != null) {
notificationManager.cancel(notificationId);
notificationManager.cancelAll();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.deleteNotificationChannel(channelId);
}
}
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
stopSelf();
*//*try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}*//*
}*/
@Override
public void onConnected(@Nullable Bundle bundle) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if(mGoogleApiClient.isConnected())
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
}
推荐阅读
- c# - 计算 Stream 中的读取和写入
- sql - SQL Server 在 2008 R2 上对大型数据集进行分页查询
- angular - 在使用通用表单进行更新和添加时将先前的值绑定到输入字段
- r - 用 R 中的唯一字符值填充 NA
- python - 如何在 python 的 ODE 中为变量添加约束?
- kubernetes - ArgoCD 跟踪指定路径中的子目录
- google-apps-script - 谷歌表格 JSON API
- javascript - 类型 'T' 不可分配给类型 'T[]'.ts(2345) 在将从 Promise 解析的数据中
- sql - sql中计算各部门月至今收入的问题
- install4j - 使用 install4j 选择安装程序旁边的文件