[Android] [PATCH 3/5] Remote playback: add the RemotePlaybackActivity to control remote playback devices such as a Chromecast

Adrien Maglo magsoft at gmail.com
Tue Jul 8 16:33:47 CEST 2014


---
 vlc-android/AndroidManifest.xml                    |   4 +
 vlc-android/res/values/strings.xml                 |   4 +
 .../vlc/gui/video/RemotePlaybackActivity.java      | 241 +++++++++++++++++++++
 3 files changed, 249 insertions(+)
 create mode 100644 vlc-android/src/org/videolan/vlc/gui/video/RemotePlaybackActivity.java

diff --git a/vlc-android/AndroidManifest.xml b/vlc-android/AndroidManifest.xml
index dba015c..4311b54 100644
--- a/vlc-android/AndroidManifest.xml
+++ b/vlc-android/AndroidManifest.xml
@@ -368,6 +368,10 @@
                 <data android:pathPattern=".*\\.XM" />
             </intent-filter>
         </activity>
+        <activity
+            android:name=".gui.video.RemotePlaybackActivity"
+            android:configChanges="orientation|screenSize"
+            android:theme="@style/Theme.VLC.Fullscreen" />
 
         <service android:name="org.videolan.vlc.audio.AudioService" />
 
diff --git a/vlc-android/res/values/strings.xml b/vlc-android/res/values/strings.xml
index d9a2a11..a31ca4b 100644
--- a/vlc-android/res/values/strings.xml
+++ b/vlc-android/res/values/strings.xml
@@ -191,6 +191,10 @@
     <string name="about_copyright" translatable="false">Copyleft © 1996–2014 by VideoLAN.\n</string>
     <string name="authors" translatable="false">Edward Wang, Sébastien Toque, Adrien Maglo, Jean-Baptiste Kempf, Ludovic Fauvet, Rafaël Carré, Alexandre Perraud, Michael Merg, Martin Storsjö, Rémi Duraffort, Dominique Martinet, Jean-Philippe André, Felix Abecassis, Christoph Miebach, Hugo Beauzée-Luyssen, Felix Paul Kühne, John Mooring, Pavol Rusnak, Rohit Yadav, Tanguy Pruvot, Thomas Clavier, Asad Mehmood, Garret Kelly, Philipp Dreimann, Walter Heck.</string>
 
+    <!-- RemotePlayback -->
+    <string name="no_cast_device">No cast device found.</string>
+    <string name="check_remote">Check your wifi and cast device.</string>
+
     <!-- Preferences -->
     <string name="preferences">Preferences</string>
 
