Skip to content

Commit

Permalink
Merge pull request #24 from faku99/master
Browse files Browse the repository at this point in the history
Basic media controls implementation.
  • Loading branch information
Lucas Elisei authored Mar 4, 2018
2 parents 815b1ab + 28186e7 commit 3e51c68
Show file tree
Hide file tree
Showing 10 changed files with 319 additions and 105 deletions.
Binary file modified example/ios/Flutter/flutter_assets/snapshot_blob.bin
Binary file not shown.
73 changes: 47 additions & 26 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,46 +14,67 @@ void main() {
runApp(new MyApp());
}

class MyApp extends StatefulWidget {
class MyApp extends StatelessWidget {
@override
_MyAppState createState() => new _MyAppState();
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Stereo Plugin Example', home: new HomeScreen());
}
}

class _MyAppState extends State<MyApp> {
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => new _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
Stereo _stereo = new Stereo();

@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text('Stereo Plugin Example'),
),
body: new Column(children: <Widget>[
new Flexible(
child: new Center(
child: new Row(children: <Widget>[
new Expanded(
child: new RaisedButton(
child: new Text('dubstep.mp3'),
onPressed: () => _playFile('dubstep.mp3'))),
new Expanded(
child: new RaisedButton(
child: new Text('pi.mp3'),
onPressed: () => _playFile('pi.mp3')))
]))),
new MediaPlayerWidget()
])));
return new Scaffold(
appBar: new AppBar(title: new Text('Stereo Plugin Example')),
body: new Column(children: <Widget>[
new Center(
heightFactor: 2.0,
child: new Text('Choose an action:',
style: new TextStyle(
fontWeight: FontWeight.bold, fontSize: 20.0))),
new Wrap(
alignment: WrapAlignment.spaceAround,
spacing: 12.0,
runSpacing: 8.0,
children: <Widget>[
new RaisedButton(
child: new Text('Play dubstep.mp3'),
onPressed: () => _playFile('dubstep.mp3')),
new RaisedButton(
child: new Text('Play pi.mp3'),
onPressed: () => _playFile('pi.mp3')),
new RaisedButton(
child: new Text('Invalid URL'),
onPressed: () => _playFile("invalid_file.mp3"))
]),
new Expanded(child: new Container()),
new Padding(
padding: new EdgeInsets.all(16.0), child: new MediaPlayerWidget())
]));
}

Future _playFile(String file) async {
await _copyFiles();

final Directory dir = await getApplicationDocumentsDirectory();

// iOS needs 'file://' to work. At the moment, we leave it here and we will
// deal with it later.
_stereo.loadItemWithURL('file://${dir.path}/$file');
try {
await _stereo.load('${dir.path}/$file');
} on StereoFileNotPlayableException {
var alert = new AlertDialog(
title: new Text('File not playable'),
content: new Text('The file you specified is not playable.'));

showDialog(context: context, child: alert);
}
}

