diff --git a/app/build.gradle b/app/build.gradle index 9eabffc..49b4718 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.smedic.tubtub" minSdkVersion 16 targetSdkVersion 25 - versionCode 9 - versionName "1.8" + versionCode 10 + versionName "1.9" } buildTypes { @@ -45,9 +45,9 @@ dependencies { testCompile 'junit:junit:4.12' compile(name: 'color_picker_library-release', ext: 'aar') compile 'com.android.support:appcompat-v7' - compile 'com.android.support:design:25.1.1' - compile 'com.android.support:support-v4:25.1.1' - compile 'com.android.support:recyclerview-v7:25.1.1' + compile 'com.android.support:design:25.2.0' + compile 'com.android.support:support-v4:25.2.0' + compile 'com.android.support:recyclerview-v7:25.2.0' compile 'com.google.android.gms:play-services-auth:10.2.0' compile files('libs/google-api-client-android-1.21.0.jar') compile files('libs/google-http-client-android-1.21.0.jar') @@ -56,10 +56,10 @@ dependencies { compile files('libs/google-http-client-jackson2-1.21.0.jar') compile files('libs/google-oauth-client-1.21.0.jar') compile files('libs/jackson-core-2.1.3.jar') - compile files('libs/jsr305-1.3.9.jar') compile files('libs/google-api-services-youtube-v3-rev160-1.21.0.jar') compile files('libs/picasso-2.5.2.jar') compile 'com.github.HaarigerHarald:android-youtubeExtractor:master-SNAPSHOT' compile 'pub.devrel:easypermissions:0.3.0' - compile 'com.android.support:cardview-v7:25.1.1' + compile 'com.facebook.network.connectionclass:connectionclass:1.0.1' //this lib include jsr501 + compile 'com.android.support:cardview-v7:25.2.0' } diff --git a/app/libs/jsr305-1.3.9.jar b/app/libs/jsr305-1.3.9.jar deleted file mode 100644 index a9afc66..0000000 Binary files a/app/libs/jsr305-1.3.9.jar and /dev/null differ diff --git a/app/src/main/java/com/smedic/tubtub/BackgroundAudioService.java b/app/src/main/java/com/smedic/tubtub/BackgroundAudioService.java index 1748b83..124414b 100644 --- a/app/src/main/java/com/smedic/tubtub/BackgroundAudioService.java +++ b/app/src/main/java/com/smedic/tubtub/BackgroundAudioService.java @@ -37,6 +37,9 @@ import android.util.SparseArray; import android.widget.Toast; +import com.facebook.network.connectionclass.ConnectionClassManager; +import com.facebook.network.connectionclass.ConnectionQuality; +import com.facebook.network.connectionclass.DeviceBandwidthSampler; import com.smedic.tubtub.model.ItemType; import com.smedic.tubtub.model.YouTubeVideo; import com.smedic.tubtub.utils.Config; @@ -45,7 +48,6 @@ import java.io.IOException; import java.util.ArrayList; -import java.util.ListIterator; import at.huber.youtubeExtractor.VideoMeta; import at.huber.youtubeExtractor.YouTubeExtractor; @@ -75,14 +77,14 @@ public class BackgroundAudioService extends Service implements MediaPlayer.OnCom private YouTubeVideo videoItem; private boolean isStarting = false; + private int currentSongIndex = 0; private ArrayList youTubeVideos; - private ListIterator iterator; private NotificationCompat.Builder builder = null; - private boolean nextWasCalled = false; - private boolean previousWasCalled = false; + private DeviceBandwidthSampler deviceBandwidthSampler; + private ConnectionQuality connectionQuality = ConnectionQuality.MODERATE; @Override public IBinder onBind(Intent intent) { @@ -98,6 +100,7 @@ public void onCreate() { mMediaPlayer.setOnPreparedListener(this); initMediaSessions(); initPhoneCallListener(); + deviceBandwidthSampler = DeviceBandwidthSampler.getInstance(); } @Override @@ -115,6 +118,7 @@ public void onCallStateChanged(int state, String incomingNumber) { pauseVideo(); } else if (state == TelephonyManager.CALL_STATE_IDLE) { //Not in call: Play music + Log.d(TAG, "onCallStateChanged: "); resumeVideo(); } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) { //A call is dialing, active or on hold @@ -129,6 +133,11 @@ public void onCallStateChanged(int state, String incomingNumber) { } } + @Override + public void onDestroy() { + super.onDestroy(); + } + /** * Handles intent (player options play/pause/stop...) * @@ -177,9 +186,9 @@ private void handleMedia(Intent intent) { mediaType = ItemType.YOUTUBE_MEDIA_TYPE_PLAYLIST; youTubeVideos = (ArrayList) intent.getSerializableExtra(Config.YOUTUBE_TYPE_PLAYLIST); int startPosition = intent.getIntExtra(Config.YOUTUBE_TYPE_PLAYLIST_VIDEO_POS, 0); - - iterator = youTubeVideos.listIterator(startPosition); - playNext(); + videoItem = youTubeVideos.get(startPosition); + currentSongIndex = startPosition; + playVideo(); break; default: Log.d(TAG, "Unknown command"); @@ -371,17 +380,13 @@ private void playNext() { return; } - if (previousWasCalled) { - previousWasCalled = false; - iterator.next(); + if (youTubeVideos.size() > currentSongIndex + 1) { + currentSongIndex++; + } else { //play 1st song + currentSongIndex = 0; } - if (!iterator.hasNext()) { - iterator = youTubeVideos.listIterator(); - } - - videoItem = iterator.next(); - nextWasCalled = true; + videoItem = youTubeVideos.get(currentSongIndex); playVideo(); } @@ -395,17 +400,12 @@ private void playPrevious() { return; } - if (nextWasCalled) { - iterator.previous(); - nextWasCalled = false; - } - - if (!iterator.hasPrevious()) { - iterator = youTubeVideos.listIterator(youTubeVideos.size()); + if (currentSongIndex - 1 >= 0) { + currentSongIndex--; + } else { //play last song + currentSongIndex = youTubeVideos.size() - 1; } - - videoItem = iterator.previous(); - previousWasCalled = true; + videoItem = youTubeVideos.get(youTubeVideos.size() - 1); playVideo(); } @@ -430,7 +430,7 @@ private void pauseVideo() { * Resumes video */ private void resumeVideo() { - if (mMediaPlayer != null) { + if (mMediaPlayer != null && mMediaPlayer.isPlaying()) { mMediaPlayer.start(); } } @@ -462,19 +462,44 @@ private void stopPlayer() { /** * Get the best available audio stream + *

