tencent_location_flutter 0.1.1 copy "tencent_location_flutter: ^0.1.1" to clipboard
tencent_location_flutter: ^0.1.1 copied to clipboard

Unofficial Flutter Tencent location plugin with federated Android and iOS implementations.

example/lib/main.dart

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:tencent_location_flutter/tencent_location_flutter.dart';

const String _defaultTencentLocationKey = 'VUXBZ-6IDKQ-G7D5L-4XDPR-6JFRQ-74BI3';
const MethodChannel _examplePermissionsChannel = MethodChannel(
  'tencent_location_flutter_example/permissions',
);

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const ExampleApp());
}

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Tencent Location Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF0D6EFD)),
        useMaterial3: true,
      ),
      home: const ExampleHomePage(),
    );
  }
}

class ExampleHomePage extends StatefulWidget {
  const ExampleHomePage({super.key});

  @override
  State<ExampleHomePage> createState() => _ExampleHomePageState();
}

class _ExampleHomePageState extends State<ExampleHomePage> {
  final TencentLocation _location = TencentLocation.instance;
  final TextEditingController _keyController = TextEditingController(
    text: _defaultTencentLocationKey,
  );
  final List<String> _logs = <String>[];

  StreamSubscription<TencentLocationData>? _sessionSubscription;
  StreamSubscription<TencentLocationError>? _sessionErrorSubscription;
  LocationUpdateSession? _session;
  TencentSdkInfo? _sdkInfo;
  TencentLocationData? _latestLocation;

  @override
  void initState() {
    super.initState();
    _location.authorizationChanges.listen((LocationAuthorizationState state) {
      _appendLog('authorization => ${state.toMap()}');
    });
    _location.locationErrors.listen((TencentLocationError error) {
      _appendLog('error => ${error.toMap()}');
    });
    _location.headingUpdates.listen((HeadingData heading) {
      _appendLog('heading => ${heading.toMap()}');
    });
    _location.geofenceEvents.listen((GeofenceEvent event) {
      _appendLog('geofence => ${event.toMap()}');
    });
    _location.drUpdates.listen((DrPosition position) {
      _appendLog('dr => ${position.toMap()}');
    });
  }

  @override
  void dispose() {
    _sessionSubscription?.cancel();
    _sessionErrorSubscription?.cancel();
    _keyController.dispose();
    super.dispose();
  }

  Future<void> _initialize() async {
    await _location.setUserAgreePrivacy(true);
    await _location.initialize(
      InitializeOptions(
        key: _keyController.text.trim(),
        coordinateType: TencentLocationCoordinateType.gcj02,
        requestLevel: TencentLocationRequestLevel.adminName,
        mockEnable: false,
        android: const AndroidInitOptions(
          locationMode: TencentAndroidLocationMode.highAccuracy,
          allowGps: true,
          loadLibraryEnabled: true,
        ),
        ios: const IosManagerOptions(
          allowsBackgroundLocationUpdates: true,
          pausesLocationUpdatesAutomatically: false,
        ),
      ),
    );
    final TencentSdkInfo sdkInfo = await _location.getSdkInfo();
    setState(() => _sdkInfo = sdkInfo);
    _appendLog('initialized => ${sdkInfo.toMap()}');
  }

  Future<void> _requestPermissions() async {
    if (Platform.isAndroid || Platform.isIOS) {
      final Object? result = await _examplePermissionsChannel.invokeMethod(
        'requestLocationPermissions',
      );
      _appendLog('${Platform.operatingSystem} permission request => $result');
    }
    if (Platform.isIOS) {
      await _location.ios.requestWhenInUseAuthorization();
    }
    final LocationAuthorizationState state = await _location
        .authorizationStatus();
    _appendLog('permission check => ${state.toMap()}');
  }

  Future<void> _getLocationOnce() async {
    final TencentLocationData data = await _location.getLocationOnce(
      options: const SingleLocationOptions(
        requestLevel: TencentLocationRequestLevel.poi,
        timeoutMillis: 10000,
      ),
    );
    setState(() => _latestLocation = data);
    _appendLog('single => ${data.toMap()}');
  }

  Future<void> _startContinuous() async {
    await _sessionSubscription?.cancel();
    await _sessionErrorSubscription?.cancel();
    final LocationUpdateSession session = await _location.startLocationUpdates(
      LocationUpdateOptions(
        intervalMillis: 15 * 1000,
        requestLevel: TencentLocationRequestLevel.geo,
        backgroundLocation: true,
        androidRequest: const AndroidLocationRequestOptions(
          intervalMillis: 15 * 1000,
          requestLevel: TencentLocationRequestLevel.geo,
          locationMode: TencentAndroidLocationMode.highAccuracy,
          allowGps: true,
          allowCache: true,
        ),
        androidForegroundNotification:
            const AndroidForegroundNotificationOptions(
              id: 1001,
              channelId: 'location_foreground',
              channelName: 'Tencent Location',
              title: 'Tencent Location',
              text: 'Continuous location is running',
            ),
        ios: const IosManagerOptions(
          allowsBackgroundLocationUpdates: true,
          pausesLocationUpdatesAutomatically: false,
        ),
      ),
    );
    _session = session;
    _sessionSubscription = session.updates.listen((TencentLocationData data) {
      setState(() => _latestLocation = data);
      _appendLog('continuous(${session.id}) => ${data.toMap()}');
    });
    _sessionErrorSubscription = session.errors.listen((
      TencentLocationError error,
    ) {
      _appendLog('continuous error(${session.id}) => ${error.toMap()}');
    });
    _appendLog('continuous started => ${session.id}');
  }

