some improvements for background player
| @@ -3,6 +3,7 @@ package org.schabi.newpipe; | |||||||
| import android.content.DialogInterface; | import android.content.DialogInterface; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.content.SharedPreferences; | import android.content.SharedPreferences; | ||||||
|  | import android.graphics.Bitmap; | ||||||
| import android.net.Uri; | import android.net.Uri; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.preference.PreferenceManager; | import android.preference.PreferenceManager; | ||||||
| @@ -40,7 +41,10 @@ class ActionBarHandler { | |||||||
|     private static final String TAG = ActionBarHandler.class.toString(); |     private static final String TAG = ActionBarHandler.class.toString(); | ||||||
|     private static final String KORE_PACKET = "org.xbmc.kore"; |     private static final String KORE_PACKET = "org.xbmc.kore"; | ||||||
|  |  | ||||||
|  |     private int serviceId; | ||||||
|     private String websiteUrl = ""; |     private String websiteUrl = ""; | ||||||
|  |     private Bitmap videoThumbnail = null; | ||||||
|  |     private String channelName = ""; | ||||||
|     private AppCompatActivity activity; |     private AppCompatActivity activity; | ||||||
|     private VideoInfo.VideoStream[] videoStreams = null; |     private VideoInfo.VideoStream[] videoStreams = null; | ||||||
|     private VideoInfo.AudioStream audioStream = null; |     private VideoInfo.AudioStream audioStream = null; | ||||||
| @@ -73,6 +77,18 @@ class ActionBarHandler { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public void setServiceId(int id) { | ||||||
|  |         serviceId = id; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setSetVideoThumbnail(Bitmap bitmap) { | ||||||
|  |         videoThumbnail = bitmap; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setChannelName(String name) { | ||||||
|  |         channelName = name; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @SuppressWarnings("deprecation") |     @SuppressWarnings("deprecation") | ||||||
|     public void setStreams(VideoInfo.VideoStream[] videoStreams, VideoInfo.AudioStream[] audioStreams) { |     public void setStreams(VideoInfo.VideoStream[] videoStreams, VideoInfo.AudioStream[] audioStreams) { | ||||||
|         this.videoStreams = videoStreams; |         this.videoStreams = videoStreams; | ||||||
| @@ -143,37 +159,41 @@ class ActionBarHandler { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean onItemSelected(MenuItem item) { |     public boolean onItemSelected(MenuItem item) { | ||||||
|         int id = item.getItemId(); |         if(!videoTitle.isEmpty()) { | ||||||
|         switch(id) { |             int id = item.getItemId(); | ||||||
|             case R.id.menu_item_share: |             switch (id) { | ||||||
|                 if(!videoTitle.isEmpty()) { |                 case R.id.menu_item_share: { | ||||||
|                     Intent intent = new Intent(); |                     Intent intent = new Intent(); | ||||||
|                     intent.setAction(Intent.ACTION_SEND); |                     intent.setAction(Intent.ACTION_SEND); | ||||||
|                     intent.putExtra(Intent.EXTRA_TEXT, websiteUrl); |                     intent.putExtra(Intent.EXTRA_TEXT, websiteUrl); | ||||||
|                     intent.setType("text/plain"); |                     intent.setType("text/plain"); | ||||||
|                     activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.shareDialogTitle))); |                     activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.shareDialogTitle))); | ||||||
|  |                     return true; | ||||||
|  |                 } | ||||||
|  |                 case R.id.menu_item_openInBrowser: { | ||||||
|  |                     openInBrowser(); | ||||||
|                 } |                 } | ||||||
|                 return true; |                 return true; | ||||||
|             case R.id.menu_item_openInBrowser: { |                 case R.id.menu_item_download: | ||||||
|                 openInBrowser(); |                     downloadVideo(); | ||||||
|  |                     return true; | ||||||
|  |                 case R.id.action_settings: { | ||||||
|  |                     Intent intent = new Intent(activity, SettingsActivity.class); | ||||||
|  |                     activity.startActivity(intent); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |                 case R.id.action_play_with_kodi: | ||||||
|  |                     playWithKodi(); | ||||||
|  |                     return true; | ||||||
|  |                 case R.id.menu_item_play_audio: | ||||||
|  |                     playAudio(); | ||||||
|  |                     return true; | ||||||
|  |                 default: | ||||||
|  |                     Log.e(TAG, "Menu Item not known"); | ||||||
|             } |             } | ||||||
|                 return true; |         } else { | ||||||
|             case R.id.menu_item_download: |             // That line may not be necessary. | ||||||
|                 downloadVideo(); |             return true; | ||||||
|                 return true; |  | ||||||
|             case R.id.action_settings: { |  | ||||||
|                 Intent intent = new Intent(activity, SettingsActivity.class); |  | ||||||
|                 activity.startActivity(intent); |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
|             case R.id.action_play_with_kodi: |  | ||||||
|                 playWithKodi(); |  | ||||||
|                 return true; |  | ||||||
|             case R.id.menu_item_play_audio: |  | ||||||
|                 playAudio(); |  | ||||||
|                 return true; |  | ||||||
|             default: |  | ||||||
|                 Log.e(TAG, "Menu Item not known"); |  | ||||||
|         } |         } | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| @@ -302,18 +322,24 @@ class ActionBarHandler { | |||||||
|                 .getBoolean(activity.getString(R.string.useExternalAudioPlayer), false); |                 .getBoolean(activity.getString(R.string.useExternalAudioPlayer), false); | ||||||
|         Intent intent; |         Intent intent; | ||||||
|  |  | ||||||
|         if (!externalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18)//internal music player: explicit intent |         if (!externalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) { | ||||||
|         { |             //internal music player: explicit intent | ||||||
|             intent = new Intent(activity, BackgroundPlayer.class); |             if (!BackgroundPlayer.isRunning  && videoThumbnail != null) { | ||||||
|  |                 ActivityCommunicator.getCommunicator() | ||||||
|  |                         .backgroundPlayerThumbnail = videoThumbnail; | ||||||
|  |                 intent = new Intent(activity, BackgroundPlayer.class); | ||||||
|  |  | ||||||
|             intent.setAction(Intent.ACTION_VIEW); |                 intent.setAction(Intent.ACTION_VIEW); | ||||||
|             Log.i(TAG, "audioStream is null:" + (audioStream == null)); |                 Log.i(TAG, "audioStream is null:" + (audioStream == null)); | ||||||
|             Log.i(TAG, "audioStream.url is null:"+(audioStream.url==null)); |                 Log.i(TAG, "audioStream.url is null:" + (audioStream.url == null)); | ||||||
|             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(BackgroundPlayer.TITLE, videoTitle); | ||||||
|             intent.putExtra("title", videoTitle); |                 intent.putExtra(BackgroundPlayer.WEB_URL, websiteUrl); | ||||||
|             activity.startService(intent); |                 intent.putExtra(BackgroundPlayer.SERVICE_ID, serviceId); | ||||||
|  |                 intent.putExtra(BackgroundPlayer.CHANNEL_NAME, channelName); | ||||||
|  |                 activity.startService(intent); | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             intent = new Intent(); |             intent = new Intent(); | ||||||
|             try { |             try { | ||||||
|   | |||||||
| @@ -0,0 +1,42 @@ | |||||||
|  | package org.schabi.newpipe; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Created by Christian Schabesberger on 24.12.15. | ||||||
|  |  * | ||||||
|  |  * Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org> | ||||||
|  |  * ActivityCommunicator.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/>. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import android.graphics.Bitmap; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Singleton: | ||||||
|  |  * Used to send data between certain Activity/Services within the same process. | ||||||
|  |  * This can be considered as hack inside the Android universe. **/ | ||||||
|  | public class ActivityCommunicator { | ||||||
|  |  | ||||||
|  |     private static ActivityCommunicator activityCommunicator = null; | ||||||
|  |  | ||||||
|  |     public static ActivityCommunicator getCommunicator() { | ||||||
|  |         if(activityCommunicator == null) { | ||||||
|  |             activityCommunicator = new ActivityCommunicator(); | ||||||
|  |         } | ||||||
|  |         return activityCommunicator; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Thumbnail send from VideoItemDetailFragment to BackgroundPlayer | ||||||
|  |     public volatile Bitmap backgroundPlayerThumbnail; | ||||||
|  | } | ||||||
| @@ -8,6 +8,8 @@ import android.content.BroadcastReceiver; | |||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
| import android.content.IntentFilter; | import android.content.IntentFilter; | ||||||
|  | import android.content.res.Resources; | ||||||
|  | import android.graphics.Bitmap; | ||||||
| import android.media.AudioManager; | import android.media.AudioManager; | ||||||
| import android.media.MediaPlayer; | import android.media.MediaPlayer; | ||||||
| import android.net.wifi.WifiManager; | import android.net.wifi.WifiManager; | ||||||
| @@ -43,8 +45,22 @@ import java.io.IOException; | |||||||
| public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPreparedListener*/ { | public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPreparedListener*/ { | ||||||
|  |  | ||||||
|     private static final String TAG = BackgroundPlayer.class.toString(); |     private static final String TAG = BackgroundPlayer.class.toString(); | ||||||
|     private static final String ACTION_STOP = TAG+".STOP"; |     private static final String ACTION_STOP = TAG + ".STOP"; | ||||||
|     private static final String ACTION_PLAYPAUSE = TAG+".PLAYPAUSE"; |     private static final String ACTION_PLAYPAUSE = TAG + ".PLAYPAUSE"; | ||||||
|  |  | ||||||
|  |     // Extra intent arguments | ||||||
|  |     public static final String TITLE = "title"; | ||||||
|  |     public static final String WEB_URL = "web_url"; | ||||||
|  |     public static final String SERVICE_ID = "service_id"; | ||||||
|  |     public static final String CHANNEL_NAME="channel_name"; | ||||||
|  |  | ||||||
|  |     private volatile String webUrl = ""; | ||||||
|  |     private volatile int serviceId = -1; | ||||||
|  |     private volatile String channelName = ""; | ||||||
|  |  | ||||||
|  |     // Determines if the service is already running. | ||||||
|  |     // Prevents launching the service twice. | ||||||
|  |     public static volatile boolean isRunning = false; | ||||||
|  |  | ||||||
|     public BackgroundPlayer() { |     public BackgroundPlayer() { | ||||||
|         super(); |         super(); | ||||||
| @@ -58,16 +74,22 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare | |||||||
|     } |     } | ||||||
|     @Override |     @Override | ||||||
|     public int onStartCommand(Intent intent, int flags, int startId) { |     public int onStartCommand(Intent intent, int flags, int startId) { | ||||||
|         Toast.makeText(this, "Playing in background", Toast.LENGTH_SHORT).show();//todo:translation string |         Toast.makeText(this, R.string.backgroundPlayerStartPlayingToast, | ||||||
|  |                 Toast.LENGTH_SHORT).show(); | ||||||
|  |  | ||||||
|         String source = intent.getDataString(); |         String source = intent.getDataString(); | ||||||
|         //Log.i(TAG, "backgroundPLayer source:"+source); |         //Log.i(TAG, "backgroundPLayer source:"+source); | ||||||
|         String videoTitle = intent.getStringExtra("title"); |         String videoTitle = intent.getStringExtra(TITLE); | ||||||
|  |         webUrl = intent.getStringExtra(WEB_URL); | ||||||
|  |         serviceId = intent.getIntExtra(SERVICE_ID, -1); | ||||||
|  |         channelName = intent.getStringExtra(CHANNEL_NAME); | ||||||
|  |  | ||||||
|         //do nearly everything in a separate thread |         //do nearly everything in a separate thread | ||||||
|         PlayerThread player = new PlayerThread(source, videoTitle, this); |         PlayerThread player = new PlayerThread(source, videoTitle, this); | ||||||
|         player.start(); |         player.start(); | ||||||
|  |  | ||||||
|  |         isRunning = true; | ||||||
|  |  | ||||||
|         // If we get killed after returning here, don't restart |         // If we get killed after returning here, don't restart | ||||||
|         return START_NOT_STICKY; |         return START_NOT_STICKY; | ||||||
|     } |     } | ||||||
| @@ -81,6 +103,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare | |||||||
|     @Override |     @Override | ||||||
|     public void onDestroy() { |     public void onDestroy() { | ||||||
|         //Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); |         //Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); | ||||||
|  |         isRunning = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private class PlayerThread extends Thread { |     private class PlayerThread extends Thread { | ||||||
| @@ -92,6 +115,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare | |||||||
|         private NotificationManager noteMgr; |         private NotificationManager noteMgr; | ||||||
|         private NotificationCompat.Builder noteBuilder; |         private NotificationCompat.Builder noteBuilder; | ||||||
|         private WifiManager.WifiLock wifiLock; |         private WifiManager.WifiLock wifiLock; | ||||||
|  |         private Bitmap videoThumbnail = null; | ||||||
|  |  | ||||||
|         public PlayerThread(String src, String title, BackgroundPlayer owner) { |         public PlayerThread(String src, String title, BackgroundPlayer owner) { | ||||||
|             this.source = src; |             this.source = src; | ||||||
| @@ -102,11 +126,14 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare | |||||||
|         } |         } | ||||||
|         @Override |         @Override | ||||||
|         public void run() { |         public void run() { | ||||||
|  |             Resources res = getApplicationContext().getResources(); | ||||||
|  |  | ||||||
|             mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//cpu lock |             mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//cpu lock | ||||||
|             try { |             try { | ||||||
|                 mediaPlayer.setDataSource(source); |                 mediaPlayer.setDataSource(source); | ||||||
|                 mediaPlayer.prepare(); //We are already in a separate worker thread, |                 //We are already in a separate worker thread, | ||||||
|                 //so calling the blocking prepare() method should be ok |                 //so calling the blocking prepare() method should be ok | ||||||
|  |                 mediaPlayer.prepare(); | ||||||
|  |  | ||||||
|                 //alternatively: |                 //alternatively: | ||||||
|                 //mediaPlayer.setOnPreparedListener(this); |                 //mediaPlayer.setOnPreparedListener(this); | ||||||
| @@ -119,10 +146,18 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             try { | ||||||
|  |                 videoThumbnail = ActivityCommunicator.getCommunicator().backgroundPlayerThumbnail; | ||||||
|  |             } catch (Exception e) { | ||||||
|  |                 Log.e(TAG, "Could not get video thumbnail from ActivityCommunicator"); | ||||||
|  |                 e.printStackTrace(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|             WifiManager wifiMgr = ((WifiManager)getSystemService(Context.WIFI_SERVICE)); |             WifiManager wifiMgr = ((WifiManager)getSystemService(Context.WIFI_SERVICE)); | ||||||
|             wifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); |             wifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); | ||||||
|  |  | ||||||
|             mediaPlayer.setOnCompletionListener(new EndListener(wifiLock));//listen for end of video |             //listen for end of video | ||||||
|  |             mediaPlayer.setOnCompletionListener(new EndListener(wifiLock)); | ||||||
|  |  | ||||||
|             //get audio focus |             //get audio focus | ||||||
|             /* |             /* | ||||||
| @@ -142,43 +177,65 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare | |||||||
|             filter.addAction(ACTION_STOP); |             filter.addAction(ACTION_STOP); | ||||||
|             registerReceiver(broadcastReceiver, filter); |             registerReceiver(broadcastReceiver, filter); | ||||||
|  |  | ||||||
|             PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID, new Intent(ACTION_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT); |             PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID, | ||||||
|  |                     new Intent(ACTION_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT); | ||||||
|  |  | ||||||
|             NotificationCompat.Action playButton = new NotificationCompat.Action.Builder |             NotificationCompat.Action playButton = new NotificationCompat.Action.Builder | ||||||
|                     (R.drawable.ic_play_arrow_white_48dp, "Play", playPI).build(); |                     (R.drawable.ic_play_arrow_white_48dp, "Play", playPI).build(); | ||||||
|  |  | ||||||
|  |             /* | ||||||
|             NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder |             NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder | ||||||
|                     (R.drawable.ic_play_arrow_white_48dp, "Pause", playPI).build(); |                     (R.drawable.ic_pause_white_24dp, "Pause", playPI).build(); | ||||||
|  |             */ | ||||||
|  |  | ||||||
|             PendingIntent stopPI = PendingIntent.getBroadcast(owner, noteID, |             PendingIntent stopPI = PendingIntent.getBroadcast(owner, noteID, | ||||||
|                     new Intent(ACTION_STOP), PendingIntent.FLAG_UPDATE_CURRENT); |                     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 = new NotificationCompat.Builder(owner); | ||||||
|             noteBuilder |             noteBuilder | ||||||
|                     .setPriority(Notification.PRIORITY_LOW) |  | ||||||
|                     .setCategory(Notification.CATEGORY_TRANSPORT) |  | ||||||
|                     .setContentTitle(title) |                     .setContentTitle(title) | ||||||
|                     .setContentText("NewPipe is playing in the background")//todo: translation string |                     //really? Id like to put something more helpful here. | ||||||
|  |                     //.setContentText("NewPipe is playing in the background") | ||||||
|  |                     .setContentText(channelName) | ||||||
|                     //.setAutoCancel(!mediaPlayer.isPlaying()) |                     //.setAutoCancel(!mediaPlayer.isPlaying()) | ||||||
|                     .setOngoing(true) |                     .setOngoing(true) | ||||||
|                     .setDeleteIntent(stopPI) |                     .setDeleteIntent(stopPI) | ||||||
|                     //.setProgress(vidLength, 0, false) //doesn't fit with Notification.MediaStyle |                     //doesn't fit with Notification.MediaStyle | ||||||
|                     .setSmallIcon(R.mipmap.ic_launcher) |                     //.setProgress(vidLength, 0, false) | ||||||
|                     .setTicker(title + " - NewPipe") |                     .setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp) | ||||||
|  |                     .setLargeIcon(videoThumbnail) | ||||||
|  |                     .setTicker( | ||||||
|  |                             String.format(res.getString( | ||||||
|  |                                     R.string.backgroundPlayerTickerText), title)) | ||||||
|                     .addAction(playButton); |                     .addAction(playButton); | ||||||
| /*                  .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) |                     //.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) | ||||||
|                     .setLargeIcon(cover)*/ |                     //.setLargeIcon(cover) | ||||||
|  |             if(android.os.Build.VERSION.SDK_INT >= 16) | ||||||
|  |                 noteBuilder.setPriority(Notification.PRIORITY_LOW); | ||||||
|  |             if(android.os.Build.VERSION.SDK_INT >= 21) | ||||||
|  |                 noteBuilder.setCategory(Notification.CATEGORY_TRANSPORT); | ||||||
|  |  | ||||||
|             noteBuilder.setStyle(new NotificationCompat.MediaStyle() |                 noteBuilder.setStyle(new NotificationCompat.MediaStyle() | ||||||
|                             //.setMediaSession(mMediaSession.getSessionToken()) |                                 //.setMediaSession(mMediaSession.getSessionToken()) | ||||||
|                             .setShowActionsInCompactView(new int[] {0}) |                                 .setShowActionsInCompactView(new int[]{0}) | ||||||
|                             .setShowCancelButton(true) |                                 .setShowCancelButton(true) | ||||||
|                             .setCancelButtonIntent(stopPI) |                                 .setCancelButtonIntent(stopPI)); | ||||||
|             ); |             if(videoThumbnail != null) { | ||||||
|  |                 noteBuilder.setLargeIcon(videoThumbnail); | ||||||
|  |             } | ||||||
|  |  | ||||||
|             startForeground(noteID, noteBuilder.build()); |             Notification note = noteBuilder.build(); | ||||||
|  |  | ||||||
|  |             Intent openDetailView = new Intent(getApplicationContext(), | ||||||
|  |                     VideoItemDetailActivity.class); | ||||||
|  |             openDetailView.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, serviceId); | ||||||
|  |             openDetailView.putExtra(VideoItemDetailFragment.VIDEO_URL, webUrl); | ||||||
|  |             openDetailView.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||||
|  |             note.contentIntent = PendingIntent.getActivity(getApplicationContext(), | ||||||
|  |                     noteID, openDetailView, | ||||||
|  |                     PendingIntent.FLAG_UPDATE_CURRENT); | ||||||
|  |  | ||||||
|  |             startForeground(noteID, note); | ||||||
|  |  | ||||||
|             //currently decommissioned progressbar looping update code - works, but doesn't fit inside |             //currently decommissioned progressbar looping update code - works, but doesn't fit inside | ||||||
|             //Notification.MediaStyle Notification layout. |             //Notification.MediaStyle Notification layout. | ||||||
| @@ -202,7 +259,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare | |||||||
|             @Override |             @Override | ||||||
|             public void onReceive(Context context, Intent intent) { |             public void onReceive(Context context, Intent intent) { | ||||||
|                 String action = intent.getAction(); |                 String action = intent.getAction(); | ||||||
|                 Log.i(TAG, "received broadcast action:"+action); |                 //Log.i(TAG, "received broadcast action:"+action); | ||||||
|                 if(action.equals(ACTION_PLAYPAUSE)) { |                 if(action.equals(ACTION_PLAYPAUSE)) { | ||||||
|                     if(mediaPlayer.isPlaying()) { |                     if(mediaPlayer.isPlaying()) { | ||||||
|                         mediaPlayer.pause(); |                         mediaPlayer.pause(); | ||||||
| @@ -214,7 +271,8 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 else if(action.equals(ACTION_STOP)) { |                 else if(action.equals(ACTION_STOP)) { | ||||||
|                     mediaPlayer.stop();//this auto-releases CPU lock |                     //this auto-releases CPU lock | ||||||
|  |                     mediaPlayer.stop(); | ||||||
|                     afterPlayCleanup(); |                     afterPlayCleanup(); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -73,7 +73,7 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|      * The fragment argument representing the item ID that this fragment |      * The fragment argument representing the item ID that this fragment | ||||||
|      * represents. |      * represents. | ||||||
|      */ |      */ | ||||||
|     public static final String ARG_ITEM_ID = "item_id"; |     //public static final String ARG_ITEM_ID = "item_id"; | ||||||
|     public static final String VIDEO_URL = "video_url"; |     public static final String VIDEO_URL = "video_url"; | ||||||
|     public static final String STREAMING_SERVICE = "streaming_service"; |     public static final String STREAMING_SERVICE = "streaming_service"; | ||||||
|     public static final String AUTO_PLAY = "auto_play"; |     public static final String AUTO_PLAY = "auto_play"; | ||||||
| @@ -81,6 +81,8 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|     private AppCompatActivity activity; |     private AppCompatActivity activity; | ||||||
|     private ActionBarHandler actionBarHandler; |     private ActionBarHandler actionBarHandler; | ||||||
|  |  | ||||||
|  |     private int streamingServiceId = -1; | ||||||
|  |  | ||||||
|     private boolean autoPlayEnabled = false; |     private boolean autoPlayEnabled = false; | ||||||
|     private VideoInfo currentVideoInfo = null; |     private VideoInfo currentVideoInfo = null; | ||||||
|     private boolean showNextVideoItem = false; |     private boolean showNextVideoItem = false; | ||||||
| @@ -105,6 +107,7 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|             this.service = service; |             this.service = service; | ||||||
|             this.videoUrl = videoUrl; |             this.videoUrl = videoUrl; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         @Override |         @Override | ||||||
|         public void run() { |         public void run() { | ||||||
|             try { |             try { | ||||||
| @@ -176,6 +179,7 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|             switch (id) { |             switch (id) { | ||||||
|                 case SetThumbnailRunnable.VIDEO_THUMBNAIL: |                 case SetThumbnailRunnable.VIDEO_THUMBNAIL: | ||||||
|                     thumbnailView = (ImageView) a.findViewById(R.id.detailThumbnailView); |                     thumbnailView = (ImageView) a.findViewById(R.id.detailThumbnailView); | ||||||
|  |                     actionBarHandler.setSetVideoThumbnail(thumbnail); | ||||||
|                     break; |                     break; | ||||||
|                 case SetThumbnailRunnable.CHANNEL_THUMBNAIL: |                 case SetThumbnailRunnable.CHANNEL_THUMBNAIL: | ||||||
|                     thumbnailView = (ImageView) a.findViewById(R.id.detailUploaderThumbnailView); |                     thumbnailView = (ImageView) a.findViewById(R.id.detailUploaderThumbnailView); | ||||||
| @@ -238,6 +242,7 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|                 case VideoInfo.VIDEO_AVAILABLE: { |                 case VideoInfo.VIDEO_AVAILABLE: { | ||||||
|                     videoTitleView.setText(info.title); |                     videoTitleView.setText(info.title); | ||||||
|                     uploaderView.setText(info.uploader); |                     uploaderView.setText(info.uploader); | ||||||
|  |                     actionBarHandler.setChannelName(info.uploader); | ||||||
|  |  | ||||||
|                     Locale locale = getPreferredLocale(); |                     Locale locale = getPreferredLocale(); | ||||||
|                     NumberFormat nf = NumberFormat.getInstance(locale); |                     NumberFormat nf = NumberFormat.getInstance(locale); | ||||||
| @@ -266,6 +271,7 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|                     descriptionView.setText(Html.fromHtml(info.description)); |                     descriptionView.setText(Html.fromHtml(info.description)); | ||||||
|                     descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); |                     descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); | ||||||
|  |  | ||||||
|  |                     actionBarHandler.setServiceId(streamingServiceId); | ||||||
|                     actionBarHandler.setVideoInfo(info.webpage_url, info.title); |                     actionBarHandler.setVideoInfo(info.webpage_url, info.title); | ||||||
|                     actionBarHandler.setStartPosition(info.startPosition); |                     actionBarHandler.setStartPosition(info.startPosition); | ||||||
|  |  | ||||||
| @@ -288,12 +294,12 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|                     public void onClick(View v) { |                     public void onClick(View v) { | ||||||
|                         Intent detailIntent = |                         Intent detailIntent = | ||||||
|                                 new Intent(getActivity(), VideoItemDetailActivity.class); |                                 new Intent(getActivity(), VideoItemDetailActivity.class); | ||||||
|                         detailIntent.putExtra( |                         /*detailIntent.putExtra( | ||||||
|                                 VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); |                                 VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */ | ||||||
|                         detailIntent.putExtra( |                         detailIntent.putExtra( | ||||||
|                                 VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url); |                                 VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url); | ||||||
|                         //todo: make id dynamic the following line is crap |                         //todo: make id dynamic the following line is crap | ||||||
|                         detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, 0); |                         detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId); | ||||||
|                         startActivity(detailIntent); |                         startActivity(detailIntent); | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
| @@ -369,8 +375,8 @@ public class VideoItemDetailFragment extends Fragment { | |||||||
|         // Otherwise the applications would crash. |         // Otherwise the applications would crash. | ||||||
|         if(playVideoButton != null) { |         if(playVideoButton != null) { | ||||||
|             try { |             try { | ||||||
|                 StreamingService streamingService = ServiceList.getService( |                 streamingServiceId = getArguments().getInt(STREAMING_SERVICE); | ||||||
|                         getArguments().getInt(STREAMING_SERVICE)); |                 StreamingService streamingService = ServiceList.getService(streamingServiceId); | ||||||
|                 Thread videoExtractorThread = new Thread(new VideoExtractorRunnable( |                 Thread videoExtractorThread = new Thread(new VideoExtractorRunnable( | ||||||
|                         getArguments().getString(VIDEO_URL), streamingService)); |                         getArguments().getString(VIDEO_URL), streamingService)); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -190,7 +190,7 @@ public class VideoItemListActivity extends AppCompatActivity | |||||||
|             // adding or replacing the detail fragment using a |             // adding or replacing the detail fragment using a | ||||||
|             // fragment transaction. |             // fragment transaction. | ||||||
|             Bundle arguments = new Bundle(); |             Bundle arguments = new Bundle(); | ||||||
|             arguments.putString(VideoItemDetailFragment.ARG_ITEM_ID, id); |             //arguments.putString(VideoItemDetailFragment.ARG_ITEM_ID, id); | ||||||
|             arguments.putString(VideoItemDetailFragment.VIDEO_URL, webpage_url); |             arguments.putString(VideoItemDetailFragment.VIDEO_URL, webpage_url); | ||||||
|             arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingServiceId); |             arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingServiceId); | ||||||
|             videoFragment = new VideoItemDetailFragment(); |             videoFragment = new VideoItemDetailFragment(); | ||||||
| @@ -209,7 +209,7 @@ public class VideoItemListActivity extends AppCompatActivity | |||||||
|             // In single-pane mode, simply start the detail activity |             // In single-pane mode, simply start the detail activity | ||||||
|             // for the selected item ID. |             // for the selected item ID. | ||||||
|             Intent detailIntent = new Intent(this, VideoItemDetailActivity.class); |             Intent detailIntent = new Intent(this, VideoItemDetailActivity.class); | ||||||
|             detailIntent.putExtra(VideoItemDetailFragment.ARG_ITEM_ID, id); |             //detailIntent.putExtra(VideoItemDetailFragment.ARG_ITEM_ID, id); | ||||||
|             detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, webpage_url); |             detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, webpage_url); | ||||||
|             detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingServiceId); |             detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, currentStreamingServiceId); | ||||||
|             startActivity(detailIntent); |             startActivity(detailIntent); | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-hdpi/ic_pause_white_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 105 B | 
| After Width: | Height: | Size: 358 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-mdpi/ic_pause_white_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 83 B | 
| After Width: | Height: | Size: 255 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 90 B | 
| After Width: | Height: | Size: 464 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 92 B | 
| After Width: | Height: | Size: 666 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxxhdpi/ic_pause_white_24dp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 94 B | 
| After Width: | Height: | Size: 883 B | 
| @@ -50,6 +50,8 @@ | |||||||
|     <string name="settingsCategoryVideoAudioTitle">VIDEO & AUDIO</string> |     <string name="settingsCategoryVideoAudioTitle">VIDEO & AUDIO</string> | ||||||
|     <string name="settingsCategoryVideoInfoTittle">INFO</string> |     <string name="settingsCategoryVideoInfoTittle">INFO</string> | ||||||
|     <string name="settingsCategoryEtcTitle">ETC</string> |     <string name="settingsCategoryEtcTitle">ETC</string> | ||||||
|  |     <string name="backgroundPlayerTickerText" translatable="false">%1$s - NewPipe</string> | ||||||
|  |     <string name="backgroundPlayerStartPlayingToast">Playing in background</string> | ||||||
|  |  | ||||||
|     <!-- Content descriptions (for better accessibility) --> |     <!-- Content descriptions (for better accessibility) --> | ||||||
|     <string name="itemThumbnailViewDescription">Video preview thumbnail</string> |     <string name="itemThumbnailViewDescription">Video preview thumbnail</string> | ||||||
|   | |||||||
 Christian Schabesberger
					Christian Schabesberger