aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/utils/GeoDirHandler.java
blob: 64806e8fe05413dff8ae9658c533b036d8deddb4 (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
package cgeo.geocaching.utils;

import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.settings.Settings;

import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import rx.util.functions.Action0;
import rx.util.functions.Action1;

import java.util.concurrent.TimeUnit;

/**
 * GeoData and Direction handler.
 * <p>
 * To use this class, override at least one of {@link #updateDirection(float)} or {@link #updateGeoData(IGeoData)}. You
 * need to start the handler using one of
 * <ul>
 * <li>{@link #startDir()}</li>
 * <li>{@link #startGeo()}</li>
 * <li>{@link #startGeoAndDir()}</li>
 * </ul>
 * A good place might be the {@code onResume} method of the Activity. Stop the Handler accordingly in {@code onPause}.
 * </p>
 */
public abstract class GeoDirHandler {
    private static final CgeoApplication app = CgeoApplication.getInstance();

    private Subscription dirSubscription = null;
    private Subscription geoSubscription = null;

    /**
     * Update method called when new IGeoData is available.
     *
     * @param data
     *            the new data
     */
    public void updateGeoData(final IGeoData data) {
        // Override this in children
    }

    /**
     * Update method called when new direction data is available.
     *
     * @param direction
     *            the new direction
     */
    public void updateDirection(final float direction) {
        // Override this in children
    }

    /**
     * Register the current GeoDirHandler for GeoData information.
     */
    public synchronized void startGeo() {
        geoSubscription = app.currentGeoObject()
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<IGeoData>() {
                    @Override
                    public void call(final IGeoData geoData) {
                        updateGeoData(geoData);
                    }
                });
    }

    /**
     * Register the current GeoDirHandler for direction information if the preferences
     * allow it.
     */
    public synchronized void startDir() {
        if (Settings.isUseCompass()) {
            dirSubscription = app.currentDirObject()
                    .subscribeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<Float>() {
                        @Override
                        public void call(final Float direction) {
                            updateDirection(direction);
                        }
                    });
        }
    }

    /**
     * Register the current GeoDirHandler for GeoData and direction information (if the
     * preferences allow it).
     */
    public void startGeoAndDir() {
        startGeo();
        startDir();
    }

    /**
     * Unregister the current GeoDirHandler for GeoData information.
     */
    public synchronized void stopGeo() {
        // Delay the unsubscription by 2.5 seconds, so that another activity has
        // the time to subscribe and the GPS receiver will not be turned down.
        if (geoSubscription != null) {
            final Subscription subscription = geoSubscription;
            geoSubscription = null;
            Schedulers.newThread().schedule(new Action0() {
                @Override
                public void call() {
                    subscription.unsubscribe();
                }
            }, 2500, TimeUnit.MILLISECONDS);
        }
    }

    /**
     * Unregister the current GeoDirHandler for direction information.
     */
    public synchronized void stopDir() {
        if (dirSubscription != null) {
            dirSubscription.unsubscribe();
            dirSubscription = null;
        }
    }

    /**
     * Unregister the current GeoDirHandler for GeoData and direction information.
     */
    public void stopGeoAndDir() {
        stopGeo();
        stopDir();
    }
}