Merge branch 'fix-bg-power-saving' of s416084/find-my-tutor-android into develop
This commit is contained in:
commit
598e603dfb
@ -53,12 +53,17 @@
|
||||
android:name=".activity.SettingsActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"/>
|
||||
|
||||
<service
|
||||
android:name=".service.BackgroundLocalizationService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop" />
|
||||
<!--
|
||||
<service
|
||||
android:name=".service.BackgroundService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop" />-->
|
||||
|
||||
<activity
|
||||
android:name=".activity.TutorTab"
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.uam.wmi.findmytutor.activity;
|
||||
|
||||
//import android.app.Fragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentTabHost;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.uam.wmi.findmytutor.R;
|
||||
|
||||
public class TutorsListTab extends Fragment {
|
||||
private FragmentTabHost mTabHost;
|
||||
|
||||
public TutorsListTab() {
|
||||
}
|
||||
|
||||
public static TutorsListTab newInstance() {
|
||||
return new TutorsListTab();
|
||||
}
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
}
|
||||
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View rootView = inflater.inflate(R.layout.tutors_list_tabs, container, false);
|
||||
|
||||
mTabHost = rootView.findViewById(android.R.id.tabhost);
|
||||
mTabHost.setup(getActivity(), getFragmentManager(), R.id.realtabcontent);
|
||||
|
||||
mTabHost.addTab(mTabHost.newTabSpec("fragmentb").setIndicator("Fragment B"),
|
||||
UsersListFragment.class, null);
|
||||
mTabHost.addTab(mTabHost.newTabSpec("fragmentc").setIndicator("Fragment C"),
|
||||
UsersListFragment.class, null);
|
||||
|
||||
|
||||
|
||||
return rootView;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import android.util.Log;
|
||||
import com.annimon.stream.Stream;
|
||||
import com.google.android.gms.location.FusedLocationProviderClient;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
|
||||
import com.mapbox.geojson.Point;
|
||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||
import com.uam.wmi.findmytutor.model.Coordinate;
|
||||
@ -33,21 +32,17 @@ import com.uam.wmi.findmytutor.network.ApiClient;
|
||||
import com.uam.wmi.findmytutor.utils.ApproximatedLocalization;
|
||||
import com.uam.wmi.findmytutor.utils.MapUtils;
|
||||
import com.uam.wmi.findmytutor.utils.PrefUtils;
|
||||
import com.uam.wmi.findmytutor.utils.RestApiHelper;
|
||||
import com.uam.wmi.findmytutor.utils.SharingLevel;
|
||||
|
||||
import org.apache.commons.collections4.queue.CircularFifoQueue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.observers.DisposableCompletableObserver;
|
||||
import io.reactivex.observers.DisposableSingleObserver;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
import static com.uam.wmi.findmytutor.utils.Const.offlineBackgroundLocationInterval;
|
||||
import static com.uam.wmi.findmytutor.utils.Const.onlineBackgroundLocationInterval;
|
||||
@ -60,18 +55,14 @@ import static java.lang.String.valueOf;
|
||||
public class BackgroundLocalizationService extends Service {
|
||||
|
||||
private static final String TAG = "MyLocationService";
|
||||
private static final float LOCATION_DISTANCE = 1f;
|
||||
private static long notify_interval = onlineBackgroundLocationInterval;
|
||||
private static long notify_interval_inside_building = onlineBackgroundLocationInterval;
|
||||
private static long notify_interval_outside_building = offlineBackgroundLocationInterval;
|
||||
private static int coordinatesHistoryLength = 5;
|
||||
private static final Long LOCATION_INTERVAL = notify_interval;
|
||||
private Location mLastLocation;
|
||||
private Boolean stopService = false;
|
||||
private ArrayList<String> providers = new ArrayList<String>();
|
||||
private LocationListener[] mLocationListeners;
|
||||
private CircularFifoQueue<Location> coordinatesHistory = new CircularFifoQueue<Location>(coordinatesHistoryLength);
|
||||
private LocationManager mLocationManager = null;
|
||||
private Handler mHandler = new Handler();
|
||||
private Runnable mStatusChecker;
|
||||
private FusedLocationProviderClient mFusedLocationClient;
|
||||
@ -80,12 +71,6 @@ public class BackgroundLocalizationService extends Service {
|
||||
providers.add(LocationManager.GPS_PROVIDER);
|
||||
providers.add(LocationManager.NETWORK_PROVIDER);
|
||||
providers.add(LocationManager.PASSIVE_PROVIDER);
|
||||
|
||||
mLocationListeners = new LocationListener[]{
|
||||
new LocationListener(LocationManager.GPS_PROVIDER),
|
||||
new LocationListener(LocationManager.NETWORK_PROVIDER),
|
||||
new LocationListener(LocationManager.PASSIVE_PROVIDER)
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -129,7 +114,6 @@ public class BackgroundLocalizationService extends Service {
|
||||
mStatusChecker = () -> {
|
||||
try {
|
||||
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
|
||||
initializeLocationManager();
|
||||
getLocalizationFromListeners();
|
||||
changeBackgroundMode();
|
||||
} finally {
|
||||
@ -192,10 +176,6 @@ public class BackgroundLocalizationService extends Service {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> providers1 = mLocationManager.getProviders(true);
|
||||
Location bestLocation = null;
|
||||
AtomicReference<Boolean> triggerAnotherLocationListener = new AtomicReference<>(false);
|
||||
|
||||
mFusedLocationClient.getLastLocation().addOnSuccessListener(
|
||||
location -> {
|
||||
if (location != null) {
|
||||
@ -204,24 +184,8 @@ public class BackgroundLocalizationService extends Service {
|
||||
sendCoordinateToBackend(location);
|
||||
}
|
||||
|
||||
triggerAnotherLocationListener.set(true);
|
||||
});
|
||||
|
||||
if (triggerAnotherLocationListener.get()) {
|
||||
for (String provider : providers1) {
|
||||
Location location = mLocationManager.getLastKnownLocation(provider);
|
||||
|
||||
if (location == null) {
|
||||
continue;
|
||||
}
|
||||
if (bestLocation == null || location.getAccuracy() < bestLocation.getAccuracy()) {
|
||||
bestLocation = location;
|
||||
}
|
||||
}
|
||||
|
||||
coordinatesHistory.add(bestLocation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sendCoordinateToBackend(Location location) {
|
||||
@ -238,48 +202,10 @@ public class BackgroundLocalizationService extends Service {
|
||||
}
|
||||
|
||||
private void destroyLocationListeners(){
|
||||
if (mLocationManager != null) {
|
||||
for (LocationListener listener : mLocationListeners) {
|
||||
try {
|
||||
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
mLocationManager.removeUpdates(listener);
|
||||
|
||||
} catch (Exception ex) {
|
||||
Log.i(TAG, "fail to remove location listener, ignore", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void initializeLocationManager() {
|
||||
Log.e(TAG, "initializeLocationManager - LOCATION_INTERVAL: " + notify_interval + " LOCATION_DISTANCE: " + LOCATION_DISTANCE);
|
||||
|
||||
if (mLocationManager == null) {
|
||||
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
|
||||
}
|
||||
|
||||
Integer providerIndex = 0;
|
||||
|
||||
for (LocationListener listener : mLocationListeners) {
|
||||
try {
|
||||
mLocationManager.requestLocationUpdates(
|
||||
providers.get(providerIndex),
|
||||
notify_interval,
|
||||
LOCATION_DISTANCE,
|
||||
listener
|
||||
);
|
||||
|
||||
} 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());
|
||||
}
|
||||
|
||||
providerIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
private class LocationListener implements android.location.LocationListener {
|
||||
|
||||
|
@ -0,0 +1,264 @@
|
||||
package com.uam.wmi.findmytutor.service;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.SyncStateContract;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static com.uam.wmi.findmytutor.utils.Const.onlineBackgroundLocationInterval;
|
||||
|
||||
|
||||
public class BackgroundService extends Service implements
|
||||
GoogleApiClient.ConnectionCallbacks,
|
||||
GoogleApiClient.OnConnectionFailedListener,
|
||||
LocationListener {
|
||||
|
||||
IBinder mBinder = new LocalBinder();
|
||||
private static final String TAG = "MyLocationService";
|
||||
|
||||
private GoogleApiClient mGoogleApiClient;
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
private LocationRequest mLocationRequest;
|
||||
// Flag that indicates if a request is underway.
|
||||
private boolean mInProgress;
|
||||
private static long notify_interval = onlineBackgroundLocationInterval;
|
||||
|
||||
private Boolean servicesAvailable = false;
|
||||
|
||||
public class LocalBinder extends Binder {
|
||||
public BackgroundService getServerInstance() {
|
||||
return BackgroundService.this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
|
||||
mInProgress = false;
|
||||
// Create the LocationRequest object
|
||||
mLocationRequest = LocationRequest.create();
|
||||
// Use high accuracy
|
||||
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
|
||||
// Set the update interval to 5 seconds
|
||||
mLocationRequest.setInterval(notify_interval);
|
||||
// Set the fastest update interval to 1 second
|
||||
mLocationRequest.setFastestInterval(notify_interval);
|
||||
|
||||
servicesAvailable = servicesConnected();
|
||||
|
||||
/*
|
||||
* Create a new location client, using the enclosing class to
|
||||
* handle callbacks.
|
||||
*/
|
||||
setUpLocationClientIfNeeded();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new location client, using the enclosing class to
|
||||
* handle callbacks.
|
||||
*/
|
||||
protected synchronized void buildGoogleApiClient() {
|
||||
this.mGoogleApiClient = new GoogleApiClient.Builder(this)
|
||||
.addConnectionCallbacks(this)
|
||||
.addOnConnectionFailedListener(this)
|
||||
.addApi(LocationServices.API)
|
||||
.build();
|
||||
}
|
||||
|
||||
private boolean servicesConnected() {
|
||||
|
||||
// Check that Google Play services is available
|
||||
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
|
||||
|
||||
// If Google Play services is available
|
||||
if (ConnectionResult.SUCCESS == resultCode) {
|
||||
|
||||
return true;
|
||||
} else {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("InvalidWakeLockTag")
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
super.onStartCommand(intent, flags, startId);
|
||||
|
||||
PowerManager mgr = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
|
||||
/*
|
||||
WakeLock is reference counted so we don't want to create multiple WakeLocks. So do a check before initializing and acquiring.
|
||||
|
||||
This will fix the "java.lang.Exception: WakeLock finalized while still held: MyWakeLock" error that you may find.
|
||||
*/
|
||||
/* if (this.mWakeLock == null) { //**Added this
|
||||
this.mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
|
||||
}
|
||||
|
||||
if (!this.mWakeLock.isHeld()) { //**Added this
|
||||
this.mWakeLock.acquire(10*60*1000L *//*10 minutes*//*);
|
||||
}*/
|
||||
|
||||
if (!servicesAvailable || mGoogleApiClient.isConnected() || mInProgress)
|
||||
return START_STICKY;
|
||||
|
||||
setUpLocationClientIfNeeded();
|
||||
if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting() && !mInProgress) {
|
||||
mInProgress = true;
|
||||
mGoogleApiClient.connect();
|
||||
}
|
||||
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
|
||||
private void setUpLocationClientIfNeeded() {
|
||||
if (mGoogleApiClient == null)
|
||||
buildGoogleApiClient();
|
||||
}
|
||||
|
||||
// Define the callback method that receives location updates
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
// Report to the UI that the location was updated
|
||||
String msg = Double.toString(location.getLatitude()) + "," +
|
||||
Double.toString(location.getLongitude());
|
||||
Log.d("debug", msg);
|
||||
Log.e(TAG, "onLocationChanged: " + location);
|
||||
|
||||
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(String s, int i, Bundle bundle) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderEnabled(String s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderDisabled(String s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
// Turn off the request flag
|
||||
this.mInProgress = false;
|
||||
|
||||
if (this.servicesAvailable && this.mGoogleApiClient != null) {
|
||||
this.mGoogleApiClient.unregisterConnectionCallbacks(this);
|
||||
this.mGoogleApiClient.unregisterConnectionFailedListener(this);
|
||||
this.mGoogleApiClient.disconnect();
|
||||
// Destroy the current location client
|
||||
this.mGoogleApiClient = null;
|
||||
}
|
||||
// Display the connection status
|
||||
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ":
|
||||
// Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (this.mWakeLock != null) {
|
||||
this.mWakeLock.release();
|
||||
this.mWakeLock = null;
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by Location Services when the request to connect the
|
||||
* client finishes successfully. At this point, you can
|
||||
* request the current location or start periodic updates
|
||||
*/
|
||||
@Override
|
||||
public void onConnected(Bundle bundle) {
|
||||
|
||||
// Request location updates using static settings
|
||||
//Intent intent = new Intent(this, LocationReceiver.class);
|
||||
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.
|
||||
return;
|
||||
}
|
||||
|
||||
LocationServices.getFusedLocationProviderClient(this);
|
||||
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, (com.google.android.gms.location.LocationListener) this);
|
||||
|
||||
/* .requestLocationUpdates(this.mGoogleApiClient,
|
||||
mLocationRequest, (com.google.android.gms.location.LocationListener) this); // This is the changed line.*/
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by Location Services if the connection to the
|
||||
* location client drops because of an error.
|
||||
*/
|
||||
@Override
|
||||
public void onConnectionSuspended(int i) {
|
||||
// Turn off the request flag
|
||||
mInProgress = false;
|
||||
// Destroy the current location client
|
||||
mGoogleApiClient = null;
|
||||
// Display the connection status
|
||||
// Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ": Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by Location Services if the attempt to
|
||||
* Location Services fails.
|
||||
*/
|
||||
@Override
|
||||
public void onConnectionFailed(ConnectionResult connectionResult) {
|
||||
mInProgress = false;
|
||||
|
||||
/*
|
||||
* Google Play services can resolve some errors it detects.
|
||||
* If the error has a resolution, try sending an Intent to
|
||||
* start a Google Play services activity that can resolve
|
||||
* error.
|
||||
*/
|
||||
if (connectionResult.hasResolution()) {
|
||||
|
||||
// If no resolution is available, display an error dialog
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
56
app/src/main/res/layout/tutors_list_tabs.xml
Normal file
56
app/src/main/res/layout/tutors_list_tabs.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v4.app.FragmentTabHost
|
||||
android:id="@+id/tabHost"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TabWidget
|
||||
android:id="@android:id/tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@android:id/tabcontent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/tab1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/tab2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/realtabcontent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_below="@+id/tabLinear"/>
|
||||
|
||||
</android.support.v4.app.FragmentTabHost>
|
||||
</RelativeLayout>
|
Loading…
Reference in New Issue
Block a user