// Don't judge the code for this method, it's for the example...
Expand Down
53 changes: 25 additions & 28 deletions example/lib/media_player_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,41 @@ class MediaPlayerWidget extends StatefulWidget {
class _MediaPlayerState extends State<MediaPlayerWidget> {
static const Icon _pauseIcon = const Icon(FontAwesomeIcons.pause);
static const Icon _playIcon = const Icon(FontAwesomeIcons.play);

bool _isPlaying = false;
static const Icon _stopIcon = const Icon(FontAwesomeIcons.stop);

Stereo _stereo = new Stereo();

@override
void initState() {
super.initState();

Stereo.togglePlayPauseCallback = () => _togglePlaying();
_stereo.isPlayingNotifier.addListener(() => setState(() {}));
}

@override
Widget build(BuildContext context) {
return new Container(
height: 80.0,
child: new Row(children: <Widget>[
new Expanded(
child: new IconButton(
icon: const Icon(FontAwesomeIcons.stepBackward),
iconSize: 30.0,
onPressed: null)),
new Expanded(
child: new IconButton(
icon: _isPlaying ? _pauseIcon : _playIcon,
iconSize: 50.0,
onPressed: () => _togglePlaying())),
new Expanded(
child: new IconButton(
icon: const Icon(FontAwesomeIcons.stepForward),
iconSize: 30.0,
onPressed: null))
]));
}

void _togglePlaying() {
_stereo
.togglePlaying()
.then((bool state) => setState(() => _isPlaying = state));
return new Column(children: <Widget>[
new Wrap(
alignment: WrapAlignment.spaceAround,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 12.0,
runSpacing: 8.0,
children: <Widget>[
new IconButton(
icon: _playIcon, iconSize: 30.0, onPressed: () => _stereo.play()),
new IconButton(
icon: _pauseIcon,
iconSize: 30.0,
onPressed: () => _stereo.pause()),
new IconButton(
icon: _stopIcon, iconSize: 30.0, onPressed: () => _stereo.stop()),
new IconButton(
icon: _stereo.isPlaying ? _pauseIcon : _playIcon,
iconSize: 50.0,
onPressed: null)
],
),
new LinearProgressIndicator(value: 0.5)
]);
}
}
16 changes: 15 additions & 1 deletion example/stereo_example_android.iml
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android" name="Android">
<configuration>
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/android/gen" />
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/android/gen" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/android/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/android/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/android/assets" />
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/android/libs" />
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/android/proguard_logs" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$/android">
<sourceFolder url="file://$MODULE_DIR$/android/app/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/android/gen" isTestSource="false" generated="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="Android API 26 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Flutter for Android" level="project" />
</component>
Expand Down
11 changes: 0 additions & 11 deletions example/test/widget_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,5 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:stereo_example/main.dart';

void main() {
testWidgets('Verify Platform version', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(new MyApp());

// Verify that platform version is retrieved.
expect(
find.byWidgetPredicate(
(Widget widget) =>
widget is Text && widget.data.startsWith('Running on:'),
),
findsOneWidget);
});
}
104 changes: 99 additions & 5 deletions src/android/src/main/java/com/twofind/stereo/StereoPlugin.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,123 @@
package com.twofind.stereo;

import android.media.MediaPlayer;
import android.net.Uri;
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.MethodCall;
import io.flutter.plugin.common.PluginRegistry.Registrar;

import java.io.IOException;

/**
* StereoPlugin
*/
public class StereoPlugin implements MethodCallHandler {
private MediaPlayer mediaPlayer;

/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "stereo");
final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.twofind.stereo");
channel.setMethodCallHandler(new StereoPlugin());
}

@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else {
// isPlaying() method.
if (call.method.equals("app.isPlaying")) {
result.success(isPlaying());
}
// load() method.
else if (call.method.equals("app.load")) {
if (call.arguments != null) {
if (!(call.arguments instanceof String)) {
result.error("WRONG_FORMAT", "The specified URL must be a string.", null);
}

String path = (String)call.arguments;

result.success(load(path));
} else {
result.error("NO_URL", "No URL was specified.", null);
}
}
// pause() method.
else if (call.method.equals("app.pause")) {
pause();

result.success(null);
}
// play() method.
else if (call.method.equals("app.play")) {
play();

result.success(null);
}
// stop() method.
else if (call.method.equals("app.stop")) {
stop();

result.success(null);
}
// Method not implemented.
else {
result.notImplemented();
}
}

private boolean isPlaying() {
if (mediaPlayer != null) {
return mediaPlayer.isPlaying();
}

return false;
}

private int load(String path) {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}

mediaPlayer = new MediaPlayer();

try {
mediaPlayer.setDataSource(path);
} catch (IOException e) {
return 1;
}

try {
mediaPlayer.prepare();
} catch (IOException e) {
return 1;
}

return 0;
}

private void pause() {
if (mediaPlayer != null) {
mediaPlayer.pause();
}
}

private void play() {
if (mediaPlayer != null) {
mediaPlayer.start();
}
}

private void stop() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();

mediaPlayer = null;
}
}
}
Loading

0 comments on commit 3e51c68

Please sign in to comment.