  Future<void> _stopContinuous() async {
    await _session?.stop();
    await _sessionSubscription?.cancel();
    await _sessionErrorSubscription?.cancel();
    _appendLog('continuous stopped');
    _session = null;
  }

  Future<void> _addGeofence() async {
    await _location.addGeofence(
      const GeofenceOptions(
        tag: 'example-fence',
        latitude: 22.543096,
        longitude: 114.057865,
        radiusMeters: 100,
      ),
    );
    _appendLog('${Platform.operatingSystem} geofence added');
  }

  Future<void> _startHeading() async {
    await _location.startHeadingUpdates();
    _appendLog('${Platform.operatingSystem} heading started');
  }

  Future<void> _stopHeading() async {
    await _location.stopHeadingUpdates();
    _appendLog('${Platform.operatingSystem} heading stopped');
  }

  Future<void> _requestIosTemporaryAccuracy() async {
    final LocationAccuracyAuthorization auth = await _location.ios
        .requestTemporaryFullAccuracyAuthorization(
          const IosTemporaryAccuracyOptions(
            purposeKey: 'TencentLocationAccuracy',
          ),
        );
    _appendLog('ios temporary accuracy => $auth');
  }

  Future<void> _startIosDr() async {
    final TencentDrStartCode code = await _location.startDrEngine(
      const TencentDrOptions(motionType: TencentDrMotionType.walk),
    );
    _appendLog('ios dr start => $code');
  }

  Future<void> _stopIosDr() async {
    await _location.stopDrEngine();
    _appendLog('ios dr stopped');
  }

  void _appendLog(String line) {
    debugPrint(line);
    setState(() {
      _logs.insert(0, '${DateTime.now().toIso8601String()}  $line');
      if (_logs.length > 40) {
        _logs.removeRange(40, _logs.length);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Tencent Location Example')),
      body: SafeArea(
        child: ListView(
          padding: const EdgeInsets.all(16),
          children: <Widget>[
            TextField(
              controller: _keyController,
              decoration: const InputDecoration(
                labelText: 'Tencent LBS Key',
                border: OutlineInputBorder(),
              ),
            ),
            const SizedBox(height: 12),
            Wrap(
              spacing: 12,
              runSpacing: 12,
              children: <Widget>[
                FilledButton(
                  onPressed: _initialize,
                  child: const Text('Agree + Init'),
                ),
                FilledButton(
                  onPressed: _requestPermissions,
                  child: const Text('Request Permissions'),
                ),
                FilledButton(
                  onPressed: _getLocationOnce,
                  child: const Text('Single Location'),
                ),
                FilledButton(
                  onPressed: _startContinuous,
                  child: const Text('Start Continuous'),
                ),
                FilledButton(
                  onPressed: _stopContinuous,
                  child: const Text('Stop Continuous'),
                ),
                if (Platform.isAndroid || Platform.isIOS)
                  FilledButton(
                    onPressed: _addGeofence,
                    child: const Text('Geofence'),
                  ),
                if (Platform.isAndroid || Platform.isIOS)
                  FilledButton(
                    onPressed: _startHeading,
                    child: const Text('Start Heading'),
                  ),
                if (Platform.isAndroid || Platform.isIOS)
                  FilledButton(
                    onPressed: _stopHeading,
                    child: const Text('Stop Heading'),
                  ),
                if (Platform.isIOS)
                  FilledButton(
                    onPressed: _requestIosTemporaryAccuracy,
                    child: const Text('Temp Accuracy'),
                  ),
                if (Platform.isIOS)
                  FilledButton(
                    onPressed: _startIosDr,
                    child: const Text('Start DR'),
                  ),
                if (Platform.isIOS)
                  FilledButton(
                    onPressed: _stopIosDr,
                    child: const Text('Stop DR'),
                  ),
              ],
            ),
            const SizedBox(height: 16),
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text('SDK Info: ${_sdkInfo?.toMap() ?? 'Not initialized'}'),
                    const SizedBox(height: 8),
                    Text(
                      'Latest Location: ${_latestLocation?.toMap() ?? 'N/A'}',
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            const Text('Logs'),
            const SizedBox(height: 8),
            Container(
              constraints: const BoxConstraints(minHeight: 240),
              decoration: BoxDecoration(
                color: Colors.black87,
                borderRadius: BorderRadius.circular(12),
              ),
              padding: const EdgeInsets.all(12),
              child: SelectableText(
                _logs.join('\n'),
                style: const TextStyle(
                  color: Colors.white,
                  fontFamily: 'monospace',
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
1
likes
160
points
54
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Unofficial Flutter Tencent location plugin with federated Android and iOS implementations.

Repository

License

MIT (license)

Dependencies

flutter, tencent_location_flutter_android, tencent_location_flutter_ios, tencent_location_flutter_platform_interface

More

Packages that depend on tencent_location_flutter

Packages that implement tencent_location_flutter