diff options
Diffstat (limited to 'News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services')
3 files changed, 370 insertions, 48 deletions
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java index 492cef8d..79100813 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/DownloadImagesService.java @@ -49,6 +49,7 @@ import de.luhmer.owncloudnewsreader.async_tasks.GetImageAsyncTask; import de.luhmer.owncloudnewsreader.database.DatabaseConnection; import de.luhmer.owncloudnewsreader.helper.BitmapDrawableLruCache; import de.luhmer.owncloudnewsreader.helper.FavIconHandler; +import de.luhmer.owncloudnewsreader.helper.FileUtils; import de.luhmer.owncloudnewsreader.helper.ImageDownloadFinished; import de.luhmer.owncloudnewsreader.helper.ImageHandler; @@ -144,7 +145,7 @@ public class DownloadImagesService extends IntentService { notificationManager.notify(NOTIFICATION_ID, notify); for (String link : links) - new GetImageAsyncTask(link, imgDownloadFinished, 999, ImageHandler.getPathImageCache(this), this, null).execute(); + new GetImageAsyncTask(link, imgDownloadFinished, 999, FileUtils.getPathImageCache(this), this, null).execute(); } } @@ -169,7 +170,7 @@ public class DownloadImagesService extends IntentService { private void RemoveOldImages(Context context) { HashMap<File, Long> files; - long size = ImageHandler.getFolderSize(new File(ImageHandler.getPath(context))); + long size = ImageHandler.getFolderSize(new File(FileUtils.getPath(context))); size = (long) (size / 1024d / 1024d); SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); @@ -177,7 +178,7 @@ public class DownloadImagesService extends IntentService { if(size > max_allowed_size) { files = new HashMap<File, Long>(); - for(File file : ImageHandler.getFilesFromDir(new File(ImageHandler.getPathImageCache(context)))) + for(File file : ImageHandler.getFilesFromDir(new File(FileUtils.getPathImageCache(context)))) { files.put(file, file.lastModified()); } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastDownloadService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastDownloadService.java new file mode 100644 index 00000000..0a88c77c --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastDownloadService.java @@ -0,0 +1,240 @@ +package de.luhmer.owncloudnewsreader.services; + +import android.annotation.TargetApi; +import android.app.DownloadManager; +import android.app.IntentService; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.ResultReceiver; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.math.BigInteger; +import java.net.URL; +import java.net.URLConnection; +import java.security.MessageDigest; + +import de.greenrobot.event.EventBus; +import de.luhmer.owncloudnewsreader.helper.FileUtils; +import de.luhmer.owncloudnewsreader.helper.JavaYoutubeDownloader; +import de.luhmer.owncloudnewsreader.model.PodcastItem; + +/** + * An {@link IntentService} subclass for handling asynchronous task requests in + * a service on a separate handler thread. + * <p> + * TODO: Customize class - update intent actions, extra parameters and static + * helper methods. + */ +public class PodcastDownloadService extends IntentService { + // TODO: Rename actions, choose action names that describe tasks that this + // IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS + private static final String ACTION_DOWNLOAD = "de.luhmer.owncloudnewsreader.services.action.DOWNLOAD"; + + + + // TODO: Rename parameters + private static final String EXTRA_RECEIVER = "de.luhmer.owncloudnewsreader.services.extra.RECEIVER"; + private static final String EXTRA_URL = "de.luhmer.owncloudnewsreader.services.extra.URL"; + private static final String EXTRA_PARAM2 = "de.luhmer.owncloudnewsreader.services.extra.PARAM2"; + private static final String TAG = "PodcastDownloadService"; + + private EventBus eventBus; + + /** + * Starts this service to perform action Foo with the given parameters. If + * the service is already performing a task this action will be queued. + * + * @see IntentService + */ + // TODO: Customize helper method + public static void startPodcastDownload(Context context, PodcastItem podcastItem/*, ResultReceiver receiver*/) { + Intent intent = new Intent(context, PodcastDownloadService.class); + intent.setAction(ACTION_DOWNLOAD); + intent.putExtra(EXTRA_URL, podcastItem); + //intent.putExtra(EXTRA_RECEIVER, receiver); + //intent.putExtra(EXTRA_PARAM2, param2); + context.startService(intent); + } + + + public PodcastDownloadService() { + super("PodcastDownloadService"); + + eventBus = EventBus.getDefault(); + } + + @Override + protected void onHandleIntent(Intent intent) { + + if (intent != null) { + final String action = intent.getAction(); + if (ACTION_DOWNLOAD.equals(action)) { + ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra(EXTRA_RECEIVER); + PodcastItem podcast = (PodcastItem) intent.getSerializableExtra(EXTRA_URL); + //final String param2 = intent.getStringExtra(EXTRA_PARAM2); + //handleActionDownload(podcast); + + downloadPodcast(podcast, this); + + + }/* else if (ACTION_BAZ.equals(action)) { + final String param1 = intent.getStringExtra(EXTRA_PARAM1); + final String param2 = intent.getStringExtra(EXTRA_PARAM2); + handleActionBaz(param1, param2); + }*/ + } + } + + /** + * Handle action Foo in the provided background thread with the provided + * parameters. + */ + @TargetApi(Build.VERSION_CODES.GINGERBREAD) + private void handleActionDownload(PodcastItem podcast) { + Uri uri = Uri.parse(podcast.link); + DownloadManager.Request request = new DownloadManager.Request(uri); + request.setDescription(podcast.mimeType); + request.setTitle(podcast.title); + + // in order for this if to run, you must use the android 3.2 to compile your app + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + request.allowScanningByMediaScanner(); + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); + } + + String path = "file://" + getUrlToPodcastFile(this, podcast.link, true); + request.setDestinationUri(Uri.parse(path)); + //request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "bla.txt"); + + // get download service and enqueue file + DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); + manager.enqueue(request); + } + + + public static String getUrlToPodcastFile(Context context, String WEB_URL_TO_FILE, boolean createDir) { + if(WEB_URL_TO_FILE.contains(JavaYoutubeDownloader.host)) + return getUrlToYoutubePodcastFile(context, WEB_URL_TO_FILE, createDir); + + File file = new File(WEB_URL_TO_FILE); + + String path = FileUtils.getPathPodcasts(context) + "/" + getHashOfString(WEB_URL_TO_FILE) + "/"; + if(createDir) + new File(path).mkdirs(); + + return path + file.getName(); + } + + private static String getUrlToYoutubePodcastFile(Context context, String WEB_URL_TO_FILE, boolean createDir) { + String path = FileUtils.getPathPodcasts(context) + "/" + getHashOfString(WEB_URL_TO_FILE) + "/"; + if(createDir) + new File(path).mkdirs(); + + return path + "video.mp4"; + } + + + public static String getHashOfString(String WEB_URL_TO_FILE) + { + try { + MessageDigest m = MessageDigest.getInstance("MD5"); + m.reset(); + m.update(WEB_URL_TO_FILE.trim().getBytes()); + byte[] digest = m.digest(); + BigInteger bigInt = new BigInteger(1,digest); + String hashtext = bigInt.toString(16); + + return hashtext; + } catch (Exception e) { + e.printStackTrace(); + } + return WEB_URL_TO_FILE; + } + + + private void downloadPodcast(PodcastItem podcast, Context context) { + try { + String urlTemp = podcast.link; + String path = getUrlToPodcastFile(this, urlTemp, true); + + if(podcast.link.contains(JavaYoutubeDownloader.host)) { + + path = getUrlToPodcastFile(context, urlTemp, true); + + try { + urlTemp = new JavaYoutubeDownloader().getDownloadUrl(podcast.link, context); + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + + } + URL url = new URL(urlTemp); + URLConnection connection = url.openConnection(); + connection.connect(); + connection.setConnectTimeout(10000); + connection.setReadTimeout(120000);//2min + // this will be useful so that you can show a typical 0-100% progress bar + int fileLength = connection.getContentLength(); + + // download the file + InputStream input = new BufferedInputStream(url.openStream()); + + + String pathCache = path + ".download"; + OutputStream output = new FileOutputStream(pathCache); + + + byte data[] = new byte[1024]; + long total = 0; + int count; + while ((count = input.read(data)) != -1) { + total += count; + + int progress = (int) (total * 100 / fileLength); + podcast.downloadProgress = progress; + eventBus.post(new DownloadProgressUpdate(podcast)); + + output.write(data, 0, count); + } + + output.flush(); + output.close(); + input.close(); + + + new File(pathCache).renameTo(new File(path)); + + } catch (IOException e) { + e.printStackTrace(); + } + + + podcast.downloadProgress = 100; + eventBus.post(new DownloadProgressUpdate(podcast)); + + /* + Bundle resultData = new Bundle(); + resultData.putInt("progress" ,100); + receiver.send(UPDATE_PROGRESS, resultData); + */ + } + + public static final int UPDATE_PROGRESS = 5555; + + + public class DownloadProgressUpdate { + + public DownloadProgressUpdate(PodcastItem podcast) { + this.podcast = podcast; + } + + public PodcastItem podcast; + } +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java index 7a656ba2..61c935ff 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java @@ -5,12 +5,16 @@ import android.content.Intent; import android.media.MediaPlayer; import android.os.Handler; import android.os.IBinder; +import android.util.Log; import android.view.SurfaceHolder; +import android.view.View; import java.io.IOException; import de.greenrobot.event.EventBus; -import de.luhmer.owncloudnewsreader.events.podcast.OpenAudioPodcastEvent; +import de.luhmer.owncloudnewsreader.R; +import de.luhmer.owncloudnewsreader.events.podcast.NewPodcastPlaybackListener; +import de.luhmer.owncloudnewsreader.events.podcast.OpenPodcastEvent; import de.luhmer.owncloudnewsreader.events.podcast.RegisterVideoOutput; import de.luhmer.owncloudnewsreader.events.podcast.TogglePlayerStateEvent; import de.luhmer.owncloudnewsreader.events.podcast.UpdatePodcastStatusEvent; @@ -19,33 +23,35 @@ import de.luhmer.owncloudnewsreader.view.PodcastNotification; public class PodcastPlaybackService extends Service { + private static final String TAG = "PodcastPlaybackService"; PodcastNotification podcastNotification; @Override public void onCreate() { podcastNotification = new PodcastNotification(this); + mediaTitle = getString(R.string.no_podcast_selected); + super.onCreate(); } public PodcastPlaybackService() { - mediaPlayer = new MediaPlayer(); + mMediaPlayer = new MediaPlayer(); mHandler = new Handler(); eventBus = EventBus.getDefault(); eventBus.register(this); - - - mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mediaPlayer) { play(); isPreparing = false; + canCallGetDuration = true; } }); - mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mediaPlayer) { pause();//Send the over signal @@ -53,39 +59,52 @@ public class PodcastPlaybackService extends Service { }); + eventBus.post(new PodcastPlaybackServiceStarted()); + + mHandler.postDelayed(mUpdateTimeTask, 0); + //openFile("/sdcard/Music/#Musik/Finest Tunes/Netsky - Running Low (Ft. Beth Ditto).mp3"); } @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return Service.START_STICKY; + //return super.onStartCommand(intent, flags, startId); + } + + @Override public IBinder onBind(Intent intent) { - // TODO: Return the communication channel to the service. - throw new UnsupportedOperationException("Not yet implemented"); + return null; + //throw new UnsupportedOperationException("Not yet implemented"); } private EventBus eventBus; private Handler mHandler; - private MediaPlayer mediaPlayer; + private MediaPlayer mMediaPlayer; private String mediaTitle; + View parentResizableView; public static final int delay = 500; //In milliseconds + private boolean canCallGetDuration = false;//Otherwise the player would call getDuration all the time without loading a media file private boolean isPreparing = false; + private boolean isVideoFile = false; public void openFile(String pathToFile, String mediaTitle) { try { - this.mediaTitle = mediaTitle; - - if(mediaPlayer.isPlaying()) + if(mMediaPlayer.isPlaying()) pause(); + this.mediaTitle = mediaTitle; + isPreparing = true; mHandler.postDelayed(mUpdateTimeTask, 0); - mediaPlayer.reset(); - mediaPlayer.setDataSource(pathToFile); - mediaPlayer.prepareAsync(); + mMediaPlayer.reset(); + mMediaPlayer.setDataSource(pathToFile); + mMediaPlayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); isPreparing = false; @@ -104,7 +123,7 @@ public class PodcastPlaybackService extends Service { }; public void onEvent(TogglePlayerStateEvent event) { - if(mediaPlayer.isPlaying()) { + if(mMediaPlayer.isPlaying()) { pause(); } else { play(); @@ -112,49 +131,91 @@ public class PodcastPlaybackService extends Service { } public void onEvent(WindPodcast event) { - if(mediaPlayer != null) { - double totalDuration = mediaPlayer.getDuration(); + if(mMediaPlayer != null) { + double totalDuration = mMediaPlayer.getDuration(); int position = (int)((totalDuration / 100d) * event.toPositionInPercent); - mediaPlayer.seekTo(position); + mMediaPlayer.seekTo(position); } } - public void onEventBackgroundThread(OpenAudioPodcastEvent event) { + public void onEventBackgroundThread(OpenPodcastEvent event) { + this.isVideoFile = event.isVideoFile; openFile(event.pathToFile, event.mediaTitle); } public void onEvent(RegisterVideoOutput videoOutput) { - if(mediaPlayer != null) { - //getHolder().addCallback(videoOutput); - videoOutput.surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); + if(mMediaPlayer != null) { + if(videoOutput.surfaceView == null) { + mMediaPlayer.setDisplay(null); + Log.d(TAG, "Disable Screen output!"); + + mMediaPlayer.setScreenOnWhilePlaying(false); + } else { + if(videoOutput.surfaceView.getHolder() != mSurfaceHolder) { + parentResizableView = videoOutput.parentResizableView; + + videoOutput.surfaceView.getHolder().addCallback(mSHCallback); + //videoOutput.surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); + + populateVideo(); + + Log.d(TAG, "Enable Screen output!"); + } + } } } + public void onEvent(NewPodcastPlaybackListener newListener) { + sendMediaStatus(); + } + public void play() { - mediaPlayer.start(); + try { + int progress = mMediaPlayer.getCurrentPosition() / mMediaPlayer.getDuration(); + if (progress >= 1) { + mMediaPlayer.seekTo(0); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + + mMediaPlayer.start(); mHandler.removeCallbacks(mUpdateTimeTask); mHandler.postDelayed(mUpdateTimeTask, 0); + + populateVideo(); + } + + private void populateVideo() { + double videoHeightRel = (double) mSurfaceWidth / (double) mMediaPlayer.getVideoWidth(); + int videoHeight = (int) (mMediaPlayer.getVideoHeight() * videoHeightRel); + + if (mSurfaceWidth != 0 && videoHeight != 0 && mSurfaceHolder != null) { + //mSurfaceHolder.setFixedSize(mSurfaceWidth, videoHeight); + + parentResizableView.getLayoutParams().height = videoHeight; + parentResizableView.setLayoutParams(parentResizableView.getLayoutParams()); + } } public void pause() { - if(mediaPlayer.isPlaying()) - mediaPlayer.pause(); + if(mMediaPlayer.isPlaying()) + mMediaPlayer.pause(); mHandler.removeCallbacks(mUpdateTimeTask); - sendMediaStatus(); } public void sendMediaStatus() { long totalDuration = 0; long currentDuration = 0; - if(!isPreparing) { - totalDuration = mediaPlayer.getDuration(); - currentDuration = mediaPlayer.getCurrentPosition(); + if(!isPreparing && canCallGetDuration) { + totalDuration = mMediaPlayer.getDuration(); + currentDuration = mMediaPlayer.getCurrentPosition(); } /* @@ -169,21 +230,43 @@ public class PodcastPlaybackService extends Service { songProgressBar.setProgress(progress); */ - UpdatePodcastStatusEvent audioPodcastEvent = new UpdatePodcastStatusEvent(currentDuration, totalDuration, mediaPlayer.isPlaying(), mediaTitle, isPreparing); + UpdatePodcastStatusEvent audioPodcastEvent = new UpdatePodcastStatusEvent(currentDuration, totalDuration, mMediaPlayer.isPlaying(), mediaTitle, isPreparing, canCallGetDuration, isVideoFile); eventBus.post(audioPodcastEvent); } + public class PodcastPlaybackServiceStarted { + + } + + /* + public class VideoAvailableState { + public VideoAvailableState(boolean isVideoAvailable) { + this.isVideoAvailable = isVideoAvailable; + } + + public boolean isVideoAvailable; + } + */ + + int mSurfaceWidth; + int mSurfaceHeight; + SurfaceHolder mSurfaceHolder; SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() { - public void surfaceChanged(SurfaceHolder holder, int format, - int w, int h) + public void surfaceChanged(SurfaceHolder holder, int format, int surfaceWidth, int surfaceHeight) { - mSurfaceWidth = w; - mSurfaceHeight = h; - if (mIsPrepared && mVideoWidth == w && mVideoHeight == h) { + mSurfaceWidth = surfaceWidth; + mSurfaceHeight = surfaceHeight; + + //populateVideo(); + + //Log.d(TAG, "surfaceChanged"); + + /* + if (!isPreparing && mVideoWidth == w && mVideoHeight == h) { if (mSeekWhenPrepared != 0) { mMediaPlayer.seekTo(mSeekWhenPrepared); } @@ -192,24 +275,22 @@ public class PodcastPlaybackService extends Service { mMediaController.show(); } } + */ } public void surfaceCreated(SurfaceHolder holder) { mSurfaceHolder = holder; - openVideo(); + mMediaPlayer.setDisplay(mSurfaceHolder); + + mMediaPlayer.setScreenOnWhilePlaying(true); + + Log.d(TAG, "surfaceCreated"); } public void surfaceDestroyed(SurfaceHolder holder) { - // after we return from this we can't use the surface any more - mSurfaceHolder = null; - if (mMediaController != null) mMediaController.hide(); - if (mMediaPlayer != null) { - mMediaPlayer.reset(); - mMediaPlayer.release(); - mMediaPlayer = null; - } + Log.d(TAG, "surfaceDestroyed"); } }; |