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