+ * Itags: + * 141 - mp4a - stereo, 44.1 KHz 256 Kbps + * 251 - webm - stereo, 48 KHz 160 Kbps + * 140 - mp4a - stereo, 44.1 KHz 128 Kbps + * 17 - mp4 - stereo, 44.1 KHz 96-100 Kbps * * @param ytFiles Array of available streams * @return Audio stream with highest bitrate */ private YtFile getBestStream(SparseArray ytFiles) { - if (ytFiles.get(141) != null) { - return ytFiles.get(141); //mp4a - stereo, 44.1 KHz 256 Kbps - } else if (ytFiles.get(251) != null) { - return ytFiles.get(251); //webm - stereo, 48 KHz 160 Kbps - } else if (ytFiles.get(140) != null) { - return ytFiles.get(140); //mp4a - stereo, 44.1 KHz 128 Kbps + + connectionQuality = ConnectionClassManager.getInstance().getCurrentBandwidthQuality(); + int[] itags = new int[]{251, 141, 140, 17}; + + if (connectionQuality != null && connectionQuality != ConnectionQuality.UNKNOWN) { + switch (connectionQuality) { + case POOR: + itags = new int[]{17, 140, 251, 141}; + break; + case MODERATE: + itags = new int[]{251, 141, 140, 17}; + break; + case GOOD: + case EXCELLENT: + itags = new int[]{141, 251, 140, 17}; + break; + } } - return ytFiles.get(17); //mp4 - stereo, 44.1 KHz 96-100 Kbps + + if (ytFiles.get(itags[0]) != null) { + return ytFiles.get(itags[0]); + } else if (ytFiles.get(itags[1]) != null) { + return ytFiles.get(itags[1]); + } else if (ytFiles.get(itags[2]) != null) { + return ytFiles.get(itags[2]); + } + return ytFiles.get(itags[3]); } /** @@ -482,6 +507,8 @@ private YtFile getBestStream(SparseArray ytFiles) { */ private void extractUrlAndPlay() { String youtubeLink = Config.YOUTUBE_BASE_URL + videoItem.getId(); + deviceBandwidthSampler.startSampling(); + new YouTubeExtractor(this) { @Override protected void onExtractionComplete(SparseArray ytFiles, VideoMeta videoMeta) { @@ -491,6 +518,7 @@ protected void onExtractionComplete(SparseArray ytFiles, VideoMeta video Toast.LENGTH_SHORT).show(); return; } + deviceBandwidthSampler.stopSampling(); YtFile ytFile = getBestStream(ytFiles); try { if (mMediaPlayer != null) { @@ -500,8 +528,7 @@ protected void onExtractionComplete(SparseArray ytFiles, VideoMeta video mMediaPlayer.prepare(); mMediaPlayer.start(); - Toast.makeText(YTApplication.getAppContext(), videoMeta.getTitle(), - Toast.LENGTH_SHORT).show(); + Toast.makeText(YTApplication.getAppContext(), videoItem.getTitle(), Toast.LENGTH_SHORT).show(); } } catch (IOException io) { io.printStackTrace(); diff --git a/app/src/main/java/com/smedic/tubtub/fragments/SearchFragment.java b/app/src/main/java/com/smedic/tubtub/fragments/SearchFragment.java index 1acd325..be7701b 100644 --- a/app/src/main/java/com/smedic/tubtub/fragments/SearchFragment.java +++ b/app/src/main/java/com/smedic/tubtub/fragments/SearchFragment.java @@ -163,6 +163,7 @@ public void onFavoriteClicked(YouTubeVideo video, boolean isChecked) { @Override public void onItemClick(YouTubeVideo video) { YouTubeSqlDb.getInstance().videos(YouTubeSqlDb.VIDEOS_TYPE.RECENTLY_WATCHED).create(video); - itemSelected.onVideoSelected(video); + //itemSelected.onVideoSelected(video); + itemSelected.onPlaylistSelected(searchResultsList, searchResultsList.indexOf(video)); } } diff --git a/app/src/main/java/com/smedic/tubtub/youtube/YouTubeVideosLoader.java b/app/src/main/java/com/smedic/tubtub/youtube/YouTubeVideosLoader.java index b0b905f..9ae4a15 100644 --- a/app/src/main/java/com/smedic/tubtub/youtube/YouTubeVideosLoader.java +++ b/app/src/main/java/com/smedic/tubtub/youtube/YouTubeVideosLoader.java @@ -69,14 +69,18 @@ public List loadInBackground() { item.setId(searchResults.get(i).getId().getVideoId()); //video info if (videoResults.get(i) != null) { - BigInteger viewsNumber = videoResults.get(i).getStatistics().getViewCount(); - String viewsFormatted = NumberFormat.getIntegerInstance().format(viewsNumber) + " views"; - item.setViewCount(viewsFormatted); - String isoTime = videoResults.get(i).getContentDetails().getDuration(); - String time = Utils.convertISO8601DurationToNormalTime(isoTime); - item.setDuration(time); + if (videoResults.get(i).getStatistics() != null) { + BigInteger viewsNumber = videoResults.get(i).getStatistics().getViewCount(); + String viewsFormatted = NumberFormat.getIntegerInstance().format(viewsNumber) + " views"; + item.setViewCount(viewsFormatted); + } + if (videoResults.get(i).getContentDetails() != null) { + String isoTime = videoResults.get(i).getContentDetails().getDuration(); + String time = Utils.convertISO8601DurationToNormalTime(isoTime); + item.setDuration(time); + } } else { - item.setDuration("NA"); + item.setDuration(""); } //add to the list diff --git a/app/src/main/res/layout/playlist_item.xml b/app/src/main/res/layout/playlist_item.xml index 6604f63..08aa20c 100644 --- a/app/src/main/res/layout/playlist_item.xml +++ b/app/src/main/res/layout/playlist_item.xml @@ -17,6 +17,7 @@ android:descendantFocusability="blocksDescendants" android:orientation="horizontal" android:paddingBottom="4dp" + android:weightSum="100" android:paddingTop="4dp"> - + android:layout_height="wrap_content"> - + - + - - + - + + - + - + - + - + - - + + + + + \ No newline at end of file