-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
124 lines (107 loc) · 3.46 KB
/
main.go
File metadata and controls
124 lines (107 loc) · 3.46 KB
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
// Live GPS location via binder IPC: register a callback, receive a fix, print coordinates.
//
// Build:
//
// GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o build/gps_location ./examples/gps_location/
// adb push build/gps_location /data/local/tmp/ && adb shell /data/local/tmp/gps_location
package main
import (
"context"
"fmt"
"math"
"os"
"time"
"github.com/AndroidGoLab/binder/android/location"
androidos "github.com/AndroidGoLab/binder/android/os"
osTypes "github.com/AndroidGoLab/binder/android/os/types"
"github.com/AndroidGoLab/binder/binder"
"github.com/AndroidGoLab/binder/binder/versionaware"
"github.com/AndroidGoLab/binder/kernelbinder"
"github.com/AndroidGoLab/binder/servicemanager"
)
const gpsTimeout = 5 * time.Second
// gpsListener receives location callbacks from the LocationManager.
type gpsListener struct {
fixCh chan location.Location
}
func (l *gpsListener) OnLocationChanged(
_ context.Context,
locations []location.Location,
_ androidos.IRemoteCallback,
) error {
for _, loc := range locations {
select {
case l.fixCh <- loc:
default:
}
}
return nil
}
func (l *gpsListener) OnProviderEnabledChanged(
_ context.Context,
_ string,
_ bool,
) error {
return nil
}
func (l *gpsListener) OnFlushComplete(_ context.Context, _ int32) error {
return nil
}
func main() {
ctx := context.Background()
drv, err := kernelbinder.Open(ctx, binder.WithMapSize(128*1024))
if err != nil {
fmt.Fprintf(os.Stderr, "open binder: %v\n", err)
os.Exit(1)
}
defer drv.Close(ctx)
transport, err := versionaware.NewTransport(ctx, drv, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "version-aware transport: %v\n", err)
os.Exit(1)
}
sm := servicemanager.New(transport)
lm, err := location.GetLocationManager(ctx, sm)
if err != nil {
fmt.Fprintf(os.Stderr, "get location manager: %v\n", err)
os.Exit(1)
}
// Create the listener stub.
impl := &gpsListener{fixCh: make(chan location.Location, 1)}
listener := location.NewLocationListenerStub(impl)
request := location.LocationRequest{
Provider: location.GpsProvider,
IntervalMillis: 1000,
Quality: 102, // QUALITY_BALANCED_POWER_ACCURACY
ExpireAtRealtimeMillis: math.MaxInt64,
DurationMillis: math.MaxInt64,
MaxUpdates: math.MaxInt32,
MinUpdateIntervalMillis: -1,
// WorkSource must be non-null; Java's LocationRequest always
// initializes it to an empty WorkSource (Num=0).
WorkSource: &osTypes.WorkSource{},
}
packageName := binder.DefaultCallerIdentity().PackageName
fmt.Println("Registering GPS listener...")
err = lm.RegisterLocationListener(ctx, location.GpsProvider, request, listener, packageName, "gps-example")
if err != nil {
fmt.Fprintf(os.Stderr, "register listener: %v\n", err)
os.Exit(1)
}
fmt.Printf("Waiting for GPS fix (timeout %s)...\n", gpsTimeout)
select {
case loc := <-impl.fixCh:
fmt.Printf("Lat: %.6f\n", loc.LatitudeDegrees)
fmt.Printf("Lon: %.6f\n", loc.LongitudeDegrees)
fmt.Printf("Alt: %.1f m\n", loc.AltitudeMeters)
fmt.Printf("Speed: %.1f m/s\n", loc.SpeedMetersPerSecond)
fmt.Printf("Bearing: %.1f deg\n", loc.BearingDegrees)
fmt.Printf("Accuracy: %.1f m\n", loc.HorizontalAccuracyMeters)
case <-time.After(gpsTimeout):
fmt.Fprintf(os.Stderr, "timed out waiting for GPS fix\n")
}
fmt.Println("Unregistering listener...")
if err := lm.UnregisterLocationListener(ctx, listener); err != nil {
fmt.Fprintf(os.Stderr, "unregister listener: %v\n", err)
}
}