Skip to content

Commit ecb5aab

Browse files
[platform_channels] adds Platform Image demo (#475)
1 parent 70976ee commit ecb5aab

File tree

8 files changed

+163
-0
lines changed

8 files changed

+163
-0
lines changed
Loading

platform_channels/android/app/src/main/kotlin/dev/flutter/platform_channels/MainActivity.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ import android.hardware.Sensor
99
import android.hardware.SensorManager
1010
import io.flutter.embedding.android.FlutterActivity
1111
import io.flutter.embedding.engine.FlutterEngine
12+
import io.flutter.plugin.common.BasicMessageChannel
1213
import io.flutter.plugin.common.EventChannel
1314
import io.flutter.plugin.common.MethodChannel
15+
import io.flutter.plugin.common.StandardMessageCodec
16+
import java.io.InputStream
1417

1518
class MainActivity : FlutterActivity() {
1619
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
@@ -40,5 +43,15 @@ class MainActivity : FlutterActivity() {
4043
val accelerometerSensor: Sensor = sensorManger.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
4144
EventChannel(flutterEngine.dartExecutor, "eventChannelDemo")
4245
.setStreamHandler(AccelerometerStreamHandler(sensorManger, accelerometerSensor))
46+
47+
// Registers a MessageHandler for BasicMessageChannel to receive a message from Dart and send
48+
// image data in reply.
49+
BasicMessageChannel(flutterEngine.dartExecutor, "platformImageDemo", StandardMessageCodec())
50+
.setMessageHandler { message, reply ->
51+
if (message == "getImage") {
52+
val inputStream: InputStream = assets.open("eat_new_orleans.jpg")
53+
reply.reply(inputStream.readBytes());
54+
}
55+
}
4356
}
4457
}
69.8 KB
Loading

platform_channels/lib/main.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:flutter/material.dart';
66
import 'package:platform_channels/src/event_channel_demo.dart';
77
import 'package:platform_channels/src/method_channel_demo.dart';
8+
import 'package:platform_channels/src/platform_image_demo.dart';
89

910
void main() {
1011
runApp(PlatformChannelSample());
@@ -17,6 +18,7 @@ class PlatformChannelSample extends StatelessWidget {
1718
routes: {
1819
'/methodChannelDemo': (context) => MethodChannelDemo(),
1920
'/eventChannelDemo': (context) => EventChannelDemo(),
21+
'/platformImageDemo': (context) => PlatformImageDemo(),
2022
},
2123
title: 'Platform Channel Sample',
2224
home: HomePage(),
@@ -41,6 +43,10 @@ List<DemoInfo> demoList = [
4143
DemoInfo(
4244
'EventChannel Demo',
4345
'/eventChannelDemo',
46+
),
47+
DemoInfo(
48+
'Platform Image Demo',
49+
'/platformImageDemo',
4450
)
4551
];
4652

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2020 The Flutter team. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:typed_data';
6+
7+
import 'package:flutter/services.dart';
8+
9+
/// This class manages a [BasicMessageChannel] that can return an image loaded
10+
/// from a native asset. The [BasicMessageChannel] uses [StandardMessageCodec]
11+
/// since it supports [Uint8List], which is used to transport the image data.
12+
class PlatformImageFetcher {
13+
static final _basicMessageChannel = const BasicMessageChannel<dynamic>(
14+
'platformImageDemo', StandardMessageCodec());
15+
16+
/// Method responsible for providing the platform image.
17+
static Future<Uint8List> getImage() async {
18+
final reply = await _basicMessageChannel.send('getImage') as Uint8List;
19+
if (reply == null) {
20+
throw PlatformException(
21+
code: 'Error',
22+
message: 'Failed to load Platform Image',
23+
details: null,
24+
);
25+
}
26+
return reply;
27+
}
28+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2020 The Flutter team. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:typed_data';
6+
7+
import 'package:flutter/material.dart';
8+
import 'package:flutter/services.dart';
9+
import 'package:platform_channels/src/image_basic_message_channel.dart';
10+
11+
/// Demonstrates how to use [BasicMessageChannel] to get an image from platform.
12+
///
13+
/// The widget uses [Image.memory] to display the image obtained from the
14+
/// platform.
15+
class PlatformImageDemo extends StatefulWidget {
16+
@override
17+
_PlatformImageDemoState createState() => _PlatformImageDemoState();
18+
}
19+
20+
class _PlatformImageDemoState extends State<PlatformImageDemo> {
21+
Future<Uint8List> imageData;
22+
23+
@override
24+
Widget build(BuildContext context) {
25+
return Scaffold(
26+
appBar: AppBar(
27+
title: Text('Platform Image Demo'),
28+
),
29+
body: Center(
30+
child: Column(
31+
mainAxisAlignment: MainAxisAlignment.center,
32+
children: [
33+
Flexible(
34+
child: FractionallySizedBox(
35+
widthFactor: 1,
36+
heightFactor: 0.6,
37+
child: FutureBuilder<Uint8List>(
38+
future: imageData,
39+
builder: (context, snapshot) {
40+
if (snapshot.connectionState == ConnectionState.none) {
41+
return Placeholder();
42+
} else if (snapshot.hasError) {
43+
return Center(
44+
child: Text(snapshot.error.toString()),
45+
);
46+
} else if (snapshot.connectionState ==
47+
ConnectionState.done) {
48+
return Image.memory(
49+
snapshot.data,
50+
fit: BoxFit.fill,
51+
);
52+
}
53+
return CircularProgressIndicator();
54+
},
55+
),
56+
),
57+
),
58+
SizedBox(
59+
height: 16,
60+
),
61+
RaisedButton(
62+
onPressed: imageData != null
63+
? null
64+
: () {
65+
setState(() {
66+
imageData = PlatformImageFetcher.getImage();
67+
});
68+
},
69+
child: Text('Get Image'),
70+
)
71+
],
72+
),
73+
),
74+
);
75+
}
76+
}

platform_channels/pubspec.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ dev_dependencies:
2020

2121
flutter:
2222
uses-material-design: true
23+
assets:
24+
- assets/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2020 The Flutter team. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/material.dart';
6+
import 'package:flutter/services.dart';
7+
import 'package:flutter_test/flutter_test.dart';
8+
import 'package:platform_channels/src/platform_image_demo.dart';
9+
10+
void main() {
11+
group('Platform Image Demo tests', () {
12+
setUpAll(() {
13+
// Register a mock for MessageHandler.
14+
BasicMessageChannel<dynamic>('platformImageDemo', StandardMessageCodec())
15+
.setMockMessageHandler((dynamic message) async {
16+
var byteData = await rootBundle.load('assets/eat_new_orleans.jpg');
17+
return byteData.buffer.asUint8List();
18+
});
19+
});
20+
21+
testWidgets('Platform Image test', (tester) async {
22+
await tester.pumpWidget(MaterialApp(
23+
home: PlatformImageDemo(),
24+
));
25+
26+
// Initially a PlaceHolder is displayed when imageData is null.
27+
expect(find.byType(Placeholder), findsOneWidget);
28+
expect(find.byType(Image), findsNothing);
29+
30+
// Tap on RaisedButton to get Image.
31+
await tester.tap(find.byType(RaisedButton));
32+
await tester.pumpAndSettle();
33+
34+
expect(find.byType(Placeholder), findsNothing);
35+
expect(find.byType(Image), findsOneWidget);
36+
});
37+
});
38+
}

0 commit comments

Comments
 (0)