|
| 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