Skip to content

Commit

Permalink
Allow easier ExoPlayer/Cast integration
Browse files Browse the repository at this point in the history
This CL adds the fundamental pieces for ExoPlayer/Cast integration and includes a
demo app to showcase this functionality. However, media queues should be supported
in the first release of this extension.

Issue:google#2283

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=165576892
  • Loading branch information
AquilesCanta authored and ojw28 committed Aug 17, 2017
1 parent 1cfd246 commit 04d76fa
Show file tree
Hide file tree
Showing 25 changed files with 1,534 additions and 2 deletions.
1 change: 1 addition & 0 deletions constants.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ project.ext {
buildToolsVersion = '26'
testSupportLibraryVersion = '0.5'
supportLibraryVersion = '26.0.1'
playServicesLibraryVersion = '11.0.2'
dexmakerVersion = '1.2'
mockitoVersion = '1.9.5'
releaseVersion = 'r2.5.1'
Expand Down
2 changes: 2 additions & 0 deletions core_settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ include modulePrefix + 'extension-ffmpeg'
include modulePrefix + 'extension-flac'
include modulePrefix + 'extension-gvr'
include modulePrefix + 'extension-ima'
include modulePrefix + 'extension-cast'
include modulePrefix + 'extension-mediasession'
include modulePrefix + 'extension-okhttp'
include modulePrefix + 'extension-opus'
Expand All @@ -46,6 +47,7 @@ project(modulePrefix + 'extension-ffmpeg').projectDir = new File(rootDir, 'exten
project(modulePrefix + 'extension-flac').projectDir = new File(rootDir, 'extensions/flac')
project(modulePrefix + 'extension-gvr').projectDir = new File(rootDir, 'extensions/gvr')
project(modulePrefix + 'extension-ima').projectDir = new File(rootDir, 'extensions/ima')
project(modulePrefix + 'extension-cast').projectDir = new File(rootDir, 'extensions/cast')
project(modulePrefix + 'extension-mediasession').projectDir = new File(rootDir, 'extensions/mediasession')
project(modulePrefix + 'extension-okhttp').projectDir = new File(rootDir, 'extensions/okhttp')
project(modulePrefix + 'extension-opus').projectDir = new File(rootDir, 'extensions/opus')
Expand Down
4 changes: 4 additions & 0 deletions demos/cast/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Cast demo application #

This folder contains a demo application that showcases ExoPlayer integration
with Google Cast.
51 changes: 51 additions & 0 deletions demos/cast/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
apply from: '../../constants.gradle'
apply plugin: 'com.android.application'

android {
compileSdkVersion project.ext.compileSdkVersion
buildToolsVersion project.ext.buildToolsVersion

defaultConfig {
minSdkVersion 16
targetSdkVersion project.ext.targetSdkVersion
}

buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt')
}
debug {
jniDebuggable = true
}
}

lintOptions {
// The demo app does not have translations.
disable 'MissingTranslation'
}

}

dependencies {
compile project(modulePrefix + 'library-core')
compile project(modulePrefix + 'library-dash')
compile project(modulePrefix + 'library-hls')
compile project(modulePrefix + 'library-smoothstreaming')
compile project(modulePrefix + 'library-ui')
compile project(modulePrefix + 'extension-cast')
}
43 changes: 43 additions & 0 deletions demos/cast/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.exoplayer2.castdemo"
android:versionCode="0001"
android:versionName="0.0.1">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="26"/>

<application android:label="@string/application_name" android:icon="@mipmap/ic_launcher"
android:largeHeap="true" android:allowBackup="false">

<meta-data android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.google.android.exoplayer2.ext.cast.DefaultCastOptionsProvider" />

<activity android:name="com.google.android.exoplayer2.castdemo.MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:launchMode="singleTop" android:label="@string/application_name"
android:theme="@style/Theme.AppCompat">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>

</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.castdemo;

