mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-30 23:03:00 +00:00 
			
		
		
		
	Merge branch 'backgroundPlayback'
This commit is contained in:
		| @@ -2,8 +2,8 @@ | |||||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|     xmlns:tools="http://schemas.android.com/tools" |     xmlns:tools="http://schemas.android.com/tools" | ||||||
|     package="org.schabi.newpipe" > |     package="org.schabi.newpipe" > | ||||||
|  |     <uses-permission android:name= "android.permission.INTERNET" /> | ||||||
|     <uses-permission android:name="android.permission.INTERNET" /> |     <uses-permission android:name= "android.permission.WAKE_LOCK" /> | ||||||
|     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> |     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> | ||||||
|     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | ||||||
|     <application |     <application | ||||||
| @@ -74,6 +74,12 @@ | |||||||
|             android:parentActivityName=".VideoItemDetailActivity" |             android:parentActivityName=".VideoItemDetailActivity" | ||||||
|             tools:ignore="UnusedAttribute"> |             tools:ignore="UnusedAttribute"> | ||||||
|         </activity> |         </activity> | ||||||
|  |         <!--TODO: make label a translatable string --> | ||||||
|  |         <service | ||||||
|  |             android:name=".BackgroundPlayer" | ||||||
|  |             android:label="NewPipe Background Player" | ||||||
|  |             android:exported="false" > | ||||||
|  |         </service> | ||||||
|         <activity |         <activity | ||||||
|             android:name=".SettingsActivity" |             android:name=".SettingsActivity" | ||||||
|             android:label="@string/title_activity_settings" > |             android:label="@string/title_activity_settings" > | ||||||
|   | |||||||
| @@ -120,6 +120,9 @@ class ActionBarHandler { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         else { | ||||||
|  |             Log.e(TAG, "FAILED to set audioStream value!"); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void selectFormatItem(int i) { |     private void selectFormatItem(int i) { | ||||||
| @@ -136,7 +139,7 @@ class ActionBarHandler { | |||||||
|         MenuItem castItem = menu.findItem(R.id.action_play_with_kodi); |         MenuItem castItem = menu.findItem(R.id.action_play_with_kodi); | ||||||
|  |  | ||||||
|         castItem.setVisible(defaultPreferences |         castItem.setVisible(defaultPreferences | ||||||
|                 .getBoolean(activity.getString(R.string.showPlayWidthKodiPreference), false)); |                 .getBoolean(activity.getString(R.string.showPlayWithKodiPreference), false)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean onItemSelected(MenuItem item) { |     public boolean onItemSelected(MenuItem item) { | ||||||
| @@ -184,7 +187,7 @@ class ActionBarHandler { | |||||||
|         // ----------- THE MAGIC MOMENT --------------- |         // ----------- THE MAGIC MOMENT --------------- | ||||||
|         if(!videoTitle.isEmpty()) { |         if(!videoTitle.isEmpty()) { | ||||||
|             if (PreferenceManager.getDefaultSharedPreferences(activity) |             if (PreferenceManager.getDefaultSharedPreferences(activity) | ||||||
|                     .getBoolean(activity.getString(R.string.useExternalPlayer), false)) { |                     .getBoolean(activity.getString(R.string.useExternalVideoPlayer), false)) { | ||||||
|  |  | ||||||
|                 // External Player |                 // External Player | ||||||
|                 Intent intent = new Intent(); |                 Intent intent = new Intent(); | ||||||
| @@ -293,14 +296,32 @@ class ActionBarHandler { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void playAudio() { |     public void playAudio() { | ||||||
|         Intent intent = new Intent(); |  | ||||||
|  |         boolean externalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity) | ||||||
|  |                 .getBoolean(activity.getString(R.string.useExternalAudioPlayer), false); | ||||||
|  |         Intent intent; | ||||||
|  |         if (!externalAudioPlayer)//internal (background) music player: explicit intent | ||||||
|  |         { | ||||||
|  |             intent = new Intent(activity, BackgroundPlayer.class); | ||||||
|  |  | ||||||
|  |             intent.setAction(Intent.ACTION_VIEW); | ||||||
|  |             Log.i(TAG, "audioStream is null:" + (audioStream == null)); | ||||||
|  |             Log.i(TAG, "audioStream.url is null:"+(audioStream.url==null)); | ||||||
|  |             intent.setDataAndType(Uri.parse(audioStream.url), | ||||||
|  |                     MediaFormat.getMimeById(audioStream.format)); | ||||||
|  |             intent.putExtra(Intent.EXTRA_TITLE, videoTitle); | ||||||
|  |             intent.putExtra("title", videoTitle); | ||||||
|  |             activity.startService(intent); | ||||||
|  |         } else { | ||||||
|  |             intent = new Intent(); | ||||||
|             try { |             try { | ||||||
|                 intent.setAction(Intent.ACTION_VIEW); |                 intent.setAction(Intent.ACTION_VIEW); | ||||||
|                 intent.setDataAndType(Uri.parse(audioStream.url), |                 intent.setDataAndType(Uri.parse(audioStream.url), | ||||||
|                         MediaFormat.getMimeById(audioStream.format)); |                         MediaFormat.getMimeById(audioStream.format)); | ||||||
|                 intent.putExtra(Intent.EXTRA_TITLE, videoTitle); |                 intent.putExtra(Intent.EXTRA_TITLE, videoTitle); | ||||||
|                 intent.putExtra("title", videoTitle); |                 intent.putExtra("title", videoTitle); | ||||||
|  |  | ||||||
|                 activity.startActivity(intent);      // HERE !!! |                 activity.startActivity(intent);      // HERE !!! | ||||||
|             } catch (Exception e) { |             } catch (Exception e) { | ||||||
|                 e.printStackTrace(); |                 e.printStackTrace(); | ||||||
| @@ -326,4 +347,5 @@ class ActionBarHandler { | |||||||
|                 e.printStackTrace(); |                 e.printStackTrace(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										255
									
								
								app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,255 @@ | |||||||
|  | package org.schabi.newpipe; | ||||||
|  |  | ||||||
|  | import android.app.Notification; | ||||||
|  | import android.app.NotificationManager; | ||||||
|  | import android.app.PendingIntent; | ||||||
|  | import android.app.Service; | ||||||
|  | import android.content.BroadcastReceiver; | ||||||
|  | import android.content.Context; | ||||||
|  | import android.content.Intent; | ||||||
|  | import android.content.IntentFilter; | ||||||
|  | import android.media.AudioManager; | ||||||
|  | import android.media.MediaPlayer; | ||||||
|  | import android.net.wifi.WifiManager; | ||||||
|  | import android.os.IBinder; | ||||||
|  | import android.os.PowerManager; | ||||||
|  | import android.support.v7.app.NotificationCompat; | ||||||
|  | import android.util.Log; | ||||||
|  | import android.widget.Toast; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by Adam Howard on 08/11/15. | ||||||
|  |  * Copyright (c) Adam Howard <achdisposable1@gmail.com> 2015 | ||||||
|  |  * | ||||||
|  |  * BackgroundPlayer.java is part of NewPipe. | ||||||
|  |  * | ||||||
|  |  * NewPipe 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 3 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * NewPipe 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 NewPipe.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /**Plays the audio stream of videos in the background.*/ | ||||||
|  | public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPreparedListener*/ { | ||||||
|  |  | ||||||
|  |     private static final String TAG = BackgroundPlayer.class.toString(); | ||||||
|  |     private static final String ACTION_STOP = TAG+".STOP"; | ||||||
|  |     private static final String ACTION_PLAYPAUSE = TAG+".PLAYPAUSE"; | ||||||
|  |  | ||||||
|  |     public BackgroundPlayer() { | ||||||
|  |         super(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void onCreate() { | ||||||
|  |         /*PendingIntent pi = PendingIntent.getActivity(this, 0, | ||||||
|  |                 new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);*/ | ||||||
|  |         super.onCreate(); | ||||||
|  |     } | ||||||
|  |     @Override | ||||||
|  |     public int onStartCommand(Intent intent, int flags, int startId) { | ||||||
|  |         Toast.makeText(this, "Playing in background", Toast.LENGTH_SHORT).show();//todo:translation string | ||||||
|  |  | ||||||
|  |         String source = intent.getDataString(); | ||||||
|  |         //Log.i(TAG, "backgroundPLayer source:"+source); | ||||||
|  |         String videoTitle = intent.getStringExtra("title"); | ||||||
|  |  | ||||||
|  |         //do nearly everything in a separate thread | ||||||
|  |         PlayerThread player = new PlayerThread(source, videoTitle, this); | ||||||
|  |         player.start(); | ||||||
|  |  | ||||||
|  |         // If we get killed after returning here, don't restart | ||||||
|  |         return START_NOT_STICKY; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public IBinder onBind(Intent intent) { | ||||||
|  |         // We don't provide binding (yet?), so return null | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void onDestroy() { | ||||||
|  |         //Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private class PlayerThread extends Thread { | ||||||
|  |         MediaPlayer mediaPlayer; | ||||||
|  |         private String source; | ||||||
|  |         private String title; | ||||||
|  |         private int noteID = TAG.hashCode(); | ||||||
|  |         private BackgroundPlayer owner; | ||||||
|  |         private NotificationManager noteMgr; | ||||||
|  |         private NotificationCompat.Builder noteBuilder; | ||||||
|  |         private WifiManager.WifiLock wifiLock; | ||||||
|  |  | ||||||
|  |         public PlayerThread(String src, String title, BackgroundPlayer owner) { | ||||||
|  |             this.source = src; | ||||||
|  |             this.title = title; | ||||||
|  |             this.owner = owner; | ||||||
|  |             mediaPlayer = new MediaPlayer(); | ||||||
|  |             mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); | ||||||
|  |         } | ||||||
|  |         @Override | ||||||
|  |         public void run() { | ||||||
|  |             mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//cpu lock | ||||||
|  |             try { | ||||||
|  |                 mediaPlayer.setDataSource(source); | ||||||
|  |                 mediaPlayer.prepare(); //We are already in a separate worker thread, | ||||||
|  |                 //so calling the blocking prepare() method should be ok | ||||||
|  |  | ||||||
|  |                 //alternatively: | ||||||
|  |                 //mediaPlayer.setOnPreparedListener(this); | ||||||
|  |                 //mediaPlayer.prepareAsync(); //prepare async to not block main thread | ||||||
|  |             } catch (IOException ioe) { | ||||||
|  |                 ioe.printStackTrace(); | ||||||
|  |                 Log.e(TAG, "video source:" + source); | ||||||
|  |                 Log.e(TAG, "video title:" + title); | ||||||
|  |                 //can't do anything useful without a file to play; exit early | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             WifiManager wifiMgr = ((WifiManager)getSystemService(Context.WIFI_SERVICE)); | ||||||
|  |             wifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); | ||||||
|  |  | ||||||
|  |             mediaPlayer.setOnCompletionListener(new EndListener(wifiLock));//listen for end of video | ||||||
|  |  | ||||||
|  |             //get audio focus | ||||||
|  |             /* | ||||||
|  |             AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); | ||||||
|  |             int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, | ||||||
|  |                     AudioManager.AUDIOFOCUS_GAIN); | ||||||
|  |  | ||||||
|  |             if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { | ||||||
|  |                 // could not get audio focus. | ||||||
|  |             }*/ | ||||||
|  |             wifiLock.acquire(); | ||||||
|  |             mediaPlayer.start(); | ||||||
|  |  | ||||||
|  |             IntentFilter filter = new IntentFilter(); | ||||||
|  |             filter.setPriority(Integer.MAX_VALUE); | ||||||
|  |             filter.addAction(ACTION_PLAYPAUSE); | ||||||
|  |             filter.addAction(ACTION_STOP); | ||||||
|  |             registerReceiver(broadcastReceiver, filter); | ||||||
|  |  | ||||||
|  |             PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID, new Intent(ACTION_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT); | ||||||
|  |  | ||||||
|  |             NotificationCompat.Action playButton = new NotificationCompat.Action.Builder | ||||||
|  |                     (R.drawable.ic_play_arrow_white_48dp, "Play", playPI).build(); | ||||||
|  |  | ||||||
|  |             NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder | ||||||
|  |                     (R.drawable.ic_play_arrow_white_48dp, "Pause", playPI).build(); | ||||||
|  |  | ||||||
|  |             PendingIntent stopPI = PendingIntent.getBroadcast(owner, noteID, | ||||||
|  |                     new Intent(ACTION_STOP), PendingIntent.FLAG_UPDATE_CURRENT); | ||||||
|  |  | ||||||
|  |             //todo: make it so that tapping the notification brings you back to the Video's DetailActivity | ||||||
|  |             //using setContentIntent | ||||||
|  |             noteBuilder = new NotificationCompat.Builder(owner); | ||||||
|  |             noteBuilder | ||||||
|  |                     .setPriority(Notification.PRIORITY_LOW) | ||||||
|  |                     .setCategory(Notification.CATEGORY_TRANSPORT) | ||||||
|  |                     .setContentTitle(title) | ||||||
|  |                     .setContentText("NewPipe is playing in the background")//todo: translation string | ||||||
|  |                     //.setAutoCancel(!mediaPlayer.isPlaying()) | ||||||
|  |                     .setOngoing(true) | ||||||
|  |                     .setDeleteIntent(stopPI) | ||||||
|  |                     //.setProgress(vidLength, 0, false) //doesn't fit with Notification.MediaStyle | ||||||
|  |                     .setSmallIcon(R.mipmap.ic_launcher) | ||||||
|  |                     .setTicker(title + " - NewPipe") | ||||||
|  |                     .addAction(playButton); | ||||||
|  | /*                  .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) | ||||||
|  |                     .setLargeIcon(cover)*/ | ||||||
|  |  | ||||||
|  |             noteBuilder.setStyle(new NotificationCompat.MediaStyle() | ||||||
|  |                             //.setMediaSession(mMediaSession.getSessionToken()) | ||||||
|  |                             .setShowActionsInCompactView(new int[] {0}) | ||||||
|  |                             .setShowCancelButton(true) | ||||||
|  |                             .setCancelButtonIntent(stopPI) | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |             startForeground(noteID, noteBuilder.build()); | ||||||
|  |  | ||||||
|  |             //currently decommissioned progressbar looping update code - works, but doesn't fit inside | ||||||
|  |             //Notification.MediaStyle Notification layout. | ||||||
|  |             noteMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); | ||||||
|  |             /* | ||||||
|  |             //update every 2s or 4 times in the video, whichever is shorter | ||||||
|  |             int sleepTime = Math.min(2000, (int)((double)vidLength/4)); | ||||||
|  |             while(mediaPlayer.isPlaying()) { | ||||||
|  |                 noteBuilder.setProgress(vidLength, mediaPlayer.getCurrentPosition(), false); | ||||||
|  |                 noteMgr.notify(noteID, noteBuilder.build()); | ||||||
|  |                 try { | ||||||
|  |                     Thread.sleep(sleepTime); | ||||||
|  |                 } catch (InterruptedException e) { | ||||||
|  |                     Log.d(TAG, "sleep failure"); | ||||||
|  |                 } | ||||||
|  |             }*/ | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { | ||||||
|  |             @Override | ||||||
|  |             public void onReceive(Context context, Intent intent) { | ||||||
|  |                 String action = intent.getAction(); | ||||||
|  |                 Log.i(TAG, "received broadcast action:"+action); | ||||||
|  |                 if(action.equals(ACTION_PLAYPAUSE)) { | ||||||
|  |                     if(mediaPlayer.isPlaying()) { | ||||||
|  |                         mediaPlayer.pause(); | ||||||
|  |                     } | ||||||
|  |                     else { | ||||||
|  |                         //reacquire CPU lock after releasing it on pause | ||||||
|  |                         mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK); | ||||||
|  |                         mediaPlayer.start(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else if(action.equals(ACTION_STOP)) { | ||||||
|  |                     mediaPlayer.stop();//this auto-releases CPU lock | ||||||
|  |                     afterPlayCleanup(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         private void afterPlayCleanup() { | ||||||
|  |             //noteBuilder.setProgress(0, 0, false);//remove progress bar | ||||||
|  |             noteMgr.cancel(noteID);//remove notification | ||||||
|  |             unregisterReceiver(broadcastReceiver); | ||||||
|  |             mediaPlayer.release();//release mediaPlayer's system resources | ||||||
|  |  | ||||||
|  |  | ||||||
|  |             wifiLock.release();//release wifilock | ||||||
|  |             stopForeground(true);//remove foreground status of service; make us killable | ||||||
|  |  | ||||||
|  |             stopSelf(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private class EndListener implements MediaPlayer.OnCompletionListener { | ||||||
|  |             private WifiManager.WifiLock wl; | ||||||
|  |             public EndListener(WifiManager.WifiLock wifiLock) { | ||||||
|  |                 this.wl = wifiLock; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             @Override | ||||||
|  |             public void onCompletion(MediaPlayer mp) { | ||||||
|  |                 afterPlayCleanup(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | /* | ||||||
|  |     private class ListenerThread extends Thread implements AudioManager.OnAudioFocusChangeListener { | ||||||
|  |         @Override | ||||||
|  |         public void onAudioFocusChange(int focusChange) { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |     }*/ | ||||||
|  | } | ||||||
| @@ -30,6 +30,6 @@ public interface StreamingService { | |||||||
|  |  | ||||||
|     /**When a VIEW_ACTION is caught this function will test if the url delivered within the calling |     /**When a VIEW_ACTION is caught this function will test if the url delivered within the calling | ||||||
|     Intent was meant to be watched with this Service. |     Intent was meant to be watched with this Service. | ||||||
|     Return false if this service shall not allow to be callean through ACTIONs.*/ |     Return false if this service shall not allow to be called through ACTIONs.*/ | ||||||
|     boolean acceptUrl(String videoUrl); |     boolean acceptUrl(String videoUrl); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -371,6 +371,16 @@ public class YoutubeVideoExtractor extends VideoExtractor { | |||||||
|         //todo: replace this with a call to getVideoId, if possible |         //todo: replace this with a call to getVideoId, if possible | ||||||
|         videoInfo.id = matchGroup1("v=([0-9a-zA-Z_-]{11})", pageUrl); |         videoInfo.id = matchGroup1("v=([0-9a-zA-Z_-]{11})", pageUrl); | ||||||
|  |  | ||||||
|  |         if(videoInfo.audioStreams == null | ||||||
|  |                 || videoInfo.audioStreams.length == 0) { | ||||||
|  |             Log.e(TAG, "uninitialised audio streams!"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(videoInfo.videoStreams == null | ||||||
|  |                 || videoInfo.videoStreams.length == 0) { | ||||||
|  |             Log.e(TAG, "uninitialised video streams!"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         videoInfo.age_limit = 0; |         videoInfo.age_limit = 0; | ||||||
|  |  | ||||||
|         //average rating |         //average rating | ||||||
| @@ -445,13 +455,14 @@ public class YoutubeVideoExtractor extends VideoExtractor { | |||||||
|         try { |         try { | ||||||
|             XmlPullParser parser = Xml.newPullParser(); |             XmlPullParser parser = Xml.newPullParser(); | ||||||
|             parser.setInput(new StringReader(dashDoc)); |             parser.setInput(new StringReader(dashDoc)); | ||||||
|             int eventType = parser.getEventType(); |  | ||||||
|             String tagName = ""; |             String tagName = ""; | ||||||
|             String currentMimeType = ""; |             String currentMimeType = ""; | ||||||
|             int currentBandwidth = -1; |             int currentBandwidth = -1; | ||||||
|             int currentSamplingRate = -1; |             int currentSamplingRate = -1; | ||||||
|             boolean currentTagIsBaseUrl = false; |             boolean currentTagIsBaseUrl = false; | ||||||
|             while(eventType != XmlPullParser.END_DOCUMENT) { |             for(int eventType = parser.getEventType(); | ||||||
|  |                 eventType != XmlPullParser.END_DOCUMENT; | ||||||
|  |                 eventType = parser.next() ) { | ||||||
|                 switch(eventType) { |                 switch(eventType) { | ||||||
|                     case XmlPullParser.START_TAG: |                     case XmlPullParser.START_TAG: | ||||||
|                         tagName = parser.getName(); |                         tagName = parser.getName(); | ||||||
| @@ -465,8 +476,8 @@ public class YoutubeVideoExtractor extends VideoExtractor { | |||||||
|                         } else if(tagName.equals("BaseURL")) { |                         } else if(tagName.equals("BaseURL")) { | ||||||
|                             currentTagIsBaseUrl = true; |                             currentTagIsBaseUrl = true; | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         break; |                         break; | ||||||
|  |  | ||||||
|                     case XmlPullParser.TEXT: |                     case XmlPullParser.TEXT: | ||||||
|                         if(currentTagIsBaseUrl && |                         if(currentTagIsBaseUrl && | ||||||
|                                 (currentMimeType.contains("audio"))) { |                                 (currentMimeType.contains("audio"))) { | ||||||
| @@ -479,16 +490,14 @@ public class YoutubeVideoExtractor extends VideoExtractor { | |||||||
|                             audioStreams.add(new VideoInfo.AudioStream(parser.getText(), |                             audioStreams.add(new VideoInfo.AudioStream(parser.getText(), | ||||||
|                                     format, currentBandwidth, currentSamplingRate)); |                                     format, currentBandwidth, currentSamplingRate)); | ||||||
|                         } |                         } | ||||||
|  |                         //missing break here? | ||||||
|                     case XmlPullParser.END_TAG: |                     case XmlPullParser.END_TAG: | ||||||
|                         if(tagName.equals("AdaptationSet")) { |                         if(tagName.equals("AdaptationSet")) { | ||||||
|                             currentMimeType = ""; |                             currentMimeType = ""; | ||||||
|                         } else if(tagName.equals("BaseURL")) { |                         } else if(tagName.equals("BaseURL")) { | ||||||
|                             currentTagIsBaseUrl = false; |                             currentTagIsBaseUrl = false; | ||||||
|  |                         }//no break needed here | ||||||
|                 } |                 } | ||||||
|                         break; |  | ||||||
|                     default: |  | ||||||
|                 } |  | ||||||
|                 eventType = parser.next(); |  | ||||||
|             } |             } | ||||||
|         } catch(Exception e) { |         } catch(Exception e) { | ||||||
|             e.printStackTrace(); |             e.printStackTrace(); | ||||||
| @@ -582,10 +591,7 @@ public class YoutubeVideoExtractor extends VideoExtractor { | |||||||
|             e.printStackTrace(); |             e.printStackTrace(); | ||||||
|         } |         } | ||||||
|         Context.exit(); |         Context.exit(); | ||||||
|         if(result != null) |         return (result == null ? "" : result.toString()); | ||||||
|             return result.toString(); |  | ||||||
|         else |  | ||||||
|             return ""; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private String cleanUrl(String complexUrl) { |     private String cleanUrl(String complexUrl) { | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-hdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-hdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 283 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-mdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-mdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 220 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xhdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xhdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 343 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 461 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_48dp.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 605 B | 
| @@ -6,9 +6,10 @@ | |||||||
|     <string name="settingsCategoryEtc">settings_category_etc</string> |     <string name="settingsCategoryEtc">settings_category_etc</string> | ||||||
|     <!-- Key values --> |     <!-- Key values --> | ||||||
|     <string name="downloadPathPreference">download_path_preference</string> |     <string name="downloadPathPreference">download_path_preference</string> | ||||||
|     <string name="useExternalPlayer">use_external_player</string> |     <string name="useExternalVideoPlayer">use_external_video_player</string> | ||||||
|  |     <string name="useExternalAudioPlayer">use_external_audio_player</string> | ||||||
|     <string name="autoPlayThroughIntent">autoplay_through_intent</string> |     <string name="autoPlayThroughIntent">autoplay_through_intent</string> | ||||||
|     <string name="defaultResolutionPreference">default_resulution_preference</string> |     <string name="defaultResolutionPreference">default_resolution_preference</string> | ||||||
|     <string-array name="resolutionList"> |     <string-array name="resolutionList"> | ||||||
|         <item>720p</item> |         <item>720p</item> | ||||||
|         <item>360p</item> |         <item>360p</item> | ||||||
| @@ -16,7 +17,7 @@ | |||||||
|         <item>144p</item> |         <item>144p</item> | ||||||
|     </string-array> |     </string-array> | ||||||
|     <string name="defaultResolutionListItem">360p</string> |     <string name="defaultResolutionListItem">360p</string> | ||||||
|     <string name="showPlayWidthKodiPreference">show_play_with_kodi_preference</string> |     <string name="showPlayWithKodiPreference">show_play_with_kodi_preference</string> | ||||||
|     <string name="defaultAudioFormatPreference">default_audio_format</string> |     <string name="defaultAudioFormatPreference">default_audio_format</string> | ||||||
|     <string-array name="audioFormatDescriptionList"> |     <string-array name="audioFormatDescriptionList"> | ||||||
|         <item>@string/webMAudioDescription</item> |         <item>@string/webMAudioDescription</item> | ||||||
|   | |||||||
| @@ -19,7 +19,8 @@ | |||||||
|     <string name="chooseBrowser">Choose browser:</string> |     <string name="chooseBrowser">Choose browser:</string> | ||||||
|     <string name="screenRotation">rotation</string> |     <string name="screenRotation">rotation</string> | ||||||
|     <string name="title_activity_settings">Settings</string> |     <string name="title_activity_settings">Settings</string> | ||||||
|     <string name="useExternalPlayerTitle">Use external player</string> |     <string name="useExternalVideoPlayerTitle">Use external video player</string> | ||||||
|  |     <string name="useExternalAudioPlayerTitle">Use external audio player</string> | ||||||
|     <string name="downloadLocation">Download location</string> |     <string name="downloadLocation">Download location</string> | ||||||
|     <string name="downloadLocationSummary">Path to store downloaded videos in.</string> |     <string name="downloadLocationSummary">Path to store downloaded videos in.</string> | ||||||
|     <string name="downloadLocationDialogTitle">Enter download path</string> |     <string name="downloadLocationDialogTitle">Enter download path</string> | ||||||
|   | |||||||
| @@ -8,8 +8,13 @@ | |||||||
|         android:title="@string/settingsCategoryVideoAudioTitle"> |         android:title="@string/settingsCategoryVideoAudioTitle"> | ||||||
|  |  | ||||||
|         <CheckBoxPreference |         <CheckBoxPreference | ||||||
|             android:key="@string/useExternalPlayer" |             android:key="@string/useExternalVideoPlayer" | ||||||
|             android:title="@string/useExternalPlayerTitle" |             android:title="@string/useExternalVideoPlayerTitle" | ||||||
|  |             android:defaultValue="false"/> | ||||||
|  |  | ||||||
|  |         <CheckBoxPreference | ||||||
|  |             android:key="@string/useExternalAudioPlayer" | ||||||
|  |             android:title="@string/useExternalAudioPlayerTitle" | ||||||
|             android:defaultValue="false"/> |             android:defaultValue="false"/> | ||||||
|  |  | ||||||
|         <ListPreference |         <ListPreference | ||||||
| @@ -32,7 +37,7 @@ | |||||||
|         android:title="@string/settingsCategoryVideoInfoTittle"> |         android:title="@string/settingsCategoryVideoInfoTittle"> | ||||||
|  |  | ||||||
|         <CheckBoxPreference |         <CheckBoxPreference | ||||||
|             android:key="@string/showPlayWidthKodiPreference" |             android:key="@string/showPlayWithKodiPreference" | ||||||
|             android:title="@string/showPlayWithKodiTitle" |             android:title="@string/showPlayWithKodiTitle" | ||||||
|             android:summary="@string/showPlayWithKodiSummary" |             android:summary="@string/showPlayWithKodiSummary" | ||||||
|             android:defaultValue="false" /> |             android:defaultValue="false" /> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Christian Schabesberger
					Christian Schabesberger