X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/ce7f7fa48c5cce2070a8e42ec19d1954a18db090..7bec1569f70349bcc1e71c4e04c2adf18572bbfe:/src/com/owncloud/android/media/MediaService.java diff --git a/src/com/owncloud/android/media/MediaService.java b/src/com/owncloud/android/media/MediaService.java index f8e70fe7..5b865262 100644 --- a/src/com/owncloud/android/media/MediaService.java +++ b/src/com/owncloud/android/media/MediaService.java @@ -1,10 +1,12 @@ -/* ownCloud Android client application - * Copyright 2013 ownCloud Inc. +/** + * ownCloud Android client application + * + * @author David A. Velasco + * Copyright (C) 2015 ownCloud Inc. * * This program 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. + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -34,25 +36,23 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.WifiLock; import android.os.IBinder; import android.os.PowerManager; -import android.util.Log; -import android.widget.MediaController; +import android.support.v7.app.NotificationCompat; import android.widget.Toast; import java.io.IOException; -import com.owncloud.android.AccountUtils; import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.ui.activity.FileDetailActivity; -import com.owncloud.android.ui.fragment.FileDetailFragment; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.ui.activity.FileActivity; +import com.owncloud.android.ui.activity.FileDisplayActivity; + /** * Service that handles media playback, both audio and video. * * Waits for Intents which signal the service to perform specific operations: Play, Pause, * Rewind, etc. - * - * @author David A. Velasco */ public class MediaService extends Service implements OnCompletionListener, OnPreparedListener, OnErrorListener, AudioManager.OnAudioFocusChangeListener { @@ -68,12 +68,15 @@ public class MediaService extends Service implements OnCompletionListener, OnPre /// Keys to add extras to the action public static final String EXTRA_FILE = MY_PACKAGE + ".extra.FILE"; public static final String EXTRA_ACCOUNT = MY_PACKAGE + ".extra.ACCOUNT"; + public static String EXTRA_START_POSITION = MY_PACKAGE + ".extra.START_POSITION"; + public static final String EXTRA_PLAY_ON_LOAD = MY_PACKAGE + ".extra.PLAY_ON_LOAD"; + /** Error code for specific messages - see regular error codes at {@link MediaPlayer} */ public static final int OC_MEDIA_ERROR = 0; /** Time To keep the control panel visible when the user does not use it */ - public static final int MEDIA_CONTROL_SHORT_LIFE = 5000; + public static final int MEDIA_CONTROL_SHORT_LIFE = 4000; /** Time To keep the control panel visible when the user does not use it */ public static final int MEDIA_CONTROL_PERMANENT = 0; @@ -121,7 +124,6 @@ public class MediaService extends Service implements OnCompletionListener, OnPre /** Notification to keep in the notification bar while a song is playing */ private NotificationManager mNotificationManager; - private Notification mNotification = null; /** File being played */ private OCFile mFile; @@ -129,13 +131,20 @@ public class MediaService extends Service implements OnCompletionListener, OnPre /** Account holding the file being played */ private Account mAccount; + /** Flag signaling if the audio should be played immediately when the file is prepared */ + protected boolean mPlayOnPrepared; + + /** Position, in miliseconds, where the audio should be started */ + private int mStartPosition; + /** Interface to access the service through binding */ private IBinder mBinder; /** Control panel shown to the user to control the playback, to register through binding */ private MediaControlView mMediaController; - + /** Notification builder to create notifications, new reuse way since Android 6 */ + private NotificationCompat.Builder mNotificationBuilder; /** * Helper method to get an error message suitable to show to users for errors occurred in media playback, @@ -211,12 +220,15 @@ public class MediaService extends Service implements OnCompletionListener, OnPre */ @Override public void onCreate() { - Log.d(TAG, "Creating ownCloud media service"); + super.onCreate(); + Log_OC.d(TAG, "Creating ownCloud media service"); mWifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)). createWifiLock(WifiManager.WIFI_MODE_FULL, MEDIA_WIFI_LOCK_TAG); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + mNotificationBuilder = new NotificationCompat.Builder(this); + mNotificationBuilder.setColor(this.getResources().getColor(R.color.primary)); mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE); mBinder = new MediaServiceBinder(this); } @@ -252,6 +264,8 @@ public class MediaService extends Service implements OnCompletionListener, OnPre if (mState != State.PREPARING) { mFile = intent.getExtras().getParcelable(EXTRA_FILE); mAccount = intent.getExtras().getParcelable(EXTRA_ACCOUNT); + mPlayOnPrepared = intent.getExtras().getBoolean(EXTRA_PLAY_ON_LOAD, false); + mStartPosition = intent.getExtras().getInt(EXTRA_START_POSITION, 0); tryToGetAudioFocus(); playMedia(); } @@ -275,14 +289,13 @@ public class MediaService extends Service implements OnCompletionListener, OnPre mState = State.PLAYING; setUpAsForeground(String.format(getString(R.string.media_state_playing), mFile.getFileName())); configAndStartMediaPlayer(); - } } /** * Makes sure the media player exists and has been reset. This will create the media player - * if needed, or reset the existing media player if one already exists. + * if needed. reset the existing media player if one already exists. */ protected void createMediaPlayerIfNeeded() { if (mPlayer == null) { @@ -457,22 +470,22 @@ public class MediaService extends Service implements OnCompletionListener, OnPre } } catch (SecurityException e) { - Log.e(TAG, "SecurityException playing " + mAccount.name + mFile.getRemotePath(), e); + Log_OC.e(TAG, "SecurityException playing " + mAccount.name + mFile.getRemotePath(), e); Toast.makeText(this, String.format(getString(R.string.media_err_security_ex), mFile.getFileName()), Toast.LENGTH_LONG).show(); processStopRequest(true); } catch (IOException e) { - Log.e(TAG, "IOException playing " + mAccount.name + mFile.getRemotePath(), e); + Log_OC.e(TAG, "IOException playing " + mAccount.name + mFile.getRemotePath(), e); Toast.makeText(this, String.format(getString(R.string.media_err_io_ex), mFile.getFileName()), Toast.LENGTH_LONG).show(); processStopRequest(true); } catch (IllegalStateException e) { - Log.e(TAG, "IllegalStateException " + mAccount.name + mFile.getRemotePath(), e); + Log_OC.e(TAG, "IllegalStateException " + mAccount.name + mFile.getRemotePath(), e); Toast.makeText(this, String.format(getString(R.string.media_err_unexpected), mFile.getFileName()), Toast.LENGTH_LONG).show(); processStopRequest(true); } catch (IllegalArgumentException e) { - Log.e(TAG, "IllegalArgumentException " + mAccount.name + mFile.getRemotePath(), e); + Log_OC.e(TAG, "IllegalArgumentException " + mAccount.name + mFile.getRemotePath(), e); Toast.makeText(this, String.format(getString(R.string.media_err_unexpected), mFile.getFileName()), Toast.LENGTH_LONG).show(); processStopRequest(true); } @@ -482,7 +495,15 @@ public class MediaService extends Service implements OnCompletionListener, OnPre /** Called when media player is done playing current song. */ public void onCompletion(MediaPlayer player) { Toast.makeText(this, String.format(getString(R.string.media_event_done, mFile.getFileName())), Toast.LENGTH_LONG).show(); - processStopRequest(true); + if (mMediaController != null) { + // somebody is still bound to the service + player.seekTo(0); + processPauseRequest(); + mMediaController.updatePausePlay(); + } else { + // nobody is bound + processStopRequest(true); + } return; } @@ -498,7 +519,12 @@ public class MediaService extends Service implements OnCompletionListener, OnPre if (mMediaController != null) { mMediaController.setEnabled(true); } + player.seekTo(mStartPosition); configAndStartMediaPlayer(); + if (!mPlayOnPrepared) { + processPauseRequest(); + } + if (mMediaController != null) { mMediaController.updatePausePlay(); } @@ -508,22 +534,25 @@ public class MediaService extends Service implements OnCompletionListener, OnPre /** * Updates the status notification */ - @SuppressWarnings("deprecation") private void updateNotification(String content) { + String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name)); + // TODO check if updating the Intent is really necessary - Intent showDetailsIntent = new Intent(this, FileDetailActivity.class); - showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, mFile); - showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, mAccount); + Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class); + showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, mFile); + showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, mAccount); showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), - (int)System.currentTimeMillis(), - showDetailsIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - mNotification.when = System.currentTimeMillis(); - //mNotification.contentView.setTextViewText(R.id.status_text, content); - String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name)); - mNotification.setLatestEventInfo(getApplicationContext(), ticker, content, mNotification.contentIntent); - mNotificationManager.notify(R.string.media_notif_ticker, mNotification); + + mNotificationBuilder.setContentIntent(PendingIntent.getActivity(getApplicationContext(), + (int) System.currentTimeMillis(), + showDetailsIntent, + PendingIntent.FLAG_UPDATE_CURRENT)); + mNotificationBuilder.setWhen(System.currentTimeMillis()); + mNotificationBuilder.setTicker(ticker); + mNotificationBuilder.setContentTitle(ticker); + mNotificationBuilder.setContentText(content); + + mNotificationManager.notify(R.string.media_notif_ticker, mNotificationBuilder.build()); } @@ -534,35 +563,29 @@ public class MediaService extends Service implements OnCompletionListener, OnPre * * A notification must be created to keep the user aware of the existance of the service. */ - @SuppressWarnings("deprecation") private void setUpAsForeground(String content) { + String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name)); + /// creates status notification // TODO put a progress bar to follow the playback progress - mNotification = new Notification(); - mNotification.icon = android.R.drawable.ic_media_play; + mNotificationBuilder.setSmallIcon(R.drawable.ic_play_arrow); //mNotification.tickerText = text; - mNotification.when = System.currentTimeMillis(); - mNotification.flags |= Notification.FLAG_ONGOING_EVENT; - //mNotification.contentView.setTextViewText(R.id.status_text, "ownCloud Music Player"); // NULL POINTER - //mNotification.contentView.setTextViewText(R.id.status_text, getString(R.string.downloader_download_in_progress_content)); - + mNotificationBuilder.setWhen(System.currentTimeMillis()); + mNotificationBuilder.setOngoing(true); /// includes a pending intent in the notification showing the details view of the file - Intent showDetailsIntent = new Intent(this, FileDetailActivity.class); - showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, mFile); - showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, mAccount); + Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class); + showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, mFile); + showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, mAccount); showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), - (int)System.currentTimeMillis(), - showDetailsIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - - - //mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification); - String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name)); - mNotification.setLatestEventInfo(getApplicationContext(), ticker, content, mNotification.contentIntent); - startForeground(R.string.media_notif_ticker, mNotification); - + mNotificationBuilder.setContentIntent(PendingIntent.getActivity(getApplicationContext(), + (int) System.currentTimeMillis(), + showDetailsIntent, + PendingIntent.FLAG_UPDATE_CURRENT)); + mNotificationBuilder.setContentTitle(ticker); + mNotificationBuilder.setContentText(content); + + startForeground(R.string.media_notif_ticker, mNotificationBuilder.build()); } /** @@ -571,7 +594,7 @@ public class MediaService extends Service implements OnCompletionListener, OnPre * Warns the user about the error and resets the media player. */ public boolean onError(MediaPlayer mp, int what, int extra) { - Log.e(TAG, "Error in audio playback, what = " + what + ", extra = " + extra); + Log_OC.e(TAG, "Error in audio playback, what = " + what + ", extra = " + extra); String message = getMessageForMediaError(this, what, extra); Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show(); @@ -615,6 +638,8 @@ public class MediaService extends Service implements OnCompletionListener, OnPre mState = State.STOPPED; releaseResources(true); giveUpAudioFocus(); + stopForeground(true); + super.onDestroy(); }