import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.gms.cast.MediaInfo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* Utility methods and constants for the Cast demo application.
*/
/* package */ final class CastDemoUtil {

public static final String MIME_TYPE_DASH = "application/dash+xml";
public static final String MIME_TYPE_HLS = "application/vnd.apple.mpegurl";
public static final String MIME_TYPE_SS = "application/vnd.ms-sstr+xml";
public static final String MIME_TYPE_VIDEO_MP4 = MimeTypes.VIDEO_MP4;

/**
* The list of samples available in the cast demo app.
*/
public static final List<Sample> SAMPLES;

/**
* Represents a media sample.
*/
public static final class Sample {

/**
* The uri from which the media sample is obtained.
*/
public final String uri;
/**
* A descriptive name for the sample.
*/
public final String name;
/**
* The mime type of the media sample, as required by {@link MediaInfo#setContentType}.
*/
public final String type;

/**
* @param uri See {@link #uri}.
* @param name See {@link #name}.
* @param type See {@link #type}.
*/
public Sample(String uri, String name, String type) {
this.uri = uri;
this.name = name;
this.type = type;
}

@Override
public String toString() {
return name;
}

}

static {
// App samples.
ArrayList<Sample> samples = new ArrayList<>();
samples.add(new Sample("https://storage.googleapis.com/wvmedia/clear/h264/tears/tears.mpd",
"DASH (clear,MP4,H264)", MIME_TYPE_DASH));
samples.add(new Sample("https://commondatastorage.googleapis.com/gtv-videos-bucket/CastVideos/"
+ "hls/TearsOfSteel.m3u8", "Tears of Steel (HLS)", MIME_TYPE_HLS));
samples.add(new Sample("https://html5demos.com/assets/dizzy.mp4", "Dizzy (MP4)",
MIME_TYPE_VIDEO_MP4));


SAMPLES = Collections.unmodifiableList(samples);

}

private CastDemoUtil() {}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.castdemo;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.ext.cast.CastPlayer;
import com.google.android.exoplayer2.ui.PlaybackControlView;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.util.Util;
import com.google.android.gms.cast.framework.CastButtonFactory;

/**
* An activity that plays video using {@link SimpleExoPlayer} and {@link CastPlayer}.
*/
public class MainActivity extends AppCompatActivity {

private SimpleExoPlayerView simpleExoPlayerView;
private PlaybackControlView castControlView;
private PlayerManager playerManager;

// Activity lifecycle methods.

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main_activity);

simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
simpleExoPlayerView.requestFocus();

castControlView = (PlaybackControlView) findViewById(R.id.cast_control_view);

ListView sampleList = (ListView) findViewById(R.id.sample_list);
sampleList.setAdapter(new SampleListAdapter());
sampleList.setOnItemClickListener(new SampleClickListener());
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu, menu);
CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), menu,
R.id.media_route_menu_item);
return true;
}

@Override
public void onStart() {
super.onStart();
if (Util.SDK_INT > 23) {
setupPlayerManager();
}
}

@Override
public void onResume() {
super.onResume();
if ((Util.SDK_INT <= 23)) {
setupPlayerManager();
}
}

@Override
public void onPause() {
super.onPause();
if (Util.SDK_INT <= 23) {
releasePlayerManager();
}
}

@Override
public void onStop() {
super.onStop();
if (Util.SDK_INT > 23) {
releasePlayerManager();
}
}

// Activity input.

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// If the event was not handled then see if the player view can handle it.
return super.dispatchKeyEvent(event) || playerManager.dispatchKeyEvent(event);
}

// Internal methods.

private void setupPlayerManager() {
playerManager = new PlayerManager(simpleExoPlayerView, castControlView,
getApplicationContext());
}

private void releasePlayerManager() {
playerManager.release();
playerManager = null;
}

// User controls.

private final class SampleListAdapter extends ArrayAdapter<CastDemoUtil.Sample> {

public SampleListAdapter() {
super(getApplicationContext(), android.R.layout.simple_list_item_1, CastDemoUtil.SAMPLES);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
view.setBackgroundColor(Color.WHITE);
return view;
}

}

private class SampleClickListener implements AdapterView.OnItemClickListener {

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (parent.getSelectedItemPosition() != position) {
CastDemoUtil.Sample currentSample = CastDemoUtil.SAMPLES.get(position);
playerManager.setCurrentSample(currentSample, 0, true);
}
}

}

}
Loading

0 comments on commit 04d76fa

Please sign in to comment.