aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2017-09-24 21:27:52 +0200
committerChristian Schneppe <christian@pix-art.de>2017-09-24 21:30:58 +0200
commit83f362c8b4f25d56ab2a74e37acd6b0fd0125a9c (patch)
tree01b2b07c70a307a526944133b6dfc88f3e2c0604
parent259d29518331c4517c36e2baf073615fb7bf193f (diff)
refactored AudioPlayer
-rw-r--r--build.gradle1
-rw-r--r--libs/audiowife/.gitignore5
-rw-r--r--libs/audiowife/build.gradle27
-rw-r--r--libs/audiowife/src/main/AndroidManifest.xml10
-rw-r--r--libs/audiowife/src/main/java/nl/changer/audiowife/AudioWife.java699
-rw-r--r--libs/audiowife/src/main/res/drawable-mdpi/ic_launcher.pngbin4567 -> 0 bytes
-rw-r--r--libs/audiowife/src/main/res/drawable-xhdpi/ic_launcher.pngbin12354 -> 0 bytes
-rw-r--r--libs/audiowife/src/main/res/drawable-xxhdpi/ic_launcher.pngbin18552 -> 0 bytes
-rw-r--r--libs/audiowife/src/main/res/drawable/gray_border_wo_padding.xml14
-rw-r--r--libs/audiowife/src/main/res/layout/aw_player.xml49
-rw-r--r--libs/audiowife/src/main/res/values/strings.xml5
-rw-r--r--libs/audiowife/src/main/res/values/styles.xml20
-rw-r--r--settings.gradle1
-rw-r--r--src/main/java/de/pixart/messenger/services/AudioPlayer.java280
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationFragment.java4
-rw-r--r--src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java110
-rw-r--r--src/main/java/de/pixart/messenger/utils/WeakReferenceSet.java26
-rw-r--r--src/main/res/drawable-hdpi/ic_pause_black_36dp.pngbin0 -> 126 bytes
-rw-r--r--src/main/res/drawable-hdpi/ic_pause_white_36dp.pngbin0 -> 121 bytes
-rw-r--r--src/main/res/drawable-hdpi/ic_play_arrow_black_36dp.pngbin0 -> 209 bytes
-rw-r--r--src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.pngbin0 -> 211 bytes
-rw-r--r--src/main/res/drawable-mdpi/ic_pause_black_36dp.pngbin0 -> 103 bytes
-rw-r--r--src/main/res/drawable-mdpi/ic_pause_white_36dp.pngbin0 -> 106 bytes
-rw-r--r--src/main/res/drawable-mdpi/ic_play_arrow_black_36dp.pngbin0 -> 166 bytes
-rw-r--r--src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.pngbin0 -> 169 bytes
-rw-r--r--src/main/res/drawable-xhdpi/ic_pause_black_36dp.pngbin0 -> 133 bytes
-rw-r--r--src/main/res/drawable-xhdpi/ic_pause_white_36dp.pngbin0 -> 149 bytes
-rw-r--r--src/main/res/drawable-xhdpi/ic_play_arrow_black_36dp.pngbin0 -> 251 bytes
-rw-r--r--src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.pngbin0 -> 255 bytes
-rw-r--r--src/main/res/drawable-xxhdpi/ic_pause_black_36dp.pngbin0 -> 188 bytes
-rw-r--r--src/main/res/drawable-xxhdpi/ic_pause_white_36dp.pngbin0 -> 220 bytes
-rw-r--r--src/main/res/drawable-xxhdpi/ic_play_arrow_black_36dp.pngbin0 -> 323 bytes
-rw-r--r--src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.pngbin0 -> 328 bytes
-rw-r--r--src/main/res/layout/message_content.xml36
-rw-r--r--src/main/res/layout/message_received.xml6
-rw-r--r--src/main/res/layout/message_sent.xml6
-rw-r--r--src/main/res/values/ids.xml1
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
deleted file mode 100644
index 6fe8b2b68..000000000
--- a/libs/audiowife/src/main/res/drawable-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/libs/audiowife/src/main/res/drawable-xhdpi/ic_launcher.png b/libs/audiowife/src/main/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644
index 75e7d9cc5..000000000
--- a/libs/audiowife/src/main/res/drawable-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/libs/audiowife/src/main/res/drawable-xxhdpi/ic_launcher.png b/libs/audiowife/src/main/res/drawable-xxhdpi/ic_launcher.png
deleted file mode 100644
index 057581d8a..000000000
--- a/libs/audiowife/src/main/res/drawable-xxhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
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
new file mode 100644
index 000000000..ec02d44a9
--- /dev/null
+++ b/src/main/res/drawable-hdpi/ic_pause_black_36dp.png
Binary files differ
diff --git a/src/main/res/drawable-hdpi/ic_pause_white_36dp.png b/src/main/res/drawable-hdpi/ic_pause_white_36dp.png
new file mode 100644
index 000000000..9d826b7e0
--- /dev/null
+++ b/src/main/res/drawable-hdpi/ic_pause_white_36dp.png
Binary files differ
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
new file mode 100644
index 000000000..848f67624
--- /dev/null
+++ b/src/main/res/drawable-hdpi/ic_play_arrow_black_36dp.png
Binary files differ
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
new file mode 100644
index 000000000..1ce6531de
--- /dev/null
+++ b/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png
Binary files differ
diff --git a/src/main/res/drawable-mdpi/ic_pause_black_36dp.png b/src/main/res/drawable-mdpi/ic_pause_black_36dp.png
new file mode 100644
index 000000000..5c0dce2df
--- /dev/null
+++ b/src/main/res/drawable-mdpi/ic_pause_black_36dp.png
Binary files differ
diff --git a/src/main/res/drawable-mdpi/ic_pause_white_36dp.png b/src/main/res/drawable-mdpi/ic_pause_white_36dp.png
new file mode 100644
index 000000000..6176e3f83
--- /dev/null
+++ b/src/main/res/drawable-mdpi/ic_pause_white_36dp.png
Binary files differ
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
new file mode 100644
index 000000000..b598dac4b
--- /dev/null
+++ b/src/main/res/drawable-mdpi/ic_play_arrow_black_36dp.png
Binary files differ
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
new file mode 100644
index 000000000..c791b597e
--- /dev/null
+++ b/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png
Binary files differ
diff --git a/src/main/res/drawable-xhdpi/ic_pause_black_36dp.png b/src/main/res/drawable-xhdpi/ic_pause_black_36dp.png
new file mode 100644
index 000000000..875a01f8a
--- /dev/null
+++ b/src/main/res/drawable-xhdpi/ic_pause_black_36dp.png
Binary files differ
diff --git a/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png b/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png
new file mode 100644
index 000000000..d8b29d7da
--- /dev/null
+++ b/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png
Binary files differ
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
new file mode 100644
index 000000000..744ae66d1
--- /dev/null
+++ b/src/main/res/drawable-xhdpi/ic_play_arrow_black_36dp.png
Binary files differ
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
new file mode 100644
index 000000000..52eb1459f
--- /dev/null
+++ b/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxhdpi/ic_pause_black_36dp.png b/src/main/res/drawable-xxhdpi/ic_pause_black_36dp.png
new file mode 100644
index 000000000..a9bfd1fb7
--- /dev/null
+++ b/src/main/res/drawable-xxhdpi/ic_pause_black_36dp.png
Binary files differ
diff --git a/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png b/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png
new file mode 100644
index 000000000..8b721f9f5
--- /dev/null
+++ b/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png
Binary files differ
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
new file mode 100644
index 000000000..ded8cda96
--- /dev/null
+++ b/src/main/res/drawable-xxhdpi/ic_play_arrow_black_36dp.png
Binary files differ
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
new file mode 100644
index 000000000..b08c0c260
--- /dev/null
+++ b/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png
Binary files differ
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