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>
|
||||||
|
|