mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13: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" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     package="org.schabi.newpipe" > | ||||
|  | ||||
|     <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.WRITE_EXTERNAL_STORAGE"/> | ||||
|     <application | ||||
| @@ -74,6 +74,12 @@ | ||||
|             android:parentActivityName=".VideoItemDetailActivity" | ||||
|             tools:ignore="UnusedAttribute"> | ||||
|         </activity> | ||||
|         <!--TODO: make label a translatable string --> | ||||
|         <service | ||||
|             android:name=".BackgroundPlayer" | ||||
|             android:label="NewPipe Background Player" | ||||
|             android:exported="false" > | ||||
|         </service> | ||||
|         <activity | ||||
|             android:name=".SettingsActivity" | ||||
|             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) { | ||||
| @@ -136,7 +139,7 @@ class ActionBarHandler { | ||||
|         MenuItem castItem = menu.findItem(R.id.action_play_with_kodi); | ||||
|  | ||||
|         castItem.setVisible(defaultPreferences | ||||
|                 .getBoolean(activity.getString(R.string.showPlayWidthKodiPreference), false)); | ||||
|                 .getBoolean(activity.getString(R.string.showPlayWithKodiPreference), false)); | ||||
|     } | ||||
|  | ||||
|     public boolean onItemSelected(MenuItem item) { | ||||
| @@ -184,7 +187,7 @@ class ActionBarHandler { | ||||
|         // ----------- THE MAGIC MOMENT --------------- | ||||
|         if(!videoTitle.isEmpty()) { | ||||
|             if (PreferenceManager.getDefaultSharedPreferences(activity) | ||||
|                     .getBoolean(activity.getString(R.string.useExternalPlayer), false)) { | ||||
|                     .getBoolean(activity.getString(R.string.useExternalVideoPlayer), false)) { | ||||
|  | ||||
|                 // External Player | ||||
|                 Intent intent = new Intent(); | ||||
| @@ -293,14 +296,32 @@ class ActionBarHandler { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void playAudio() { | ||||
|         Intent intent = new Intent(); | ||||
|     public void playAudio() { | ||||
|  | ||||
|         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 { | ||||
|                 intent.setAction(Intent.ACTION_VIEW); | ||||
|                 intent.setDataAndType(Uri.parse(audioStream.url), | ||||
|                         MediaFormat.getMimeById(audioStream.format)); | ||||
|                 intent.putExtra(Intent.EXTRA_TITLE, videoTitle); | ||||
|                 intent.putExtra("title", videoTitle); | ||||
|  | ||||
|                 activity.startActivity(intent);      // HERE !!! | ||||
|             } catch (Exception e) { | ||||
|                 e.printStackTrace(); | ||||
| @@ -327,3 +348,4 @@ class ActionBarHandler { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										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 | ||||
|     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); | ||||
| } | ||||
|   | ||||
| @@ -371,6 +371,16 @@ public class YoutubeVideoExtractor extends VideoExtractor { | ||||
|         //todo: replace this with a call to getVideoId, if possible | ||||
|         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; | ||||
|  | ||||
|         //average rating | ||||
| @@ -445,13 +455,14 @@ public class YoutubeVideoExtractor extends VideoExtractor { | ||||
|         try { | ||||
|             XmlPullParser parser = Xml.newPullParser(); | ||||
|             parser.setInput(new StringReader(dashDoc)); | ||||
|             int eventType = parser.getEventType(); | ||||
|             String tagName = ""; | ||||
|             String currentMimeType = ""; | ||||
|             int currentBandwidth = -1; | ||||
|             int currentSamplingRate = -1; | ||||
|             boolean currentTagIsBaseUrl = false; | ||||
|             while(eventType != XmlPullParser.END_DOCUMENT) { | ||||
|             for(int eventType = parser.getEventType(); | ||||
|                 eventType != XmlPullParser.END_DOCUMENT; | ||||
|                 eventType = parser.next() ) { | ||||
|                 switch(eventType) { | ||||
|                     case XmlPullParser.START_TAG: | ||||
|                         tagName = parser.getName(); | ||||
| @@ -465,8 +476,8 @@ public class YoutubeVideoExtractor extends VideoExtractor { | ||||
|                         } else if(tagName.equals("BaseURL")) { | ||||
|                             currentTagIsBaseUrl = true; | ||||
|                         } | ||||
|  | ||||
|                         break; | ||||
|  | ||||
|                     case XmlPullParser.TEXT: | ||||
|                         if(currentTagIsBaseUrl && | ||||
|                                 (currentMimeType.contains("audio"))) { | ||||
| @@ -479,16 +490,14 @@ public class YoutubeVideoExtractor extends VideoExtractor { | ||||
|                             audioStreams.add(new VideoInfo.AudioStream(parser.getText(), | ||||
|                                     format, currentBandwidth, currentSamplingRate)); | ||||
|                         } | ||||
|                         //missing break here? | ||||
|                     case XmlPullParser.END_TAG: | ||||
|                         if(tagName.equals("AdaptationSet")) { | ||||
|                             currentMimeType = ""; | ||||
|                         } else if(tagName.equals("BaseURL")) { | ||||
|                             currentTagIsBaseUrl = false; | ||||
|                         }//no break needed here | ||||
|                 } | ||||
|                         break; | ||||
|                     default: | ||||
|                 } | ||||
|                 eventType = parser.next(); | ||||
|             } | ||||
|         } catch(Exception e) { | ||||
|             e.printStackTrace(); | ||||
| @@ -582,10 +591,7 @@ public class YoutubeVideoExtractor extends VideoExtractor { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         Context.exit(); | ||||
|         if(result != null) | ||||
|             return result.toString(); | ||||
|         else | ||||
|             return ""; | ||||
|         return (result == null ? "" : result.toString()); | ||||
|     } | ||||
|  | ||||
|     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> | ||||
|     <!-- Key values --> | ||||
|     <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="defaultResolutionPreference">default_resulution_preference</string> | ||||
|     <string name="defaultResolutionPreference">default_resolution_preference</string> | ||||
|     <string-array name="resolutionList"> | ||||
|         <item>720p</item> | ||||
|         <item>360p</item> | ||||
| @@ -16,7 +17,7 @@ | ||||
|         <item>144p</item> | ||||
|     </string-array> | ||||
|     <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-array name="audioFormatDescriptionList"> | ||||
|         <item>@string/webMAudioDescription</item> | ||||
|   | ||||
| @@ -19,7 +19,8 @@ | ||||
|     <string name="chooseBrowser">Choose browser:</string> | ||||
|     <string name="screenRotation">rotation</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="downloadLocationSummary">Path to store downloaded videos in.</string> | ||||
|     <string name="downloadLocationDialogTitle">Enter download path</string> | ||||
|   | ||||
| @@ -8,8 +8,13 @@ | ||||
|         android:title="@string/settingsCategoryVideoAudioTitle"> | ||||
|  | ||||
|         <CheckBoxPreference | ||||
|             android:key="@string/useExternalPlayer" | ||||
|             android:title="@string/useExternalPlayerTitle" | ||||
|             android:key="@string/useExternalVideoPlayer" | ||||
|             android:title="@string/useExternalVideoPlayerTitle" | ||||
|             android:defaultValue="false"/> | ||||
|  | ||||
|         <CheckBoxPreference | ||||
|             android:key="@string/useExternalAudioPlayer" | ||||
|             android:title="@string/useExternalAudioPlayerTitle" | ||||
|             android:defaultValue="false"/> | ||||
|  | ||||
|         <ListPreference | ||||
| @@ -32,7 +37,7 @@ | ||||
|         android:title="@string/settingsCategoryVideoInfoTittle"> | ||||
|  | ||||
|         <CheckBoxPreference | ||||
|             android:key="@string/showPlayWidthKodiPreference" | ||||
|             android:key="@string/showPlayWithKodiPreference" | ||||
|             android:title="@string/showPlayWithKodiTitle" | ||||
|             android:summary="@string/showPlayWithKodiSummary" | ||||
|             android:defaultValue="false" /> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Christian Schabesberger
					Christian Schabesberger