diff --git a/vlc-android/src/org/videolan/vlc/gui/video/RemotePlaybackActivity.java b/vlc-android/src/org/videolan/vlc/gui/video/RemotePlaybackActivity.java
new file mode 100644
index 0000000..4f5b94e
--- /dev/null
+++ b/vlc-android/src/org/videolan/vlc/gui/video/RemotePlaybackActivity.java
@@ -0,0 +1,241 @@
+/*****************************************************************************
+ * RemotePlaybackActivity.java
+ *****************************************************************************
+ * Copyright © 2011-2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.vlc.gui.video;
+
+import java.util.List;
+import org.videolan.vlc.R;
+import org.videolan.vlc.RemotePlaybackHTTPServer;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v7.app.MediaRouteChooserDialog;
+import android.support.v7.media.MediaControlIntent;
+import android.support.v7.media.MediaItemStatus;
+import android.support.v7.media.MediaRouteSelector;
+import android.support.v7.media.MediaRouter;
+import android.support.v7.media.MediaRouter.RouteInfo;
+import android.support.v7.media.MediaSessionStatus;
+import android.support.v7.media.RemotePlaybackClient;
+import android.support.v7.media.RemotePlaybackClient.ItemActionCallback;
+import android.support.v7.media.RemotePlaybackClient.SessionActionCallback;
+import android.support.v7.media.RemotePlaybackClient.StatusCallback;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+
+public class RemotePlaybackActivity extends Activity {
+
+    public final static String TAG = "VLC/RemotePlaybackActivity";
+
+    private MediaRouteSelector mSelector;
+    private MediaRouter mMediaRouter;
+    private RemotePlaybackClient mRemotePlaybackClient;
+    private RouteInfo mRoute;
+    private RemotePlaybackHTTPServer mServer;
+
+    private ImageButton mPlayPause;
+    private ImageButton mRouteChooser;
+    private TextView mDeviceName;
+    private TextView mDeviceType;
+
+    private enum State {STOPED, PLAYING, PAUSED}
+    private State mState = State.STOPED;
+    private String mItemLocation;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.remote_playback);
+
+        mPlayPause = (ImageButton) findViewById(R.id.play_pause);
+        mRouteChooser = (ImageButton) findViewById(R.id.route_chooser);
+        mDeviceName = (TextView) findViewById(R.id.device_name);
+        mDeviceType = (TextView) findViewById(R.id.device_type);
+
+        mItemLocation = getIntent().getExtras().getString("itemLocation");
+
+        mSelector = new MediaRouteSelector.Builder()
+            .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
+            .build();
+
+        mMediaRouter = MediaRouter.getInstance(this);
+    }
+
+
+    @Override
+    public void onStart() {
+        List<RouteInfo> routes = mMediaRouter.getRoutes();
+        for (RouteInfo route : routes)
+            if (route.getPlaybackType() == RouteInfo.PLAYBACK_TYPE_REMOTE) {
+                if (!route.isSelected())
+                    mMediaRouter.selectRoute(route);
+                else
+                    setCurrentRoute(route);
+            }
+
+        mMediaRouter.addCallback(mSelector, mMediaRouterCallback,
+                MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
+
+        super.onStart();
+    }
+
+
+    @Override
+    public void onPause() {
+        stop();
+        super.onPause();
+    }
+
+    @Override
+    public void onStop() {
+        mMediaRouter.removeCallback(mMediaRouterCallback);
+        super.onStop();
+    }
+
+
+    private final MediaRouter.Callback mMediaRouterCallback =
+            new MediaRouter.Callback() {
+
+        @Override
+        public void onRouteAdded(MediaRouter router, RouteInfo route) {
+            Log.d(TAG, "Route added.");
+            if (mRoute == null)
+                router.selectRoute(route);
+        }
+
+        @Override
+        public void onRouteSelected(MediaRouter router, RouteInfo route) {
+            Log.d(TAG, "Route selected.");
+            setCurrentRoute(route);
+        }
+
+        @Override
+        public void onRouteUnselected(MediaRouter router, RouteInfo route) {
+            if (route == mRoute) {
+                Log.d(TAG, "Route unselected.");
+                stop();
+                setCurrentRoute(null);
+            }
+        }
+    };
+
+
+    private void setCurrentRoute(RouteInfo route) {
+        mRoute = route;
+        mDeviceName.setText(route == null ?
+                getString(R.string.no_cast_device) : mRoute.getName());
+        mDeviceType.setText(route == null ?
+                getString(R.string.check_remote) : mRoute.getDescription());
+    }
+
+
+    private void play(RouteInfo route) {
+        if (route == null)
+            return;
+
+        if (mRemotePlaybackClient != null)
+            throw new IllegalStateException("Remote playback client already instantiated.");
+
+        mServer = new RemotePlaybackHTTPServer(mItemLocation);
+        mServer.start();
+        mRemotePlaybackClient = new RemotePlaybackClient(this, route);
+
+        String ip = mServer.getIPAddress(true);
+        if (ip == null)
+            throw new IllegalStateException("Cannot get device's IP address.");
+
+        mState = State.PLAYING;
+        mPlayPause.setBackgroundResource(R.drawable.ic_pause_circle_big_o);
+        mRouteChooser.setVisibility(ImageButton.GONE);
+
+        mRemotePlaybackClient.play(Uri.parse("http://" + ip + ":4212/video"),
+                "video/mp4", new Bundle(), 0, new Bundle(), new ItemActionCallback() {
+
+            @Override
+            public void onResult(Bundle data, String sessionId,
+                    MediaSessionStatus sessionStatus,
+                    String itemId, MediaItemStatus itemStatus) {
+                Log.d(TAG, "Playback command successfully sent for item: "
+                      + itemId + " - " + sessionId);
+            }
+
+            @Override
+            public void onError(String error, int code, Bundle data) {
+                Log.d(TAG, "Playback command error: "+ code +" - "+ error);
+                stop();
+            }
+        });
+    }
+
+
+    private void stop() {
+        if (mRemotePlaybackClient != null) {
+            mRemotePlaybackClient.stop(new Bundle(), new SessionActionCallback() {});
+            mMediaRouter.removeRemoteControlClient(mRemotePlaybackClient);
+            mRemotePlaybackClient.release();
+            mRemotePlaybackClient = null;
+            mServer.stopServer();
+        }
+        mState = State.STOPED;
+        mPlayPause.setBackgroundResource(R.drawable.ic_play_circle_big_o);
+        mRouteChooser.setVisibility(ImageButton.VISIBLE);
+    }
+
+
+    private void pause() {
+        mRemotePlaybackClient.pause(new Bundle(), new SessionActionCallback() {});
+        mState = State.PAUSED;
+        mPlayPause.setBackgroundResource(R.drawable.ic_play_circle_big_o);
+    }
+
+
+    private void resume() {
+        mRemotePlaybackClient.resume(new Bundle(), new SessionActionCallback() {});
+        mState = State.PLAYING;
+        mPlayPause.setBackgroundResource(R.drawable.ic_pause_circle_big_o);
+    }
+
+
+    public void playPause(View v) {
+        switch (mState) {
+        case STOPED:
+            play(mRoute);
+            break;
+        case PLAYING:
+            pause();
+            break;
+        case PAUSED:
+            resume();
+            break;
+        }
+    }
+
+
+    public void showRouteChooser(View v) {
+        MediaRouteChooserDialog d = new MediaRouteChooserDialog(this);
+        d.setRouteSelector(mSelector);
+        d.show();
+    }
+
+}
-- 
1.9.1



More information about the Android mailing list