Skip to content

Commit e0bd235

Browse files
feat: add GPS location example with live ILocationListener callback
Add examples/gps_location/ that registers a location listener callback, receives a real GPS fix via onLocationChanged, and prints coordinates. Fix LocationRequest.MarshalParcel to write a non-null empty WorkSource instead of WriteInt32(-1). Java's readTypedObject treats 0 as null and non-zero as present; -1 caused the LocationManager to attempt deserializing a WorkSource from non-existent data (BadParcelable). Also set ExpireAtRealtimeMillis and DurationMillis to MaxInt64 in the example request — zero values cause getExpirationRealtimeMs to return 0, which is always <= elapsedRealtime, triggering immediate listener removal via onAlarm.
1 parent 477d2f5 commit e0bd235

2 files changed

Lines changed: 124 additions & 1 deletion

File tree

android/location/locationrequest.go

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/gps_location/main.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Live GPS location via binder IPC: register a callback, receive a fix, print coordinates.
2+
//
3+
// Build:
4+
//
5+
// GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o build/gps_location ./examples/gps_location/
6+
// adb push build/gps_location /data/local/tmp/ && adb shell /data/local/tmp/gps_location
7+
package main
8+
9+
import (
10+
"context"
11+
"fmt"
12+
"math"
13+
"os"
14+
"time"
15+
16+
"github.com/xaionaro-go/binder/android/location"
17+
androidos "github.com/xaionaro-go/binder/android/os"
18+
"github.com/xaionaro-go/binder/binder"
19+
"github.com/xaionaro-go/binder/binder/versionaware"
20+
"github.com/xaionaro-go/binder/kernelbinder"
21+
"github.com/xaionaro-go/binder/servicemanager"
22+
)
23+
24+
const gpsTimeout = 30 * time.Second
25+
26+
// gpsListener receives location callbacks from the LocationManager.
27+
type gpsListener struct {
28+
fixCh chan location.Location
29+
}
30+
31+
func (l *gpsListener) OnLocationChanged(
32+
_ context.Context,
33+
locations []location.Location,
34+
_ androidos.IRemoteCallback,
35+
) error {
36+
for _, loc := range locations {
37+
select {
38+
case l.fixCh <- loc:
39+
default:
40+
}
41+
}
42+
return nil
43+
}
44+
45+
func (l *gpsListener) OnProviderEnabledChanged(
46+
_ context.Context,
47+
_ string,
48+
_ bool,
49+
) error {
50+
return nil
51+
}
52+
53+
func (l *gpsListener) OnFlushComplete(_ context.Context, _ int32) error {
54+
return nil
55+
}
56+
57+
func main() {
58+
ctx := context.Background()
59+
60+
drv, err := kernelbinder.Open(ctx, binder.WithMapSize(128*1024))
61+
if err != nil {
62+
fmt.Fprintf(os.Stderr, "open binder: %v\n", err)
63+
os.Exit(1)
64+
}
65+
defer drv.Close(ctx)
66+
67+
transport, err := versionaware.NewTransport(ctx, drv, 0)
68+
if err != nil {
69+
fmt.Fprintf(os.Stderr, "version-aware transport: %v\n", err)
70+
os.Exit(1)
71+
}
72+
73+
sm := servicemanager.New(transport)
74+
75+
lm, err := location.GetLocationManager(ctx, sm)
76+
if err != nil {
77+
fmt.Fprintf(os.Stderr, "get location manager: %v\n", err)
78+
os.Exit(1)
79+
}
80+
81+
// Create the listener stub.
82+
impl := &gpsListener{fixCh: make(chan location.Location, 1)}
83+
listener := location.NewLocationListenerStub(impl)
84+
85+
request := location.LocationRequest{
86+
Provider: location.GpsProvider,
87+
IntervalMillis: 1000,
88+
ExpireAtRealtimeMillis: math.MaxInt64,
89+
DurationMillis: math.MaxInt64,
90+
}
91+
92+
packageName := binder.DefaultCallerIdentity().PackageName
93+
fmt.Println("Registering GPS listener...")
94+
err = lm.RegisterLocationListener(ctx, location.GpsProvider, request, listener, packageName, "gps-example")
95+
if err != nil {
96+
fmt.Fprintf(os.Stderr, "register listener: %v\n", err)
97+
os.Exit(1)
98+
}
99+
100+
fmt.Printf("Waiting for GPS fix (timeout %s)...\n", gpsTimeout)
101+
select {
102+
case loc := <-impl.fixCh:
103+
fmt.Printf("Lat: %.6f\n", loc.LatitudeDegrees)
104+
fmt.Printf("Lon: %.6f\n", loc.LongitudeDegrees)
105+
fmt.Printf("Alt: %.1f m\n", loc.AltitudeMeters)
106+
fmt.Printf("Speed: %.1f m/s\n", loc.SpeedMetersPerSecond)
107+
fmt.Printf("Bearing: %.1f deg\n", loc.BearingDegrees)
108+
fmt.Printf("Accuracy: %.1f m\n", loc.HorizontalAccuracyMeters)
109+
case <-time.After(gpsTimeout):
110+
fmt.Fprintf(os.Stderr, "timed out waiting for GPS fix\n")
111+
}
112+
113+
fmt.Println("Unregistering listener...")
114+
if err := lm.UnregisterLocationListener(ctx, listener); err != nil {
115+
fmt.Fprintf(os.Stderr, "unregister listener: %v\n", err)
116+
}
117+
}

0 commit comments

Comments
 (0)