mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
[federated_plugin] adds platform interface implementation and plugin implementation for Android (#503)
This commit is contained in:
@@ -40,4 +40,5 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'com.google.android.gms:play-services-location:17.0.0'
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="dev.flutter.federated_plugin">
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
</manifest>
|
||||
|
||||
@@ -4,37 +4,109 @@
|
||||
|
||||
package dev.flutter.federated_plugin
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.annotation.NonNull
|
||||
import androidx.core.app.ActivityCompat.requestPermissions
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.android.gms.location.LocationServices.getFusedLocationProviderClient
|
||||
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||
import io.flutter.plugin.common.MethodChannel.Result
|
||||
import io.flutter.plugin.common.PluginRegistry.Registrar
|
||||
import io.flutter.plugin.common.PluginRegistry
|
||||
|
||||
/** FederatedPlugin */
|
||||
public class FederatedPlugin: FlutterPlugin, MethodCallHandler {
|
||||
/// The MethodChannel that will the communication between Flutter and native Android
|
||||
///
|
||||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
||||
/// when the Flutter Engine is detached from the Activity
|
||||
private lateinit var channel : MethodChannel
|
||||
|
||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel = MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "federated_plugin")
|
||||
channel.setMethodCallHandler(this);
|
||||
}
|
||||
class FederatedPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, PluginRegistry.RequestPermissionsResultListener {
|
||||
private lateinit var channel: MethodChannel
|
||||
private lateinit var context: Context
|
||||
private lateinit var activity: Activity
|
||||
private lateinit var result: Result
|
||||
private val REQUEST_CODE = 1001
|
||||
|
||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
||||
if (call.method == "getPlatformVersion") {
|
||||
result.success("Android ${android.os.Build.VERSION.RELEASE}")
|
||||
} else {
|
||||
result.notImplemented()
|
||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "location")
|
||||
channel.setMethodCallHandler(this)
|
||||
context = flutterPluginBinding.applicationContext
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel.setMethodCallHandler(null)
|
||||
}
|
||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
||||
this.result = result
|
||||
if (call.method == "getLocation") {
|
||||
// Check for the runtime permission if SDK version is greater than 23. If permissions
|
||||
// are granted, send the location data back to Dart. If permissions are not granted,
|
||||
// request for the runtime permissions.
|
||||
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.LOLLIPOP && !checkPermissions()) {
|
||||
requestPermissions(activity, arrayOf(
|
||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
), REQUEST_CODE)
|
||||
} else {
|
||||
provideLocation()
|
||||
}
|
||||
} else {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
// Method to fetch and send the last known location of the device to Dart.
|
||||
private fun provideLocation() {
|
||||
getFusedLocationProviderClient(context).lastLocation
|
||||
.addOnSuccessListener { location ->
|
||||
if (location != null) {
|
||||
result.success(listOf(location.longitude, location.latitude))
|
||||
} else {
|
||||
result.error("NOT_DETERMINED", "Not able to determine location", null)
|
||||
}
|
||||
}.addOnFailureListener { exception ->
|
||||
result.error("Error", exception.message, null)
|
||||
}
|
||||
}
|
||||
|
||||
// Method to check permissions to access the location data.
|
||||
private fun checkPermissions(): Boolean {
|
||||
val fineLocationPermission = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
val coarseLocationPermission = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||
|
||||
return fineLocationPermission == PackageManager.PERMISSION_GRANTED &&
|
||||
coarseLocationPermission == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
|
||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel.setMethodCallHandler(null)
|
||||
}
|
||||
|
||||
override fun onDetachedFromActivity() {}
|
||||
|
||||
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
|
||||
activity = binding.activity
|
||||
}
|
||||
|
||||
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
||||
activity = binding.activity
|
||||
binding.addRequestPermissionsResultListener(this)
|
||||
}
|
||||
|
||||
override fun onDetachedFromActivityForConfigChanges() {}
|
||||
|
||||
// Callback for the result after requesting for runtime permissions. If permissions
|
||||
// are granted, send the location data, or send an error back to Dart if permissions
|
||||
// are not granted.
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>?, grantResults: IntArray): Boolean {
|
||||
if (requestCode == REQUEST_CODE && grantResults.isNotEmpty()) {
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
|
||||
provideLocation()
|
||||
} else {
|
||||
result.error("PERMISSION_DENIED", "Permission denied from User", null)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,60 +2,74 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:federated_plugin/federated_plugin.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
void main() {
|
||||
runApp(MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
String _platformVersion = 'Unknown';
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initPlatformState();
|
||||
}
|
||||
|
||||
// Platform messages are asynchronous, so we initialize in an async method.
|
||||
Future<void> initPlatformState() async {
|
||||
String platformVersion;
|
||||
// Platform messages may fail, so we use a try/catch PlatformException.
|
||||
try {
|
||||
platformVersion = await FederatedPlugin.platformVersion;
|
||||
} on PlatformException {
|
||||
platformVersion = 'Failed to get platform version.';
|
||||
}
|
||||
|
||||
// If the widget was removed from the tree while the asynchronous platform
|
||||
// message was in flight, we want to discard the reply rather than calling
|
||||
// setState to update our non-existent appearance.
|
||||
if (!mounted) return;
|
||||
|
||||
setState(() {
|
||||
_platformVersion = platformVersion;
|
||||
});
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Plugin example app'),
|
||||
),
|
||||
body: Center(
|
||||
child: Text('Running on: $_platformVersion\n'),
|
||||
),
|
||||
home: HomePage(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Demonstrates how to use the getLocation method from federated_plugin to access
|
||||
/// location data.
|
||||
class HomePage extends StatefulWidget {
|
||||
@override
|
||||
_HomePageState createState() => _HomePageState();
|
||||
}
|
||||
|
||||
class _HomePageState extends State<HomePage> {
|
||||
Location location;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Federated Plugin Demo'),
|
||||
),
|
||||
body: Builder(
|
||||
builder: (context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
location == null
|
||||
? SizedBox.shrink()
|
||||
: Text(
|
||||
'Latitude: ${location.latitude}\n'
|
||||
'Longitude: ${location.longitude}',
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
RaisedButton(
|
||||
child: Text('Get Location'),
|
||||
onPressed: () async {
|
||||
try {
|
||||
final result = await getLocation();
|
||||
setState(() {
|
||||
location = result;
|
||||
});
|
||||
} catch (error) {
|
||||
Scaffold.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
content: Text(error.message as String),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,13 @@ packages:
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
federated_plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "../../federated_plugin_platform_interface"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -102,6 +109,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.2"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
||||
@@ -2,23 +2,35 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:federated_plugin/federated_plugin.dart';
|
||||
import 'package:federated_plugin_example/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:federated_plugin_example/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Verify Platform version', (tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(MyApp());
|
||||
group('federated plugin demo tests', () {
|
||||
final location = Location(latitude: 131.0, longitude: 221.0);
|
||||
setUpAll(() {
|
||||
MethodChannel('location').setMockMethodCallHandler((call) async {
|
||||
if (call.method == 'getLocation') {
|
||||
return [location.longitude, location.latitude];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Verify that platform version is retrieved.
|
||||
expect(
|
||||
find.byWidgetPredicate(
|
||||
(widget) => widget is Text &&
|
||||
widget.data.startsWith('Running on:'),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
testWidgets('get location from platform', (tester) async {
|
||||
await tester.pumpWidget(MyApp());
|
||||
|
||||
// Tap button to get location from platform.
|
||||
await tester.tap(find.byType(RaisedButton));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
find.text('Latitude: ${location.latitude}\n'
|
||||
'Longitude: ${location.longitude}'),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:federated_plugin_platform_interface/federated_plugin_platform_interface.dart';
|
||||
import 'package:federated_plugin_platform_interface/location_model.dart';
|
||||
export 'package:federated_plugin_platform_interface/location_model.dart';
|
||||
|
||||
class FederatedPlugin {
|
||||
static const MethodChannel _channel = MethodChannel('federated_plugin');
|
||||
|
||||
static Future<String> get platformVersion async {
|
||||
final version = await _channel.invokeMethod<String>('getPlatformVersion');
|
||||
return version;
|
||||
}
|
||||
/// Returns [Location] to provide latitude and longitude.
|
||||
///
|
||||
/// It uses [FederatedPluginInterface] interface to provide location.
|
||||
Future<Location> getLocation() async {
|
||||
return await FederatedPluginInterface.instance.getLocation();
|
||||
}
|
||||
|
||||
@@ -50,6 +50,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
federated_plugin_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../federated_plugin_platform_interface"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -88,6 +95,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.2"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
||||
@@ -12,6 +12,8 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
federated_plugin_platform_interface:
|
||||
path: ../federated_plugin_platform_interface
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -7,21 +7,20 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:federated_plugin/federated_plugin.dart';
|
||||
|
||||
void main() {
|
||||
const channel = MethodChannel('federated_plugin');
|
||||
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
setUp(() {
|
||||
channel.setMockMethodCallHandler((methodCall) async {
|
||||
return '42';
|
||||
group('Federated Plugin Test', () {
|
||||
final location = Location(latitude: 131.0, longitude: 221.0);
|
||||
MethodChannel('location').setMockMethodCallHandler((call) async {
|
||||
if (call.method == 'getLocation') {
|
||||
return [location.longitude, location.latitude];
|
||||
}
|
||||
});
|
||||
|
||||
test('getLocation method test', () async {
|
||||
final result = await getLocation();
|
||||
expect(result.longitude, location.longitude);
|
||||
expect(result.latitude, location.latitude);
|
||||
});
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
channel.setMockMethodCallHandler(null);
|
||||
});
|
||||
|
||||
test('getPlatformVersion', () async {
|
||||
expect(await FederatedPlugin.platformVersion, '42');
|
||||
});
|
||||
}
|
||||
|
||||
75
experimental/federated_plugin/federated_plugin_platform_interface/.gitignore
vendored
Normal file
75
experimental/federated_plugin/federated_plugin_platform_interface/.gitignore
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
build/
|
||||
|
||||
# Android related
|
||||
**/android/**/gradle-wrapper.jar
|
||||
**/android/.gradle
|
||||
**/android/captures/
|
||||
**/android/gradlew
|
||||
**/android/gradlew.bat
|
||||
**/android/local.properties
|
||||
**/android/**/GeneratedPluginRegistrant.java
|
||||
|
||||
# iOS/XCode related
|
||||
**/ios/**/*.mode1v3
|
||||
**/ios/**/*.mode2v3
|
||||
**/ios/**/*.moved-aside
|
||||
**/ios/**/*.pbxuser
|
||||
**/ios/**/*.perspectivev3
|
||||
**/ios/**/*sync/
|
||||
**/ios/**/.sconsign.dblite
|
||||
**/ios/**/.tags*
|
||||
**/ios/**/.vagrant/
|
||||
**/ios/**/DerivedData/
|
||||
**/ios/**/Icon?
|
||||
**/ios/**/Pods/
|
||||
**/ios/**/.symlinks/
|
||||
**/ios/**/profile
|
||||
**/ios/**/xcuserdata
|
||||
**/ios/.generated/
|
||||
**/ios/Flutter/App.framework
|
||||
**/ios/Flutter/Flutter.framework
|
||||
**/ios/Flutter/Flutter.podspec
|
||||
**/ios/Flutter/Generated.xcconfig
|
||||
**/ios/Flutter/app.flx
|
||||
**/ios/Flutter/app.zip
|
||||
**/ios/Flutter/flutter_assets/
|
||||
**/ios/Flutter/flutter_export_environment.sh
|
||||
**/ios/ServiceDefinitions.json
|
||||
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Exceptions to above rules.
|
||||
!**/ios/**/default.mode1v3
|
||||
!**/ios/**/default.mode2v3
|
||||
!**/ios/**/default.pbxuser
|
||||
!**/ios/**/default.perspectivev3
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||
@@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 8bd2e6585b0eda5ccdc10c1e1d35105e11f84424
|
||||
channel: master
|
||||
|
||||
project_type: package
|
||||
@@ -0,0 +1,31 @@
|
||||
include: package:pedantic/analysis_options.yaml
|
||||
|
||||
analyzer:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
||||
implicit-dynamic: false
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- avoid_types_on_closure_parameters
|
||||
- avoid_void_async
|
||||
- await_only_futures
|
||||
- camel_case_types
|
||||
- cancel_subscriptions
|
||||
- close_sinks
|
||||
- constant_identifier_names
|
||||
- control_flow_in_finally
|
||||
- directives_ordering
|
||||
- empty_statements
|
||||
- hash_and_equals
|
||||
- implementation_imports
|
||||
- non_constant_identifier_names
|
||||
- package_api_docs
|
||||
- package_names
|
||||
- package_prefixed_library_names
|
||||
- test_types_in_equals
|
||||
- throw_in_finally
|
||||
- unnecessary_brace_in_string_interps
|
||||
- unnecessary_getters_setters
|
||||
- unnecessary_new
|
||||
- unnecessary_statements
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2020 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:federated_plugin_platform_interface/location_method_channel.dart';
|
||||
import 'package:federated_plugin_platform_interface/location_model.dart';
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
|
||||
/// Interface which allows all the platform plugins to implement the same
|
||||
/// functionality.
|
||||
abstract class FederatedPluginInterface extends PlatformInterface {
|
||||
FederatedPluginInterface() : super(token: _object);
|
||||
|
||||
static FederatedPluginInterface _federatedPluginInterface =
|
||||
LocationMethodChannel();
|
||||
|
||||
static final Object _object = Object();
|
||||
|
||||
/// Provides instance of [LocationMethodChannel] to invoke platform calls.
|
||||
static FederatedPluginInterface get instance => _federatedPluginInterface;
|
||||
|
||||
static set instance(FederatedPluginInterface instance) {
|
||||
PlatformInterface.verifyToken(instance, _object);
|
||||
_federatedPluginInterface = instance;
|
||||
}
|
||||
|
||||
/// Returns [Location] to provide latitude and longitude.
|
||||
Future<Location> getLocation() async {
|
||||
throw UnimplementedError('getLocation() has not been implemented.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2020 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:federated_plugin_platform_interface/federated_plugin_platform_interface.dart';
|
||||
import 'package:federated_plugin_platform_interface/location_model.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
/// Implements [FederatedPluginInterface] using [MethodChannel] to fetch
|
||||
/// location from platform.
|
||||
class LocationMethodChannel extends FederatedPluginInterface {
|
||||
static const MethodChannel _methodChannel = MethodChannel('location');
|
||||
|
||||
@override
|
||||
Future<Location> getLocation() async {
|
||||
final result =
|
||||
await _methodChannel.invokeMethod<List<dynamic>>('getLocation');
|
||||
|
||||
return Location(
|
||||
longitude: result.first as double,
|
||||
latitude: result.last as double,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2020 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/// Model to hold the incoming latitude and longitude values from platform.
|
||||
class Location {
|
||||
final double latitude;
|
||||
final double longitude;
|
||||
|
||||
Location({this.latitude, this.longitude});
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0-nullsafety"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.8"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
pedantic:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.2"
|
||||
plugin_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.5"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.17"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety"
|
||||
sdks:
|
||||
dart: ">=2.9.0-18.0 <2.9.0"
|
||||
flutter: ">=1.17.0 <2.0.0"
|
||||
@@ -0,0 +1,20 @@
|
||||
name: federated_plugin_platform_interface
|
||||
description: A new Flutter package project.
|
||||
version: 0.0.1
|
||||
author:
|
||||
homepage:
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
flutter: ">=1.17.0 <2.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
plugin_platform_interface: ^1.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
pedantic: ^1.9.0
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2020 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:federated_plugin_platform_interface/location_method_channel.dart';
|
||||
import 'package:federated_plugin_platform_interface/location_model.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('MethodChannel test', () {
|
||||
final location = Location(latitude: 1.0, longitude: 2.0);
|
||||
MethodChannel('location').setMockMethodCallHandler((call) async {
|
||||
if (call.method == 'getLocation') {
|
||||
return [location.longitude, location.latitude];
|
||||
}
|
||||
});
|
||||
|
||||
test('getLocation method test', () async {
|
||||
final locationMethodChannel = LocationMethodChannel();
|
||||
final result = await locationMethodChannel.getLocation();
|
||||
expect(result.longitude, location.longitude);
|
||||
expect(result.latitude, result.latitude);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user