diff options
author | Christian Schneppe <christian@pix-art.de> | 2017-09-24 21:27:52 +0200 |
---|---|---|
committer | Christian Schneppe <christian@pix-art.de> | 2017-09-24 21:30:58 +0200 |
commit | 83f362c8b4f25d56ab2a74e37acd6b0fd0125a9c (patch) | |
tree | 01b2b07c70a307a526944133b6dfc88f3e2c0604 | |
parent | 259d29518331c4517c36e2baf073615fb7bf193f (diff) |
refactored AudioPlayer
37 files changed, 390 insertions, 910 deletions
diff --git a/build.gradle b/build.gradle index 1f51bd01c..cccf9e65b 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,6 @@ configurations { dependencies { compile project(':libs:MemorizingTrustManager') - compile project(':libs:audiowife') compile project(':libs:android-transcoder') standardPushCompile 'com.google.android.gms:play-services-gcm:11.0.4' compile 'org.sufficientlysecure:openpgp-api:10.0' diff --git a/libs/audiowife/.gitignore b/libs/audiowife/.gitignore deleted file mode 100644 index e99645287..000000000 --- a/libs/audiowife/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.gradle -.idea -build -*.iml -*.properties
\ No newline at end of file diff --git a/libs/audiowife/build.gradle b/libs/audiowife/build.gradle deleted file mode 100644 index 883d7aab1..000000000 --- a/libs/audiowife/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 26 - buildToolsVersion "26.0.1" - - defaultConfig { - minSdkVersion 14 - targetSdkVersion 26 - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - - } - } - - // It would be better to fix the issues - lintOptions { - abortOnError false - } -} - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) -} diff --git a/libs/audiowife/src/main/AndroidManifest.xml b/libs/audiowife/src/main/AndroidManifest.xml deleted file mode 100644 index 5876c3afe..000000000 --- a/libs/audiowife/src/main/AndroidManifest.xml +++ /dev/null @@ -1,10 +0,0 @@ -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="nl.changer.audiowife"> - - <application - android:allowBackup="true" - android:label="@string/app_name"> - - </application> - -</manifest> diff --git a/libs/audiowife/src/main/java/nl/changer/audiowife/AudioWife.java b/libs/audiowife/src/main/java/nl/changer/audiowife/AudioWife.java deleted file mode 100644 index 25bf7a003..000000000 --- a/libs/audiowife/src/main/java/nl/changer/audiowife/AudioWife.java +++ /dev/null @@ -1,699 +0,0 @@ -/*** - * The MIT License (MIT) - * <p/> - * Copyright (c) 2014 Jaydeep - * <p/> - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * <p/> - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * <p/> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package nl.changer.audiowife; - -import android.content.Context; -import android.media.AudioManager; -import android.media.MediaPlayer; -import android.media.MediaPlayer.OnCompletionListener; -import android.net.Uri; -import android.os.Handler; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.SeekBar; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.concurrent.TimeUnit; - -/*** - * A simple audio player wrapper for Android - ***/ -public class AudioWife { - - private static final String TAG = AudioWife.class.getSimpleName(); - /**** - * Playback progress update time in milliseconds - ****/ - private static final int AUDIO_PROGRESS_UPDATE_TIME = 100; - // TODO: externalize the error messages. - private static final String ERROR_PLAYVIEW_NULL = "Play view cannot be null"; - private static final String ERROR_PLAYTIME_CURRENT_NEGATIVE = "Current playback time cannot be negative"; - private static final String ERROR_PLAYTIME_TOTAL_NEGATIVE = "Total playback time cannot be negative"; - /*** - * Keep a single copy of this in memory unless required to create a new instance explicitly. - ****/ - private static AudioWife mAudioWife; - /*** - * Audio URI - ****/ - private static Uri mUri; - private Handler mProgressUpdateHandler; - private MediaPlayer mMediaPlayer; - private SeekBar mSeekBar; - @Deprecated - /*** - * Set both current playack time and total runtime - * of the audio in the UI. - */ - private TextView mPlaybackTime; - private View mPlayButton; - private View mPauseButton; - /*** - * Indicates the current run-time of the audio being played - */ - private TextView mRunTime; - /*** - * Indicates the total duration of the audio being played. - */ - private TextView mTotalTime; - /*** - * Set if AudioWife is using the default UI provided with the library. - **/ - private boolean mHasDefaultUi; - /**** - * Array to hold custom completion listeners - ****/ - private ArrayList<OnCompletionListener> mCompletionListeners = new ArrayList<OnCompletionListener>(); - private ArrayList<View.OnClickListener> mPlayListeners = new ArrayList<View.OnClickListener>(); - private ArrayList<View.OnClickListener> mPauseListeners = new ArrayList<View.OnClickListener>(); - private Runnable mUpdateProgress = new Runnable() { - - public void run() { - - if (mSeekBar == null) { - return; - } - - if (mProgressUpdateHandler != null && mMediaPlayer.isPlaying()) { - mSeekBar.setProgress((int) mMediaPlayer.getCurrentPosition()); - int currentTime = mMediaPlayer.getCurrentPosition(); - updatePlaytime(currentTime); - updateRuntime(currentTime); - // repeat the process - mProgressUpdateHandler.postDelayed(this, AUDIO_PROGRESS_UPDATE_TIME); - } else { - // DO NOT update UI if the player is paused - } - } - }; - private OnCompletionListener mOnCompletion = new OnCompletionListener() { - - @Override - public void onCompletion(MediaPlayer mp) { - // set UI when audio finished playing - int currentPlayTime = 0; - mSeekBar.setProgress((int) currentPlayTime); - updatePlaytime(currentPlayTime); - updateRuntime(currentPlayTime); - setPlayable(); - // ensure that our completion listener fires first. - // This will provide the developer to over-ride our - // completion listener functionality - - fireCustomCompletionListeners(mp); - } - }; - private View playerUi; - - public static AudioWife getInstance() { - - if (mAudioWife == null) { - mAudioWife = new AudioWife(); - } - - return mAudioWife; - } - - /*** - * Starts playing audio file associated. Before playing the audio, visibility of appropriate UI - * controls is made visible. Calling this method has no effect if the audio is already being - * played. - ****/ - public void play() { - - // if play button itself is null, the whole purpose of AudioWife is - // defeated. - if (mPlayButton == null) { - throw new IllegalStateException(ERROR_PLAYVIEW_NULL); - } - - if (mUri == null) { - throw new IllegalStateException("Uri cannot be null. Call init() before calling this method"); - } - - if (mMediaPlayer == null) { - throw new IllegalStateException("Call init() before calling this method"); - } - - if (mMediaPlayer.isPlaying()) { - return; - } - - mProgressUpdateHandler.postDelayed(mUpdateProgress, AUDIO_PROGRESS_UPDATE_TIME); - - // enable visibility of all UI controls. - setViewsVisibility(); - - mMediaPlayer.start(); - - setPausable(); - } - - /** - * Ensure the views are visible before playing the audio. - */ - private void setViewsVisibility() { - - if (mSeekBar != null) { - mSeekBar.setVisibility(View.VISIBLE); - } - - if (mPlaybackTime != null) { - mPlaybackTime.setVisibility(View.VISIBLE); - } - - if (mRunTime != null) { - mRunTime.setVisibility(View.VISIBLE); - } - - if (mTotalTime != null) { - mTotalTime.setVisibility(View.VISIBLE); - } - - if (mPlayButton != null) { - mPlayButton.setVisibility(View.VISIBLE); - } - - if (mPauseButton != null) { - mPauseButton.setVisibility(View.VISIBLE); - } - } - - /*** - * Pause the audio being played. Calling this method has no effect if the audio is already - * paused - */ - public void pause() { - - if (mMediaPlayer == null) { - return; - } - - if (mMediaPlayer.isPlaying()) { - mMediaPlayer.pause(); - setPlayable(); - } - } - - @Deprecated - private void updatePlaytime(int currentTime) { - - if (mPlaybackTime == null) { - return; - } - - if (currentTime < 0) { - throw new IllegalArgumentException(ERROR_PLAYTIME_CURRENT_NEGATIVE); - } - - StringBuilder playbackStr = new StringBuilder(); - - // set the current time - // its ok to show 00:00 in the UI - playbackStr.append(String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes((long) currentTime), TimeUnit.MILLISECONDS.toSeconds((long) currentTime) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) currentTime)))); - - playbackStr.append("/"); - - // show total duration. - long totalDuration = 0; - - if (mMediaPlayer != null) { - try { - totalDuration = mMediaPlayer.getDuration(); - } catch (IllegalStateException e) { - //e.printStackTrace(); - } catch (Exception e) { - //e.printStackTrace(); - } - } - - // set total time as the audio is being played - if (totalDuration != 0) { - playbackStr.append(String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes((long) totalDuration), TimeUnit.MILLISECONDS.toSeconds((long) totalDuration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) totalDuration)))); - } else { - Log.w(TAG, "Something strage this audio track duration in zero"); - } - - mPlaybackTime.setText(playbackStr); - - // DebugLog.i(currentTime + " / " + totalDuration); - } - - private void updateRuntime(int currentTime) { - - if (mRunTime == null) { - // this view can be null if the user - // does not want to use it. Don't throw - // an exception. - return; - } - - if (currentTime < 0) { - throw new IllegalArgumentException(ERROR_PLAYTIME_CURRENT_NEGATIVE); - } - - StringBuilder playbackStr = new StringBuilder(); - - // set the current time - // its ok to show 00:00 in the UI - playbackStr.append(String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes((long) currentTime), TimeUnit.MILLISECONDS.toSeconds((long) currentTime) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) currentTime)))); - - mRunTime.setText(playbackStr); - - // DebugLog.i(currentTime + " / " + totalDuration); - } - - private void setTotalTime() { - - if (mTotalTime == null) { - // this view can be null if the user - // does not want to use it. Don't throw - // an exception. - return; - } - - StringBuilder playbackStr = new StringBuilder(); - long totalDuration = 0; - - // by this point the media player is brought to ready state - // by the call to init(). - if (mMediaPlayer != null) { - try { - totalDuration = mMediaPlayer.getDuration(); - } catch (IllegalStateException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (totalDuration < 0) { - throw new IllegalArgumentException(ERROR_PLAYTIME_TOTAL_NEGATIVE); - } - - // set total time as the audio is being played - if (totalDuration != 0) { - playbackStr.append(String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes((long) totalDuration), TimeUnit.MILLISECONDS.toSeconds((long) totalDuration) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long) totalDuration)))); - } - - mTotalTime.setText(playbackStr); - } - - /*** - * Changes audiowife state to enable play functionality. - */ - private void setPlayable() { - if (mPlayButton != null) { - mPlayButton.setVisibility(View.VISIBLE); - } - - if (mPauseButton != null) { - mPauseButton.setVisibility(View.GONE); - } - } - - /**** - * Changes audio wife to enable pause functionality. - */ - private void setPausable() { - if (mPlayButton != null) { - mPlayButton.setVisibility(View.GONE); - } - - if (mPauseButton != null) { - mPauseButton.setVisibility(View.VISIBLE); - } - } - - /*** - * Initialize the audio player. This method should be the first one to be called before starting - * to play audio using {@link nl.changer.audiowife.AudioWife} - * - * @param ctx {@link android.app.Activity} Context - * @param uri Uri of the audio to be played. - ****/ - public AudioWife init(Context ctx, Uri uri) { - - if (uri == null) { - throw new IllegalArgumentException("Uri cannot be null"); - } - - if (mAudioWife == null) { - mAudioWife = new AudioWife(); - } - - mUri = uri; - - mProgressUpdateHandler = new Handler(); - - initPlayer(ctx); - - return this; - } - - /*** - * Sets the audio play functionality on click event of this view. You can set {@link android.widget.Button} or - * an {@link android.widget.ImageView} as audio play control - * - * @see nl.changer.audiowife.AudioWife#addOnPauseClickListener(android.view.View.OnClickListener) - ****/ - public AudioWife setPlayView(View play) { - - if (play == null) { - throw new NullPointerException("PlayView cannot be null"); - } - - if (mHasDefaultUi) { - Log.w(TAG, "Already using default UI. Setting play view will have no effect"); - return this; - } - - mPlayButton = play; - - initOnPlayClick(); - return this; - } - - private void initOnPlayClick() { - if (mPlayButton == null) { - throw new NullPointerException(ERROR_PLAYVIEW_NULL); - } - - // add default click listener to the top - // so that it is the one that gets fired first - mPlayListeners.add(0, new View.OnClickListener() { - - @Override - public void onClick(View v) { - play(); - } - }); - - // Fire all the attached listeners - // when the play button is clicked - mPlayButton.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View v) { - for (View.OnClickListener listener : mPlayListeners) { - listener.onClick(v); - } - } - }); - } - - /*** - * Sets the audio pause functionality on click event of the view passed in as a parameter. You - * can set {@link android.widget.Button} or an {@link android.widget.ImageView} as audio pause control. Audio pause - * functionality will be unavailable if this method is not called. - * - * @see nl.changer.audiowife.AudioWife#addOnPauseClickListener(android.view.View.OnClickListener) - ****/ - public AudioWife setPauseView(View pause) { - - if (pause == null) { - throw new NullPointerException("PauseView cannot be null"); - } - - if (mHasDefaultUi) { - Log.w(TAG, "Already using default UI. Setting pause view will have no effect"); - return this; - } - - mPauseButton = pause; - - initOnPauseClick(); - return this; - } - - private void initOnPauseClick() { - if (mPauseButton == null) { - throw new NullPointerException("Pause view cannot be null"); - } - - // add default click listener to the top - // so that it is the one that gets fired first - mPauseListeners.add(0, new View.OnClickListener() { - - @Override - public void onClick(View v) { - pause(); - } - }); - - // Fire all the attached listeners - // when the pause button is clicked - mPauseButton.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View v) { - for (View.OnClickListener listener : mPauseListeners) { - listener.onClick(v); - } - } - }); - } - - /*** - * @deprecated Use {@link nl.changer.audiowife.AudioWife#setRuntimeView(android.widget.TextView)} and - * {@link nl.changer.audiowife.AudioWife#setTotalTimeView(android.widget.TextView)} instead. <br/> - * Sets current and total playback time. Use this if you have a playback time - * counter in the UI. - ****/ - public AudioWife setPlaytime(TextView playTime) { - - if (mHasDefaultUi) { - Log.w(TAG, "Already using default UI. Setting play time will have no effect"); - return this; - } - - mPlaybackTime = playTime; - - // initialize the playtime to 0 - updatePlaytime(0); - return this; - } - - /*** - * Sets current playback time view. Use this if you have a playback time counter in the UI. - * - * @see nl.changer.audiowife.AudioWife#setTotalTimeView(android.widget.TextView) - ****/ - public AudioWife setRuntimeView(TextView currentTime) { - - if (mHasDefaultUi) { - Log.w(TAG, "Already using default UI. Setting play time will have no effect"); - return this; - } - - mRunTime = currentTime; - - // initialize the playtime to 0 - updateRuntime(0); - return this; - } - - /*** - * Sets the total playback time view. Use this if you have a playback time counter in the UI. - * - * @see nl.changer.audiowife.AudioWife#setRuntimeView(android.widget.TextView) - ****/ - public AudioWife setTotalTimeView(TextView totalTime) { - - if (mHasDefaultUi) { - Log.w(TAG, "Already using default UI. Setting play time will have no effect"); - return this; - } - - mTotalTime = totalTime; - - setTotalTime(); - return this; - } - - public AudioWife setSeekBar(SeekBar seekbar) { - - if (mHasDefaultUi) { - Log.w(TAG, "Already using default UI. Setting seek bar will have no effect"); - return this; - } - - mSeekBar = seekbar; - initMediaSeekBar(); - return this; - } - - /**** - * Add custom playback completion listener. Adding multiple listeners will queue up all the - * listeners and fire them on media playback completes. - */ - public AudioWife addOnCompletionListener(OnCompletionListener listener) { - - // add default click listener to the top - // so that it is the one that gets fired first - mCompletionListeners.add(0, listener); - - return this; - } - - /**** - * Add custom play view click listener. Calling this method multiple times will queue up all the - * listeners and fire them all together when the event occurs. - ***/ - public AudioWife addOnPlayClickListener(View.OnClickListener listener) { - - mPlayListeners.add(listener); - - return this; - } - - /*** - * Add custom pause view click listener. Calling this method multiple times will queue up all - * the listeners and fire them all together when the event occurs. - ***/ - public AudioWife addOnPauseClickListener(View.OnClickListener listener) { - - mPauseListeners.add(listener); - - return this; - } - - /**** - * Initialize and prepare the audio player - ****/ - private void initPlayer(Context ctx) { - - mMediaPlayer = new MediaPlayer(); - mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); - - try { - mMediaPlayer.setDataSource(ctx, mUri); - } catch (Exception ignored) { - } - - try { - mMediaPlayer.prepare(); - } catch (Exception ignored) { - } - - mMediaPlayer.setOnCompletionListener(mOnCompletion); - } - - private void initMediaSeekBar() { - - if (mSeekBar == null) { - return; - } - - // update seekbar - long finalTime = mMediaPlayer.getDuration(); - mSeekBar.setMax((int) finalTime); - - mSeekBar.setProgress(0); - - mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - mMediaPlayer.seekTo(seekBar.getProgress()); - - // if the audio is paused and seekbar is moved, - // update the play time in the UI. - updateRuntime(seekBar.getProgress()); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - } - }); - } - - private void fireCustomCompletionListeners(MediaPlayer mp) { - for (OnCompletionListener listener : mCompletionListeners) { - listener.onCompletion(mp); - } - } - - public void cleanPlayerUi() { - ((ViewGroup) playerUi.getParent()).removeView(playerUi); - } - - public View getPlayerUi() { - return playerUi; - } - - public AudioWife useDefaultUi(ViewGroup playerContainer, LayoutInflater inflater) { - if (playerContainer == null) { - throw new NullPointerException("Player container cannot be null"); - } - - if (inflater == null) { - throw new IllegalArgumentException("Inflater cannot be null"); - } - - playerUi = inflater.inflate(R.layout.aw_player, playerContainer, false); // IMPORTANT, sonst geht meine Lösung nicht xD - - // init play view - View playView = playerUi.findViewById(R.id.play); - setPlayView(playView); - - // init pause view - View pauseView = playerUi.findViewById(R.id.pause); - setPauseView(pauseView); - - // init seekbar - SeekBar seekBar = (SeekBar) playerUi.findViewById(R.id.media_seekbar); - setSeekBar(seekBar); - - // init playback time view - TextView playbackTime = (TextView) playerUi.findViewById(R.id.playback_time); - setPlaytime(playbackTime); - - // this has to be set after all the views - // have finished initializing. - mHasDefaultUi = true; - return this; - } - - public void release() { - - if (mMediaPlayer != null) { - mMediaPlayer.stop(); - mMediaPlayer.reset(); - mMediaPlayer.release(); - mMediaPlayer = null; - mProgressUpdateHandler = null; - } - } -} diff --git a/libs/audiowife/src/main/res/drawable-mdpi/ic_launcher.png b/libs/audiowife/src/main/res/drawable-mdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 6fe8b2b68..000000000 --- a/libs/audiowife/src/main/res/drawable-mdpi/ic_launcher.png +++ /dev/null diff --git a/libs/audiowife/src/main/res/drawable-xhdpi/ic_launcher.png b/libs/audiowife/src/main/res/drawable-xhdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 75e7d9cc5..000000000 --- a/libs/audiowife/src/main/res/drawable-xhdpi/ic_launcher.png +++ /dev/null diff --git a/libs/audiowife/src/main/res/drawable-xxhdpi/ic_launcher.png b/libs/audiowife/src/main/res/drawable-xxhdpi/ic_launcher.png Binary files differdeleted file mode 100644 index 057581d8a..000000000 --- a/libs/audiowife/src/main/res/drawable-xxhdpi/ic_launcher.png +++ /dev/null diff --git a/libs/audiowife/src/main/res/drawable/gray_border_wo_padding.xml b/libs/audiowife/src/main/res/drawable/gray_border_wo_padding.xml deleted file mode 100644 index 890aadcbf..000000000 --- a/libs/audiowife/src/main/res/drawable/gray_border_wo_padding.xml +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android"> - - - <!-- view border color and width --> - <stroke - android:width="1dp" - android:color="#F2F2F2"></stroke> - - <gradient - android:endColor="@android:color/white" - android:startColor="@android:color/white" /> - -</shape>
\ No newline at end of file diff --git a/libs/audiowife/src/main/res/layout/aw_player.xml b/libs/audiowife/src/main/res/layout/aw_player.xml deleted file mode 100644 index f3e061381..000000000 --- a/libs/audiowife/src/main/res/layout/aw_player.xml +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/player_layout" - android:layout_width="match_parent" - android:layout_height="70dp" - android:gravity="center_vertical" - android:paddingLeft="4dp"> - - <ImageView - android:id="@+id/play" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_weight="6" - android:src="@android:drawable/ic_media_play" /> - - <ImageView - android:id="@+id/pause" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_weight="6" - android:src="@android:drawable/ic_media_pause" - android:visibility="gone" /> - - <FrameLayout - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_weight="0.8" - android:paddingBottom="5dp" - android:paddingRight="10dp" - android:paddingTop="5dp"> - - <SeekBar - android:id="@+id/media_seekbar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" /> - - <TextView - android:id="@+id/playback_time" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="right|top" - android:ellipsize="end" - android:inputType="text" - android:textColor="@android:color/darker_gray" - android:textSize="11sp" /> - </FrameLayout> - -</LinearLayout>
\ No newline at end of file diff --git a/libs/audiowife/src/main/res/values/strings.xml b/libs/audiowife/src/main/res/values/strings.xml deleted file mode 100644 index 66966868f..000000000 --- a/libs/audiowife/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ -<resources> - - <string name="app_name">LibAudioWife</string> - -</resources> diff --git a/libs/audiowife/src/main/res/values/styles.xml b/libs/audiowife/src/main/res/values/styles.xml deleted file mode 100644 index 6ce89c7ba..000000000 --- a/libs/audiowife/src/main/res/values/styles.xml +++ /dev/null @@ -1,20 +0,0 @@ -<resources> - - <!-- - Base application theme, dependent on API level. This theme is replaced - by AppBaseTheme from res/values-vXX/styles.xml on newer devices. - --> - <style name="AppBaseTheme" parent="android:Theme.Light"> - <!-- - Theme customizations available in newer API levels can go in - res/values-vXX/styles.xml, while customizations related to - backward-compatibility can go here. - --> - </style> - - <!-- Application theme. --> - <style name="AppTheme" parent="AppBaseTheme"> - <!-- All customizations that are NOT specific to a particular API-level can go here. --> - </style> - -</resources> diff --git a/settings.gradle b/settings.gradle index ce3660cdb..f58a52264 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,3 @@ include ':libs:MemorizingTrustManager' -include ':libs:audiowife' include ':libs:android-transcoder' rootProject.name = 'Pix-Art Messenger' diff --git a/src/main/java/de/pixart/messenger/services/AudioPlayer.java b/src/main/java/de/pixart/messenger/services/AudioPlayer.java new file mode 100644 index 000000000..6c3b55344 --- /dev/null +++ b/src/main/java/de/pixart/messenger/services/AudioPlayer.java @@ -0,0 +1,280 @@ +package de.pixart.messenger.services; + +import android.content.res.ColorStateList; +import android.media.MediaPlayer; +import android.os.Build; +import android.os.Handler; +import android.support.v4.content.ContextCompat; +import android.view.View; +import android.widget.ImageButton; +import android.widget.RelativeLayout; +import android.widget.SeekBar; +import android.widget.TextView; + +import java.lang.ref.WeakReference; +import java.util.Locale; + +import de.pixart.messenger.R; +import de.pixart.messenger.entities.Message; +import de.pixart.messenger.ui.adapter.MessageAdapter; +import de.pixart.messenger.utils.WeakReferenceSet; + +public class AudioPlayer implements View.OnClickListener, MediaPlayer.OnCompletionListener, SeekBar.OnSeekBarChangeListener, Runnable { + + private static final int REFRESH_INTERVAL = 250; + private static final Object LOCK = new Object(); + private static MediaPlayer player = null; + private static Message currentlyPlayingMessage = null; + private final MessageAdapter messageAdapter; + private final WeakReferenceSet<RelativeLayout> audioPlayerLayouts = new WeakReferenceSet<>(); + + private final Handler handler = new Handler(); + + public AudioPlayer(MessageAdapter adapter) { + this.messageAdapter = adapter; + synchronized (AudioPlayer.LOCK) { + if (AudioPlayer.player != null) { + AudioPlayer.player.setOnCompletionListener(this); + } + } + } + + private static String formatTime(int ms) { + return String.format(Locale.ENGLISH, "%d:%02d", ms / 60000, Math.min(Math.round((ms % 60000) / 1000f), 59)); + } + + public void init(RelativeLayout audioPlayer, Message message) { + synchronized (AudioPlayer.LOCK) { + audioPlayer.setTag(message); + if (init(ViewHolder.get(audioPlayer), message)) { + this.audioPlayerLayouts.addWeakReferenceTo(audioPlayer); + this.stopRefresher(true); + } else { + this.audioPlayerLayouts.removeWeakReferenceTo(audioPlayer); + } + } + } + + private boolean init(ViewHolder viewHolder, Message message) { + viewHolder.runtime.setTextColor(this.messageAdapter.getMessageTextColor(viewHolder.darkBackground, false)); + viewHolder.progress.setOnSeekBarChangeListener(this); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + ColorStateList color = ContextCompat.getColorStateList(messageAdapter.getContext(), viewHolder.darkBackground ? R.color.white70 : R.color.bubble); + viewHolder.progress.setThumbTintList(color); + viewHolder.progress.setProgressTintList(color); + } + viewHolder.playPause.setAlpha(viewHolder.darkBackground ? 0.7f : 0.57f); + viewHolder.playPause.setOnClickListener(this); + if (message == currentlyPlayingMessage) { + if (AudioPlayer.player != null && AudioPlayer.player.isPlaying()) { + viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp); + viewHolder.progress.setEnabled(true); + } else { + viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); + viewHolder.progress.setEnabled(false); + } + return true; + } else { + viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); + viewHolder.runtime.setText(formatTime(message.getFileParams().runtime)); + viewHolder.progress.setProgress(0); + viewHolder.progress.setEnabled(false); + return false; + } + } + + @Override + public synchronized void onClick(View v) { + if (v.getId() == R.id.play_pause) { + synchronized (LOCK) { + startStop((ImageButton) v); + } + } + } + + private void startStop(ImageButton playPause) { + final RelativeLayout audioPlayer = (RelativeLayout) playPause.getParent(); + final ViewHolder viewHolder = ViewHolder.get(audioPlayer); + final Message message = (Message) audioPlayer.getTag(); + if (startStop(viewHolder, message)) { + this.audioPlayerLayouts.clear(); + this.audioPlayerLayouts.addWeakReferenceTo(audioPlayer); + stopRefresher(true); + } + } + + private boolean playPauseCurrent(ViewHolder viewHolder) { + viewHolder.playPause.setAlpha(viewHolder.darkBackground ? 0.7f : 0.57f); + if (player.isPlaying()) { + viewHolder.progress.setEnabled(false); + player.pause(); + viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); + } else { + viewHolder.progress.setEnabled(true); + player.start(); + this.stopRefresher(true); + viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp); + } + return false; + } + + private boolean play(ViewHolder viewHolder, Message message) { + AudioPlayer.player = new MediaPlayer(); + try { + AudioPlayer.currentlyPlayingMessage = message; + AudioPlayer.player.setDataSource(messageAdapter.getFileBackend().getFile(message).getAbsolutePath()); + AudioPlayer.player.setOnCompletionListener(this); + AudioPlayer.player.prepare(); + AudioPlayer.player.start(); + viewHolder.progress.setEnabled(true); + viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_pause_white_36dp : R.drawable.ic_pause_black_36dp); + return true; + } catch (Exception e) { + AudioPlayer.currentlyPlayingMessage = null; + return false; + } + } + + private boolean startStop(ViewHolder viewHolder, Message message) { + if (message == currentlyPlayingMessage && player != null) { + return playPauseCurrent(viewHolder); + } + if (AudioPlayer.player != null) { + stopCurrent(); + } + return play(viewHolder, message); + } + + private void stopCurrent() { + if (AudioPlayer.player.isPlaying()) { + AudioPlayer.player.stop(); + } + AudioPlayer.player.release(); + AudioPlayer.player = null; + resetPlayerUi(); + } + + private void resetPlayerUi() { + for (WeakReference<RelativeLayout> audioPlayer : audioPlayerLayouts) { + resetPlayerUi(audioPlayer.get()); + } + } + + private void resetPlayerUi(RelativeLayout audioPlayer) { + if (audioPlayer == null) { + return; + } + final ViewHolder viewHolder = ViewHolder.get(audioPlayer); + final Message message = (Message) audioPlayer.getTag(); + viewHolder.playPause.setImageResource(viewHolder.darkBackground ? R.drawable.ic_play_arrow_white_36dp : R.drawable.ic_play_arrow_black_36dp); + if (message != null) { + viewHolder.runtime.setText(formatTime(message.getFileParams().runtime)); + } + viewHolder.progress.setProgress(0); + viewHolder.progress.setEnabled(false); + } + + @Override + public void onCompletion(MediaPlayer mediaPlayer) { + synchronized (AudioPlayer.LOCK) { + this.stopRefresher(false); + if (AudioPlayer.player == mediaPlayer) { + AudioPlayer.currentlyPlayingMessage = null; + AudioPlayer.player = null; + } + mediaPlayer.release(); + resetPlayerUi(); + } + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + synchronized (AudioPlayer.LOCK) { + final RelativeLayout audioPlayer = (RelativeLayout) seekBar.getParent(); + final Message message = (Message) audioPlayer.getTag(); + if (fromUser && message == AudioPlayer.currentlyPlayingMessage) { + float percent = progress / 100f; + int duration = AudioPlayer.player.getDuration(); + int seekTo = Math.round(duration * percent); + AudioPlayer.player.seekTo(seekTo); + } + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + + public void stop() { + synchronized (AudioPlayer.LOCK) { + stopRefresher(false); + if (AudioPlayer.player != null) { + stopCurrent(); + } + AudioPlayer.currentlyPlayingMessage = null; + } + } + + private void stopRefresher(boolean runOnceMore) { + this.handler.removeCallbacks(this); + if (runOnceMore) { + this.handler.post(this); + } + } + + @Override + public void run() { + synchronized (AudioPlayer.LOCK) { + if (AudioPlayer.player != null) { + boolean renew = false; + final int current = player.getCurrentPosition(); + final int duration = player.getDuration(); + for (WeakReference<RelativeLayout> audioPlayer : audioPlayerLayouts) { + renew |= refreshAudioPlayer(audioPlayer.get(), current, duration); + } + if (renew && AudioPlayer.player.isPlaying()) { + handler.postDelayed(this, REFRESH_INTERVAL); + } + } + } + } + + private boolean refreshAudioPlayer(RelativeLayout audioPlayer, int current, int duration) { + if (audioPlayer == null || audioPlayer.getVisibility() != View.VISIBLE) { + return false; + } + final ViewHolder viewHolder = ViewHolder.get(audioPlayer); + viewHolder.progress.setProgress(current * 100 / duration); + viewHolder.runtime.setText(formatTime(current) + " / " + formatTime(duration)); + return true; + } + + public static class ViewHolder { + private TextView runtime; + private SeekBar progress; + private ImageButton playPause; + private boolean darkBackground = false; + + public static ViewHolder get(RelativeLayout audioPlayer) { + ViewHolder viewHolder = (ViewHolder) audioPlayer.getTag(R.id.TAG_AUDIO_PLAYER_VIEW_HOLDER); + if (viewHolder == null) { + viewHolder = new ViewHolder(); + viewHolder.runtime = (TextView) audioPlayer.findViewById(R.id.runtime); + viewHolder.progress = (SeekBar) audioPlayer.findViewById(R.id.progress); + viewHolder.playPause = (ImageButton) audioPlayer.findViewById(R.id.play_pause); + audioPlayer.setTag(R.id.TAG_AUDIO_PLAYER_VIEW_HOLDER, viewHolder); + } + return viewHolder; + } + + public void setDarkBackground(boolean darkBackground) { + this.darkBackground = darkBackground; + } + } +}
\ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 29862861c..d6e3f49da 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -889,6 +889,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa @Override public void onStop() { super.onStop(); + if (activity == null || !activity.isChangingConfigurations()) { + messageListAdapter.stopAudioPlayer(); + } if (this.conversation != null) { final String msg = mEditMessage.getText().toString(); this.conversation.setNextMessage(msg); @@ -915,6 +918,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa this.conversation.setNextMessage(msg); if (this.conversation != conversation) { updateChatState(this.conversation, msg); + messageListAdapter.stopAudioPlayer(); } this.conversation.trim(); } diff --git a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java index d923172b5..0a3cb7008 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java @@ -1,7 +1,6 @@ package de.pixart.messenger.ui.adapter; import android.content.ActivityNotFoundException; -import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -26,7 +25,6 @@ import android.text.util.Linkify; import android.util.DisplayMetrics; import android.util.Log; import android.view.ActionMode; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -49,7 +47,6 @@ import java.io.File; import java.io.IOException; import java.lang.ref.WeakReference; import java.net.URL; -import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.concurrent.RejectedExecutionException; @@ -66,6 +63,7 @@ import de.pixart.messenger.entities.Message; import de.pixart.messenger.entities.Message.FileParams; import de.pixart.messenger.entities.Transferable; import de.pixart.messenger.persistance.FileBackend; +import de.pixart.messenger.services.AudioPlayer; import de.pixart.messenger.services.MessageArchiveService; import de.pixart.messenger.services.NotificationService; import de.pixart.messenger.ui.ConversationActivity; @@ -82,7 +80,6 @@ import de.pixart.messenger.utils.UIHelper; import de.pixart.messenger.xmpp.mam.MamReference; import ezvcard.Ezvcard; import ezvcard.VCard; -import nl.changer.audiowife.AudioWife; public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextView.CopyHandler { @@ -131,12 +128,12 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie private boolean mIndicateReceived = false; private OnQuoteListener onQuoteListener; private final ListSelectionManager listSelectionManager = new ListSelectionManager(); - private AudioWife audioWife = new AudioWife(); - private HashMap<Integer, AudioWife> audioPlayer; + private final AudioPlayer audioPlayer; private boolean mUseWhiteBackground = false; public MessageAdapter(ConversationActivity activity, List<Message> messages) { super(activity, 0, messages); + this.audioPlayer = new AudioPlayer(this); this.activity = activity; metrics = getContext().getResources().getDisplayMetrics(); updatePreferences(); @@ -179,7 +176,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie return getItemViewType(getItem(position)); } - private int getMessageTextColor(boolean onDark, boolean primary) { + public int getMessageTextColor(boolean onDark, boolean primary) { if (onDark) { return ContextCompat.getColor(activity, primary ? R.color.dark : R.color.primary); } else { @@ -336,10 +333,8 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } private void displayInfoMessage(ViewHolder viewHolder, String text, boolean darkBackground) { - viewHolder.aw_player.setVisibility(View.GONE); - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } + viewHolder.download_button.setVisibility(View.GONE); + viewHolder.audioPlayer.setVisibility(View.GONE); viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.VISIBLE); viewHolder.messageBody.setText(text); @@ -349,11 +344,9 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } private void displayDecryptionFailed(ViewHolder viewHolder, boolean darkBackground) { - viewHolder.aw_player.setVisibility(View.GONE); - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } + viewHolder.download_button.setVisibility(View.GONE); viewHolder.image.setVisibility(View.GONE); + viewHolder.audioPlayer.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.VISIBLE); viewHolder.messageBody.setText(getContext().getString( R.string.decryption_failed)); @@ -363,10 +356,8 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } private void displayEmojiMessage(final ViewHolder viewHolder, final String body) { - viewHolder.aw_player.setVisibility(View.GONE); - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } + viewHolder.download_button.setVisibility(View.GONE); + viewHolder.audioPlayer.setVisibility(View.GONE); viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.VISIBLE); viewHolder.messageBody.setIncludeFontPadding(false); @@ -381,7 +372,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie contact = contact.split(":")[1]; contact = contact.split("\\?")[0]; String add_contact = activity.getString(R.string.add_to_contact_list) + " (" + contact + ")"; - viewHolder.aw_player.setVisibility(View.GONE); + viewHolder.audioPlayer.setVisibility(View.GONE); viewHolder.download_button.setVisibility(View.VISIBLE); viewHolder.download_button.setText(add_contact); viewHolder.download_button.setOnClickListener(new OnClickListener() { @@ -552,7 +543,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } private void displayDownloadableMessage(ViewHolder viewHolder, final Message message, String text) { - viewHolder.aw_player.setVisibility(View.GONE); + viewHolder.audioPlayer.setVisibility(View.GONE); viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.GONE); viewHolder.download_button.setVisibility(View.VISIBLE); @@ -567,35 +558,8 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie }); } - private void displayAudioMessage(ViewHolder viewHolder, final Message message, int position) { - if (audioPlayer == null) { - audioPlayer = new HashMap<>(); - } - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setVisibility(View.GONE); - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } - viewHolder.aw_player.setVisibility(View.VISIBLE); - Uri audioFile = Uri.fromFile(activity.xmppConnectionService.getFileBackend().getFile(message)); - - audioWife = audioPlayer.get(position); - if (audioWife == null) { - audioWife = new AudioWife(); - audioWife.init(getContext(), audioFile); - audioPlayer.put(position, audioWife); - RelativeLayout vg = new RelativeLayout(activity); - LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - audioWife.useDefaultUi(vg, layoutInflater); - viewHolder.aw_player.addView(audioWife.getPlayerUi()); - } else { - audioWife.cleanPlayerUi(); - viewHolder.aw_player.addView(audioWife.getPlayerUi()); - } - } - private void displayOpenableMessage(ViewHolder viewHolder, final Message message) { - viewHolder.aw_player.setVisibility(View.GONE); + viewHolder.audioPlayer.setVisibility(View.GONE); viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.GONE); viewHolder.download_button.setVisibility(View.VISIBLE); @@ -669,7 +633,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } private void displayLocationMessage(ViewHolder viewHolder, final Message message) { - viewHolder.aw_player.setVisibility(View.GONE); + viewHolder.audioPlayer.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.GONE); String url = GeoHelper.MapPreviewUri(message); viewHolder.image.setVisibility(View.VISIBLE); @@ -720,13 +684,20 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } - private void displayImageMessage(ViewHolder viewHolder, - final Message message) { - viewHolder.aw_player.setVisibility(View.GONE); - if (viewHolder.download_button != null) { - viewHolder.download_button.setVisibility(View.GONE); - } + private void displayAudioMessage(ViewHolder viewHolder, Message message, boolean darkBackground) { + viewHolder.image.setVisibility(View.GONE); viewHolder.messageBody.setVisibility(View.GONE); + viewHolder.download_button.setVisibility(View.GONE); + final RelativeLayout audioPlayer = viewHolder.audioPlayer; + audioPlayer.setVisibility(View.VISIBLE); + AudioPlayer.ViewHolder.get(audioPlayer).setDarkBackground(darkBackground); + this.audioPlayer.init(audioPlayer, message); + } + + private void displayImageMessage(ViewHolder viewHolder, final Message message) { + viewHolder.download_button.setVisibility(View.GONE); + viewHolder.messageBody.setVisibility(View.GONE); + viewHolder.audioPlayer.setVisibility(View.GONE); viewHolder.image.setVisibility(View.VISIBLE); FileParams params = message.getFileParams(); double target = metrics.density * 200; @@ -799,7 +770,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie .findViewById(R.id.message_box); viewHolder.contact_picture = (ImageView) view .findViewById(R.id.message_photo); - viewHolder.aw_player = (ViewGroup) view.findViewById(R.id.aw_player); + viewHolder.audioPlayer = (RelativeLayout) view.findViewById(R.id.audio_player); viewHolder.download_button = (Button) view .findViewById(R.id.download_button); viewHolder.resend_button = (Button) view @@ -825,7 +796,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie .findViewById(R.id.message_box); viewHolder.contact_picture = (ImageView) view .findViewById(R.id.message_photo); - viewHolder.aw_player = (ViewGroup) view.findViewById(R.id.aw_player); + viewHolder.audioPlayer = (RelativeLayout) view.findViewById(R.id.audio_player); viewHolder.download_button = (Button) view .findViewById(R.id.download_button); viewHolder.indicator = (ImageView) view @@ -860,7 +831,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } - boolean darkBackground = (type == SENT && (!isInValidSession || !mUseWhiteBackground)); + boolean darkBackground = false; // default: (type == SENT && (!isInValidSession || !mUseWhiteBackground)); if (type == DATE_SEPARATOR) { if (UIHelper.today(message.getTimeSent())) { @@ -917,7 +888,6 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie }); final Transferable transferable = message.getTransferable(); - String mimeType = message.getMimeType(); if (transferable != null && transferable.getStatus() != Transferable.STATUS_UPLOADING) { if (transferable.getStatus() == Transferable.STATUS_OFFER) { displayDownloadableMessage(viewHolder, message, activity.getString(R.string.download_x_file, UIHelper.getFileDescriptionString(activity, message))); @@ -929,14 +899,12 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } else if (message.getType() == Message.TYPE_IMAGE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { displayImageMessage(viewHolder, message); } else if (message.getType() == Message.TYPE_FILE && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) { - if (message.getFileParams().width > 0) { + if (message.getFileParams().width > 0 && message.getFileParams().height > 0) { displayImageMessage(viewHolder, message); + } else if (message.getFileParams().runtime > 0) { + displayAudioMessage(viewHolder, message, darkBackground); } else { - if (mimeType != null) { - if (message.getMimeType().startsWith("audio/")) { - displayAudioMessage(viewHolder, message, position); - } else displayOpenableMessage(viewHolder, message); - } else displayOpenableMessage(viewHolder, message); + displayOpenableMessage(viewHolder, message); } } else if (message.getEncryption() == Message.ENCRYPTION_PGP) { if (account.isPgpDecryptionServiceConnected()) { @@ -1052,6 +1020,14 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie } } + public FileBackend getFileBackend() { + return activity.xmppConnectionService.getFileBackend(); + } + + public void stopAudioPlayer() { + audioPlayer.stop(); + } + public interface OnQuoteListener { public void onQuote(String text); } @@ -1189,7 +1165,6 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie protected LinearLayout message_box; protected Button download_button; protected Button resend_button; - protected ViewGroup aw_player; protected ImageView image; protected ImageView indicator; protected ImageView indicatorReceived; @@ -1201,6 +1176,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie protected TextView encryption; public Button load_more_messages; public ImageView edit_indicator; + public RelativeLayout audioPlayer; } class BitmapWorkerTask extends AsyncTask<Message, Void, Bitmap> { diff --git a/src/main/java/de/pixart/messenger/utils/WeakReferenceSet.java b/src/main/java/de/pixart/messenger/utils/WeakReferenceSet.java new file mode 100644 index 000000000..b6ccbd560 --- /dev/null +++ b/src/main/java/de/pixart/messenger/utils/WeakReferenceSet.java @@ -0,0 +1,26 @@ +package de.pixart.messenger.utils; + +import java.lang.ref.WeakReference; +import java.util.HashSet; +import java.util.Iterator; + +public class WeakReferenceSet<T> extends HashSet<WeakReference<T>> { + + public void removeWeakReferenceTo(T reference) { + for (Iterator<WeakReference<T>> iterator = iterator(); iterator.hasNext(); ) { + if (reference == iterator.next().get()) { + iterator.remove(); + } + } + } + + + public void addWeakReferenceTo(T reference) { + for (WeakReference<T> weakReference : this) { + if (reference == weakReference.get()) { + return; + } + } + this.add(new WeakReference<>(reference)); + } +}
\ No newline at end of file diff --git a/src/main/res/drawable-hdpi/ic_pause_black_36dp.png b/src/main/res/drawable-hdpi/ic_pause_black_36dp.png Binary files differnew file mode 100644 index 000000000..ec02d44a9 --- /dev/null +++ b/src/main/res/drawable-hdpi/ic_pause_black_36dp.png diff --git a/src/main/res/drawable-hdpi/ic_pause_white_36dp.png b/src/main/res/drawable-hdpi/ic_pause_white_36dp.png Binary files differnew file mode 100644 index 000000000..9d826b7e0 --- /dev/null +++ b/src/main/res/drawable-hdpi/ic_pause_white_36dp.png diff --git a/src/main/res/drawable-hdpi/ic_play_arrow_black_36dp.png b/src/main/res/drawable-hdpi/ic_play_arrow_black_36dp.png Binary files differnew file mode 100644 index 000000000..848f67624 --- /dev/null +++ b/src/main/res/drawable-hdpi/ic_play_arrow_black_36dp.png diff --git a/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png b/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png Binary files differnew file mode 100644 index 000000000..1ce6531de --- /dev/null +++ b/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png diff --git a/src/main/res/drawable-mdpi/ic_pause_black_36dp.png b/src/main/res/drawable-mdpi/ic_pause_black_36dp.png Binary files differnew file mode 100644 index 000000000..5c0dce2df --- /dev/null +++ b/src/main/res/drawable-mdpi/ic_pause_black_36dp.png diff --git a/src/main/res/drawable-mdpi/ic_pause_white_36dp.png b/src/main/res/drawable-mdpi/ic_pause_white_36dp.png Binary files differnew file mode 100644 index 000000000..6176e3f83 --- /dev/null +++ b/src/main/res/drawable-mdpi/ic_pause_white_36dp.png diff --git a/src/main/res/drawable-mdpi/ic_play_arrow_black_36dp.png b/src/main/res/drawable-mdpi/ic_play_arrow_black_36dp.png Binary files differnew file mode 100644 index 000000000..b598dac4b --- /dev/null +++ b/src/main/res/drawable-mdpi/ic_play_arrow_black_36dp.png diff --git a/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png b/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png Binary files differnew file mode 100644 index 000000000..c791b597e --- /dev/null +++ b/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png diff --git a/src/main/res/drawable-xhdpi/ic_pause_black_36dp.png b/src/main/res/drawable-xhdpi/ic_pause_black_36dp.png Binary files differnew file mode 100644 index 000000000..875a01f8a --- /dev/null +++ b/src/main/res/drawable-xhdpi/ic_pause_black_36dp.png diff --git a/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png b/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png Binary files differnew file mode 100644 index 000000000..d8b29d7da --- /dev/null +++ b/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png diff --git a/src/main/res/drawable-xhdpi/ic_play_arrow_black_36dp.png b/src/main/res/drawable-xhdpi/ic_play_arrow_black_36dp.png Binary files differnew file mode 100644 index 000000000..744ae66d1 --- /dev/null +++ b/src/main/res/drawable-xhdpi/ic_play_arrow_black_36dp.png diff --git a/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png b/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png Binary files differnew file mode 100644 index 000000000..52eb1459f --- /dev/null +++ b/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png diff --git a/src/main/res/drawable-xxhdpi/ic_pause_black_36dp.png b/src/main/res/drawable-xxhdpi/ic_pause_black_36dp.png Binary files differnew file mode 100644 index 000000000..a9bfd1fb7 --- /dev/null +++ b/src/main/res/drawable-xxhdpi/ic_pause_black_36dp.png diff --git a/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png b/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png Binary files differnew file mode 100644 index 000000000..8b721f9f5 --- /dev/null +++ b/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png diff --git a/src/main/res/drawable-xxhdpi/ic_play_arrow_black_36dp.png b/src/main/res/drawable-xxhdpi/ic_play_arrow_black_36dp.png Binary files differnew file mode 100644 index 000000000..ded8cda96 --- /dev/null +++ b/src/main/res/drawable-xxhdpi/ic_play_arrow_black_36dp.png diff --git a/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png b/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png Binary files differnew file mode 100644 index 000000000..b08c0c260 --- /dev/null +++ b/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png diff --git a/src/main/res/layout/message_content.xml b/src/main/res/layout/message_content.xml index b073868ad..bb9370313 100644 --- a/src/main/res/layout/message_content.xml +++ b/src/main/res/layout/message_content.xml @@ -35,4 +35,40 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> android:layout_height="wrap_content" android:longClickable="true" android:visibility="gone" /> + + <RelativeLayout + android:id="@+id/audio_player" + android:layout_width="288dp" + android:layout_height="wrap_content" + android:visibility="gone" + > + + <ImageButton + android:id="@+id/play_pause" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:alpha="1.0" + android:background="?android:selectableItemBackground"/> + + <TextView + android:id="@+id/runtime" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentEnd="true" + android:layout_alignParentRight="true" + android:paddingBottom="16dp" + android:paddingRight="16dp" + android:textColor="@color/primary" + android:textSize="?attr/TextSizeInfo"/> + + <SeekBar + android:id="@+id/progress" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/runtime" + android:layout_centerVertical="true" + android:layout_toRightOf="@+id/play_pause" + android:progress="100"/> + </RelativeLayout> </merge>
\ No newline at end of file diff --git a/src/main/res/layout/message_received.xml b/src/main/res/layout/message_received.xml index 099448a74..41be316a9 100644 --- a/src/main/res/layout/message_received.xml +++ b/src/main/res/layout/message_received.xml @@ -42,12 +42,6 @@ <include layout="@layout/message_content"/> - <RelativeLayout - android:id="@+id/aw_player" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="visible" /> - <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/src/main/res/layout/message_sent.xml b/src/main/res/layout/message_sent.xml index b19765e79..835830ea9 100644 --- a/src/main/res/layout/message_sent.xml +++ b/src/main/res/layout/message_sent.xml @@ -51,12 +51,6 @@ android:longClickable="true" android:visibility="gone" /> - <RelativeLayout - android:id="@+id/aw_player" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="visible" /> - <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/src/main/res/values/ids.xml b/src/main/res/values/ids.xml index d1fd477b5..c4f584851 100644 --- a/src/main/res/values/ids.xml +++ b/src/main/res/values/ids.xml @@ -7,4 +7,5 @@ <item name="TAG_ACCOUNT" type="id" /> <item name="TAG_FINGERPRINT" type="id" /> <item name="TAG_FINGERPRINT_STATUS" type="id" /> + <item name="TAG_AUDIO_PLAYER_VIEW_HOLDER" type="id" /> </resources>
\ No newline at end of file |