blob: 34dab095e99cf2b7b1b291f74e5dcfafb81d16c4 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
|
package cgeo.geocaching;
import cgeo.geocaching.playservices.LocationProvider;
import cgeo.geocaching.sensors.GeoData;
import cgeo.geocaching.sensors.GeoDataProvider;
import cgeo.geocaching.sensors.GpsStatusProvider;
import cgeo.geocaching.sensors.GpsStatusProvider.Status;
import cgeo.geocaching.sensors.IGeoData;
import cgeo.geocaching.sensors.OrientationProvider;
import cgeo.geocaching.sensors.RotationProvider;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.OOMDumpingUncaughtExceptionHandler;
import cgeo.geocaching.utils.RxUtils;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import org.eclipse.jdt.annotation.NonNull;
import rx.Observable;
import rx.functions.Action1;
import rx.functions.Func1;
import android.app.Application;
import android.view.ViewConfiguration;
import java.lang.reflect.Field;
public class CgeoApplication extends Application {
private boolean forceRelog = false; // c:geo needs to log into cache providers
public boolean showLoginToast = true; //login toast shown just once.
private boolean liveMapHintShownInThisSession = false; // livemap hint has been shown
private static CgeoApplication instance;
private Observable<IGeoData> geoDataObservable;
private Observable<IGeoData> geoDataObservableLowPower;
private Observable<Float> directionObservable;
private Observable<Status> gpsStatusObservable;
@NonNull private volatile IGeoData currentGeo = GeoData.DUMMY_LOCATION;
private volatile boolean hasValidLocation = false;
private volatile float currentDirection = 0.0f;
private boolean isGooglePlayServicesAvailable = false;
private final Action1<IGeoData> rememberGeodataAction = new Action1<IGeoData>() {
@Override
public void call(final IGeoData geoData) {
currentGeo = geoData;
hasValidLocation = true;
}
};
public static void dumpOnOutOfMemory(final boolean enable) {
if (enable) {
if (!OOMDumpingUncaughtExceptionHandler.activateHandler()) {
Log.e("OOM dumping handler not activated (either a problem occured or it was already active)");
}
} else {
if (!OOMDumpingUncaughtExceptionHandler.resetToDefault()) {
Log.e("OOM dumping handler not resetted (either a problem occured or it was not active)");
}
}
}
public CgeoApplication() {
setInstance(this);
}
private static void setInstance(final CgeoApplication application) {
instance = application;
}
public static CgeoApplication getInstance() {
return instance;
}
@Override
public void onCreate() {
try {
final ViewConfiguration config = ViewConfiguration.get(this);
final Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException ignore) {
}
// Set language to English if the user decided so.
Settings.setLanguage(Settings.isUseEnglish());
// ensure initialization of lists
DataStore.getLists();
// Check if Google Play services is available
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
isGooglePlayServicesAvailable = true;
}
Log.i("Google Play services are " + (isGooglePlayServicesAvailable ? "" : "not ") + "available");
setupGeoDataObservables(Settings.useGooglePlayServices(), Settings.useLowPowerMode());
setupDirectionObservable(Settings.useLowPowerMode());
gpsStatusObservable = GpsStatusProvider.create(this).replay(1).refCount();
// Attempt to acquire an initial location before any real activity happens.
geoDataObservableLowPower.subscribeOn(RxUtils.looperCallbacksScheduler).first().subscribe(rememberGeodataAction);
}
public void setupGeoDataObservables(final boolean useGooglePlayServices, final boolean useLowPowerLocation) {
if (useGooglePlayServices) {
geoDataObservable = LocationProvider.getMostPrecise(this).doOnNext(rememberGeodataAction);
if (useLowPowerLocation) {
geoDataObservableLowPower = LocationProvider.getLowPower(this, true).doOnNext(rememberGeodataAction);
} else {
geoDataObservableLowPower = geoDataObservable;
}
} else {
geoDataObservable = GeoDataProvider.create(this).replay(1).refCount().doOnNext(rememberGeodataAction);
geoDataObservableLowPower = geoDataObservable;
}
}
public void setupDirectionObservable(final boolean useLowPower) {
directionObservable = RotationProvider.create(this, useLowPower).onErrorResumeNext(new Func1<Throwable, Observable<? extends Float>>() {
@Override
public Observable<? extends Float> call(final Throwable throwable) {
return OrientationProvider.create(CgeoApplication.this);
}
}).onErrorResumeNext(new Func1<Throwable, Observable<? extends Float>>() {
@Override
public Observable<? extends Float> call(final Throwable throwable) {
Log.e("Device orientation will not be available as no suitable sensors were found");
return Observable.<Float>never().startWith(0.0f);
}
}).replay(1).refCount().doOnNext(new Action1<Float>() {
@Override
public void call(final Float direction) {
currentDirection = direction;
}
});
}
@Override
public void onLowMemory() {
Log.i("Cleaning applications cache.");
DataStore.removeAllFromCache();
}
public Observable<IGeoData> geoDataObservable(final boolean lowPower) {
return lowPower ? geoDataObservableLowPower : geoDataObservable;
}
public Observable<Float> directionObservable() {
return directionObservable;
}
public Observable<Status> gpsStatusObservable() {
if (gpsStatusObservable == null) {
gpsStatusObservable = GpsStatusProvider.create(this).share();
}
return gpsStatusObservable;
}
@NonNull
public IGeoData currentGeo() {
return currentGeo;
}
public boolean hasValidLocation() {
return hasValidLocation;
}
public Float distanceNonBlocking(final ICoordinates target) {
if (target.getCoords() == null) {
return null;
}
return currentGeo.getCoords().distanceTo(target);
}
public float currentDirection() {
return currentDirection;
}
public boolean isLiveMapHintShownInThisSession() {
return liveMapHintShownInThisSession;
}
public void setLiveMapHintShownInThisSession() {
liveMapHintShownInThisSession = true;
}
/**
* Check if cgeo must relog even if already logged in.
*
* @return <code>true</code> if it is necessary to relog
*/
public boolean mustRelog() {
final boolean mustLogin = forceRelog;
forceRelog = false;
return mustLogin;
}
/**
* Force cgeo to relog when reaching the main activity.
*/
public void forceRelog() {
forceRelog = true;
}
public boolean isGooglePlayServicesAvailable() {
return isGooglePlayServicesAvailable;
}
}
|