diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b91e44fee..3a7547137 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ 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 diff --git a/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java b/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java index c14f93b56..2a4096d4a 100644 --- a/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java +++ b/app/src/main/java/org/schabi/newpipe/ActionBarHandler.java @@ -298,38 +298,39 @@ public class ActionBarHandler { intent.putExtra(Intent.EXTRA_TITLE, videoTitle); intent.putExtra("title", videoTitle); activity.startService(intent); - } - /*Intent 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); + } 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(); - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setMessage(R.string.noPlayerFound) - .setPositiveButton(R.string.installStreamPlayer, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_VIEW); - intent.setData(Uri.parse(activity.getString(R.string.fdroidVLCurl))); - activity.startActivity(intent); - } - }) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Log.i(TAG, "You unlocked a secret unicorn."); - } - }); - builder.create().show(); - Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:"); - e.printStackTrace(); - }*/ + activity.startActivity(intent); // HERE !!! + } catch (Exception e) { + e.printStackTrace(); + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setMessage(R.string.noPlayerFound) + .setPositiveButton(R.string.installStreamPlayer, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(activity.getString(R.string.fdroidVLCurl))); + activity.startActivity(intent); + } + }) + .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Log.i(TAG, "You unlocked a secret unicorn."); + } + }); + builder.create().show(); + Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:"); + e.printStackTrace(); + } + } } } diff --git a/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java index b47a59248..7cf49fda6 100644 --- a/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/BackgroundPlayer.java @@ -2,11 +2,21 @@ package org.schabi.newpipe; import android.app.IntentService; import android.app.Notification; -import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.media.MediaPlayer; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; import android.os.PowerManager; +import android.support.v7.app.NotificationCompat; +import android.widget.Toast; +import android.os.Process; import java.io.IOException; @@ -30,44 +40,145 @@ import java.io.IOException; * You should have received a copy of the GNU General Public License * along with NewPipe. If not, see <http://www.gnu.org/licenses/>. */ -public class BackgroundPlayer extends IntentService /*implements MediaPlayer.OnPreparedListener*/ { + +/**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(); - /** - * Creates an IntentService. Invoked by your subclass's constructor. - */ + private Looper mServiceLooper; + private ServiceHandler mServiceHandler; + public BackgroundPlayer() { - super(TAG); + super(); } @Override + public void onCreate() { + // Start up the thread running the service. Note that we create a + // separate thread because the service normally runs in the process's + // main thread, which we don't want to block. We also make it + // background priority so CPU-intensive work will not disrupt our UI. + super.onCreate(); + HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); + thread.start(); + + // Get the HandlerThread's Looper and use it for our Handler + mServiceLooper = thread.getLooper(); + mServiceHandler = new ServiceHandler(mServiceLooper); + } + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Toast.makeText(this, "Playing in background", Toast.LENGTH_SHORT).show();//todo:translation string + + // For each start request, send a message to start a job and deliver the + // start ID so we know which request we're stopping when we finish the job + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = startId; + msg.obj = intent; + mServiceHandler.sendMessage(msg); + + // If we get killed, after returning from 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(); + mServiceLooper.quit(); + } + protected void onHandleIntent(Intent intent) { String source = intent.getDataString(); + if (intent.getAction().equals(ACTION_PLAY)) { + mMediaPlayer.setOnPreparedListener(this); + mMediaPlayer.prepareAsync(); // prepare async to not block main thread + } + + MediaPlayer mediaPlayer = new MediaPlayer(); - //mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//cpu lock apparently + mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//cpu lock mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); try { mediaPlayer.setDataSource(source); - mediaPlayer.prepare(); // IntentService already puts us in a separate worker thread, + mediaPlayer.prepare(); //IntentService already puts us in a separate worker thread, //so calling the blocking prepare() method should be ok } catch (IOException ioe) { ioe.printStackTrace(); //can't really do anything useful without a file to play; exit early return; } + + WifiManager wifiMgr = ((WifiManager)getSystemService(Context.WIFI_SERVICE)); + WifiManager.WifiLock 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.setOnPreparedListener(this); mediaPlayer.start(); + + String videoTitle = intent.getStringExtra("title"); + + Notification noti = new NotificationCompat.Builder(this) + .setPriority(Notification.PRIORITY_LOW) + .setCategory(Notification.CATEGORY_TRANSPORT) + .setContentTitle(videoTitle) + .setContentText("NewPipe is playing in the background")//todo: add translatable string + .setOngoing(true) + .setSmallIcon(R.mipmap.ic_launcher) + .build(); + + startForeground(TAG.hashCode(), noti); + } /* - PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, - new Intent(getApplicationContext(), MainActivity.class), - PendingIntent.FLAG_UPDATE_CURRENT); - Notification notification = new Notification(); - notification.tickerText = text; - notification.icon = R.drawable.play0; - notification.flags |= Notification.FLAG_ONGOING_EVENT; - notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample", - "Playing: " + songName, pi); - startForeground(NOTIFICATION_ID, notification);*/ + private class ListenerThread extends Thread implements AudioManager.OnAudioFocusChangeListener { + + } + + @Override + public void onAudioFocusChange(int focusChange) { + + }*/ + + private class EndListener implements MediaPlayer.OnCompletionListener { + private WifiManager.WifiLock wl; + public EndListener(WifiManager.WifiLock wifiLock) { + this.wl = wifiLock; + } + + @Override + public void onCompletion(MediaPlayer mp) { + wl.release(); + } + } + + // Handler that receives messages from the thread + private final class ServiceHandler extends Handler { + public ServiceHandler(Looper looper) { + super(looper); + } + @Override + public void handleMessage(Message msg) { + onHandleIntent((Intent)msg.obj); + // Stop the service using the startId, so that we don't stop + // the service in the middle of handling another job + stopSelfResult(msg.arg1); + } } } diff --git a/app/src/main/java/org/schabi/newpipe/services/youtube/YoutubeExtractor.java b/app/src/main/java/org/schabi/newpipe/services/youtube/YoutubeExtractor.java index cb996d2ef..cca460902 100644 --- a/app/src/main/java/org/schabi/newpipe/services/youtube/YoutubeExtractor.java +++ b/app/src/main/java/org/schabi/newpipe/services/youtube/YoutubeExtractor.java @@ -509,8 +509,8 @@ public class YoutubeExtractor extends Extractor { //this page causes the NullPointerException, after finding it by searching for "tjvg": //https://www.youtube.com/watch?v=Uqg0aEhLFAg String views = li.select("span.view-count").first().text(); - Log.i(TAG, "title:"+info.title); - Log.i(TAG, "view count:"+views); + //Log.i(TAG, "title:"+info.title); + //Log.i(TAG, "view count:"+views); try { info.view_count = Long.parseLong(li.select("span.view-count") .first().text().replaceAll("[^\\d]", ""));