From a515edd718d71e569684053e4a8b48f191598d42 Mon Sep 17 00:00:00 2001 From: Negue Date: Mon, 10 Oct 2016 22:15:42 +0200 Subject: [PATCH 01/11] AudioFileLoader - Load AudioFile from Path or download from the Web (github for now) --- .../habitrpg/android/habitica/AudioFile.java | 40 +++++++++++ .../android/habitica/AudioFileLoader.java | 72 +++++++++++++++++++ .../android/habitica/modules/AppModule.java | 6 ++ .../habitica/ui/activities/MainActivity.java | 13 ++++ 4 files changed, 131 insertions(+) create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/AudioFile.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFile.java b/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFile.java new file mode 100644 index 000000000..f7466cd15 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFile.java @@ -0,0 +1,40 @@ +package com.habitrpg.android.habitica; + +import java.io.File; + +public class AudioFile{ + private String theme; + private String fileName; + private File file; + + public AudioFile(String theme, String fileName){ + + this.theme = theme; + this.fileName = fileName; + } + + public String getTheme() { + return theme; + } + + public String getFileName() { + return fileName; + } + + public String getWebUrl(){ + return "https://github.com/HabitRPG/habitica/blob/develop/website/assets/audio/"+ + getTheme()+"/"+getFileName()+".mp3"; + } + + public String getFilePath() { + return getTheme()+"_"+getFileName()+".mp3"; + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java b/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java new file mode 100644 index 000000000..aa3c259e4 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java @@ -0,0 +1,72 @@ +package com.habitrpg.android.habitica; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okio.BufferedSink; +import okio.Okio; +import rx.Observable; +import rx.exceptions.OnErrorThrowable; +import rx.schedulers.Schedulers; + +// based on http://stackoverflow.com/questions/29838565/downloading-files-using-okhttp-okio-and-rxjava +public class AudioFileLoader { + OkHttpClient client; + + public AudioFileLoader(){ + client = new OkHttpClient(); + } + + public Observable> download(List files) { + return Observable.from(files) + .flatMap(audioFile -> { + File file = new File(getExternalCacheDir() + File.separator + audioFile.getFilePath()); + if (file.exists()) { + audioFile.setFile(file); + return Observable.just(audioFile); + } + + final Observable fileObservable = Observable.create(sub -> { + if (sub.isUnsubscribed()) { + return; + } + + Request request = new Request.Builder().url(audioFile.getWebUrl()).build(); + + Response response; + try { + response = client.newCall(request).execute(); + if (!response.isSuccessful()) { throw new IOException(); } + } catch (IOException io) { + throw OnErrorThrowable.from(OnErrorThrowable.addValueAsLastCause(io, audioFile)); + } + + if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + if (!sub.isUnsubscribed()) { + try (BufferedSink sink = Okio.buffer(Okio.sink(file))) { + sink.writeAll(response.body().source()); + } catch (IOException io) { + throw OnErrorThrowable.from(OnErrorThrowable.addValueAsLastCause(io, audioFile)); + } + + audioFile.setFile(file); + sub.onNext(audioFile); + sub.onCompleted(); + } + } + }); + return fileObservable.subscribeOn(Schedulers.io()); + }, 5) + .toList() + .map(ArrayList::new); + } + + private String getExternalCacheDir() { + return HabiticaApplication.getInstance(HabiticaApplication.currentActivity).getExternalCacheDir().getPath(); + } +} \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java index ce5bda5e2..1cf800389 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java @@ -1,6 +1,7 @@ package com.habitrpg.android.habitica.modules; import com.habitrpg.android.habitica.APIHelper; +import com.habitrpg.android.habitica.AudioFileLoader; import com.habitrpg.android.habitica.HabiticaApplication; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.helpers.TagsHelper; @@ -53,4 +54,9 @@ public class AppModule { public Resources providesResources(Context context) { return context.getResources(); } + + @Provides + public AudioFileLoader providesAudioFileLoad(){ + return new AudioFileLoader(); + } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java index 33f574565..7bac49d73 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java @@ -43,6 +43,8 @@ import android.widget.TextView; import com.amplitude.api.Amplitude; import com.habitrpg.android.habitica.APIHelper; +import com.habitrpg.android.habitica.AudioFile; +import com.habitrpg.android.habitica.AudioFileLoader; import com.habitrpg.android.habitica.HabiticaApplication; import com.habitrpg.android.habitica.HostConfig; import com.habitrpg.android.habitica.NotificationPublisher; @@ -159,6 +161,7 @@ import retrofit2.adapter.rxjava.HttpException; import rx.Observable; import rx.functions.Action1; +import static com.habitrpg.android.habitica.AudioFileLoader.*; import static com.habitrpg.android.habitica.ui.helpers.UiUtils.SnackbarDisplayType; import static com.habitrpg.android.habitica.ui.helpers.UiUtils.showSnackbar; @@ -173,6 +176,8 @@ public class MainActivity extends BaseActivity implements Action1, Ha @Inject public APIHelper apiHelper; @Inject + public AudioFileLoader audioFileLoader; + @Inject public MaintenanceApiService maintenanceService; public HabitRPGUser user; @Inject @@ -246,6 +251,14 @@ public class MainActivity extends BaseActivity implements Action1, Ha getResources().updateConfiguration(configuration, getResources().getDisplayMetrics()); + ArrayList audioFiles = new ArrayList<>(); + audioFiles.add(new AudioFile("danielTheBard", "Chat")); + audioFileLoader.download(audioFiles).subscribe(audioFiles1 -> { + showSnackbar(this, floatingMenuWrapper, audioFiles.get(0).getFileName()+" loaded", SnackbarDisplayType.NORMAL); + }, throwable -> { + showSnackbar(this, floatingMenuWrapper, "Error: "+throwable.getMessage(), SnackbarDisplayType.NORMAL); + }); + if (!HabiticaApplication.checkUserAuthentication(this, hostConfig)) { return; } From 31764dcbf7e6c3365f35259805f29c1874b1ef64 Mon Sep 17 00:00:00 2001 From: Negue Date: Wed, 12 Oct 2016 21:10:29 +0200 Subject: [PATCH 02/11] set loaded audiofile readable --- .../android/habitica/AudioFileLoader.java | 9 ++++++++- .../habitica/ui/activities/MainActivity.java | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java b/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java index aa3c259e4..0bcd795e6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java @@ -25,8 +25,10 @@ public class AudioFileLoader { public Observable> download(List files) { return Observable.from(files) .flatMap(audioFile -> { - File file = new File(getExternalCacheDir() + File.separator + audioFile.getFilePath()); + File file = new File(getFullAudioFilePath(audioFile)); if (file.exists()) { + // Important, or else the MediaPlayer can't access this file + file.setReadable(true, false); audioFile.setFile(file); return Observable.just(audioFile); } @@ -54,6 +56,7 @@ public class AudioFileLoader { throw OnErrorThrowable.from(OnErrorThrowable.addValueAsLastCause(io, audioFile)); } + file.setReadable(true, false); audioFile.setFile(file); sub.onNext(audioFile); sub.onCompleted(); @@ -69,4 +72,8 @@ public class AudioFileLoader { private String getExternalCacheDir() { return HabiticaApplication.getInstance(HabiticaApplication.currentActivity).getExternalCacheDir().getPath(); } + + public String getFullAudioFilePath(AudioFile audioFile) { + return getExternalCacheDir() + File.separator + audioFile.getFilePath(); + } } \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java index 7bac49d73..67a07ee2e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java @@ -21,6 +21,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; +import android.media.MediaPlayer; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -142,6 +143,7 @@ import org.solovyev.android.checkout.ActivityCheckout; import org.solovyev.android.checkout.Checkout; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -251,10 +253,22 @@ public class MainActivity extends BaseActivity implements Action1, Ha getResources().updateConfiguration(configuration, getResources().getDisplayMetrics()); + MediaPlayer mp = new MediaPlayer(); + long start = System.currentTimeMillis(); ArrayList audioFiles = new ArrayList<>(); audioFiles.add(new AudioFile("danielTheBard", "Chat")); audioFileLoader.download(audioFiles).subscribe(audioFiles1 -> { - showSnackbar(this, floatingMenuWrapper, audioFiles.get(0).getFileName()+" loaded", SnackbarDisplayType.NORMAL); + showSnackbar(this, floatingMenuWrapper, audioFiles.get(0).getFileName()+" loaded in "+(System.currentTimeMillis()-start), SnackbarDisplayType.NORMAL); + + try { + String path = audioFileLoader.getFullAudioFilePath(audioFiles.get(0)); + mp.setDataSource(audioFiles.get(0).getFile().); + mp.prepare(); + } catch (IOException e) { + e.printStackTrace(); + } + + mp.start(); }, throwable -> { showSnackbar(this, floatingMenuWrapper, "Error: "+throwable.getMessage(), SnackbarDisplayType.NORMAL); }); From d233c30f502961eb2e699a40d085433c02d18f21 Mon Sep 17 00:00:00 2001 From: Negue Date: Fri, 14 Oct 2016 21:33:14 +0200 Subject: [PATCH 03/11] soundpool testcase - no sound - no exception --- .../habitica/ui/activities/MainActivity.java | 103 ++++++++++++++---- 1 file changed, 83 insertions(+), 20 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java index 67a07ee2e..6d60f3846 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java @@ -12,6 +12,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; import android.database.sqlite.SQLiteDoneException; import android.databinding.DataBindingUtil; @@ -21,7 +22,11 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; +import android.media.AudioAttributes; +import android.media.AudioManager; +import android.media.MediaDataSource; import android.media.MediaPlayer; +import android.media.SoundPool; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -143,6 +148,7 @@ import org.solovyev.android.checkout.ActivityCheckout; import org.solovyev.android.checkout.Checkout; import java.io.File; +import java.io.FileDescriptor; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; @@ -162,6 +168,7 @@ import butterknife.BindView; import retrofit2.adapter.rxjava.HttpException; import rx.Observable; import rx.functions.Action1; +import rx.schedulers.Schedulers; import static com.habitrpg.android.habitica.AudioFileLoader.*; import static com.habitrpg.android.habitica.ui.helpers.UiUtils.SnackbarDisplayType; @@ -253,25 +260,7 @@ public class MainActivity extends BaseActivity implements Action1, Ha getResources().updateConfiguration(configuration, getResources().getDisplayMetrics()); - MediaPlayer mp = new MediaPlayer(); - long start = System.currentTimeMillis(); - ArrayList audioFiles = new ArrayList<>(); - audioFiles.add(new AudioFile("danielTheBard", "Chat")); - audioFileLoader.download(audioFiles).subscribe(audioFiles1 -> { - showSnackbar(this, floatingMenuWrapper, audioFiles.get(0).getFileName()+" loaded in "+(System.currentTimeMillis()-start), SnackbarDisplayType.NORMAL); - try { - String path = audioFileLoader.getFullAudioFilePath(audioFiles.get(0)); - mp.setDataSource(audioFiles.get(0).getFile().); - mp.prepare(); - } catch (IOException e) { - e.printStackTrace(); - } - - mp.start(); - }, throwable -> { - showSnackbar(this, floatingMenuWrapper, "Error: "+throwable.getMessage(), SnackbarDisplayType.NORMAL); - }); if (!HabiticaApplication.checkUserAuthentication(this, hostConfig)) { return; @@ -861,12 +850,86 @@ public class MainActivity extends BaseActivity implements Action1, Ha } } } - + int poolId = -1; @Override public void onUserReceived(HabitRPGUser user) { - this.user = user; + /*this.user = user; this.lastSync = new Date(); MainActivity.this.setUserData(false); +*/ + + // AudioManager audio settings for adjusting the volume + AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE); + + SoundPool soundPool; + + // For Android SDK >= 21 + if (Build.VERSION.SDK_INT >= 21 ) { + + AudioAttributes audioAttrib = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_GAME) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .build(); + + SoundPool.Builder builder= new SoundPool.Builder(); + builder.setAudioAttributes(audioAttrib).setMaxStreams(2); + + soundPool = builder.build(); + } + // for Android SDK < 21 + else { + // SoundPool(int maxStreams, int streamType, int srcQuality) + soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0); + } + + + MediaPlayer mp = new MediaPlayer(); + long start = System.currentTimeMillis(); + ArrayList audioFiles = new ArrayList<>(); + audioFiles.add(new AudioFile("danielTheBard", "Chat")); + audioFileLoader.download(audioFiles).observeOn(Schedulers.newThread()).subscribe(audioFiles1 -> { + showSnackbar(this, floatingMenuWrapper, audioFiles.get(0).getFileName()+" loaded in "+(System.currentTimeMillis()-start), SnackbarDisplayType.NORMAL); + + try { + File file = audioFiles.get(0).getFile(); +/* + mp.setDataSource("file://"+file.getAbsolutePath()); + mp.setAudioStreamType(AudioManager.STREAM_MUSIC); + mp.prepare();*/ + + // Current volumn Index of particular stream type. + float currentVolumeIndex = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + + // Get the maximum volume index for a particular stream type. + float maxVolumeIndex = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + + // Volumn (0 --> 1) + float volume = currentVolumeIndex / maxVolumeIndex; + + + // When Sound Pool load complete. + soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() { + @Override + public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { + int streamId = soundPool.play(MainActivity.this.poolId,volume, volume, 1, 0, 1f); + } + }); + + + poolId = soundPool.load(file.getPath(),1 ); + + + + } catch (Exception e) { + e.printStackTrace(); + } + + //mp.start(); + }, throwable -> { + showSnackbar(this, floatingMenuWrapper, "Error: "+throwable.getMessage(), SnackbarDisplayType.NORMAL); + }); + + } public void setActiveFragment(BaseMainFragment fragment) { From dec6775656bf2a9e35143d82038d8943ad0afaed Mon Sep 17 00:00:00 2001 From: Negue Date: Mon, 17 Oct 2016 21:36:27 +0200 Subject: [PATCH 04/11] rename SoundFileLoader, prepare SoundManager, finally playing the sound --- Habitica/assets/migrations/Habitica/29.sql | 1 + .../android/habitica/HabitDatabase.java | 2 +- .../habitica/components/AppComponent.java | 3 + .../SoundFile.java} | 8 +- .../SoundFileLoader.java} | 21 ++-- .../habitica/helpers/SoundManager.java | 98 +++++++++++++++++++ .../android/habitica/modules/AppModule.java | 21 ++-- .../habitica/ui/activities/MainActivity.java | 92 ++--------------- .../lib/models/Preferences.java | 10 +- 9 files changed, 150 insertions(+), 106 deletions(-) create mode 100644 Habitica/assets/migrations/Habitica/29.sql rename Habitica/src/main/java/com/habitrpg/android/habitica/{AudioFile.java => helpers/SoundFile.java} (74%) rename Habitica/src/main/java/com/habitrpg/android/habitica/{AudioFileLoader.java => helpers/SoundFileLoader.java} (80%) create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java diff --git a/Habitica/assets/migrations/Habitica/29.sql b/Habitica/assets/migrations/Habitica/29.sql new file mode 100644 index 000000000..1f9c5522b --- /dev/null +++ b/Habitica/assets/migrations/Habitica/29.sql @@ -0,0 +1 @@ +ALTER TABLE Preferences ADD COLUMN 'sound' varchar(50); \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/HabitDatabase.java b/Habitica/src/main/java/com/habitrpg/android/habitica/HabitDatabase.java index 83a45a18c..0af04bf80 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/HabitDatabase.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/HabitDatabase.java @@ -7,5 +7,5 @@ public class HabitDatabase { public static final String NAME = "Habitica"; - public static final int VERSION = 27; + public static final int VERSION = 29; } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java index b848b0731..143126e33 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java @@ -1,6 +1,7 @@ package com.habitrpg.android.habitica.components; import com.habitrpg.android.habitica.HabiticaApplication; +import com.habitrpg.android.habitica.helpers.SoundManager; import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager; import com.habitrpg.android.habitica.modules.ApiModule; import com.habitrpg.android.habitica.modules.AppModule; @@ -178,4 +179,6 @@ public interface AppComponent { void inject(HabitButtonWidgetProvider habitButtonWidgetProvider); void inject(AvatarStatsWidgetProvider avatarStatsWidgetProvider); + + void inject(SoundManager soundManager); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFile.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFile.java similarity index 74% rename from Habitica/src/main/java/com/habitrpg/android/habitica/AudioFile.java rename to Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFile.java index f7466cd15..7ee91a79f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFile.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFile.java @@ -1,13 +1,13 @@ -package com.habitrpg.android.habitica; +package com.habitrpg.android.habitica.helpers; import java.io.File; -public class AudioFile{ +public class SoundFile { private String theme; private String fileName; private File file; - public AudioFile(String theme, String fileName){ + public SoundFile(String theme, String fileName){ this.theme = theme; this.fileName = fileName; @@ -22,7 +22,7 @@ public class AudioFile{ } public String getWebUrl(){ - return "https://github.com/HabitRPG/habitica/blob/develop/website/assets/audio/"+ + return "https://habitica.com/assets/audio/"+ getTheme()+"/"+getFileName()+".mp3"; } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.java similarity index 80% rename from Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java rename to Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.java index 0bcd795e6..19d98bd78 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/AudioFileLoader.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.java @@ -1,4 +1,6 @@ -package com.habitrpg.android.habitica; +package com.habitrpg.android.habitica.helpers; + +import com.habitrpg.android.habitica.HabiticaApplication; import java.io.File; import java.io.IOException; @@ -15,14 +17,14 @@ import rx.exceptions.OnErrorThrowable; import rx.schedulers.Schedulers; // based on http://stackoverflow.com/questions/29838565/downloading-files-using-okhttp-okio-and-rxjava -public class AudioFileLoader { +public class SoundFileLoader { OkHttpClient client; - public AudioFileLoader(){ + public SoundFileLoader(){ client = new OkHttpClient(); } - public Observable> download(List files) { + public Observable> download(List files) { return Observable.from(files) .flatMap(audioFile -> { File file = new File(getFullAudioFilePath(audioFile)); @@ -33,7 +35,7 @@ public class AudioFileLoader { return Observable.just(audioFile); } - final Observable fileObservable = Observable.create(sub -> { + final Observable fileObservable = Observable.create(sub -> { if (sub.isUnsubscribed()) { return; } @@ -50,8 +52,11 @@ public class AudioFileLoader { if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { if (!sub.isUnsubscribed()) { - try (BufferedSink sink = Okio.buffer(Okio.sink(file))) { + try { + BufferedSink sink = Okio.buffer(Okio.sink(file)); sink.writeAll(response.body().source()); + sink.flush(); + sink.close(); } catch (IOException io) { throw OnErrorThrowable.from(OnErrorThrowable.addValueAsLastCause(io, audioFile)); } @@ -73,7 +78,7 @@ public class AudioFileLoader { return HabiticaApplication.getInstance(HabiticaApplication.currentActivity).getExternalCacheDir().getPath(); } - public String getFullAudioFilePath(AudioFile audioFile) { - return getExternalCacheDir() + File.separator + audioFile.getFilePath(); + public String getFullAudioFilePath(SoundFile soundFile) { + return getExternalCacheDir() + File.separator + soundFile.getFilePath(); } } \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java new file mode 100644 index 000000000..84e6e77cf --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java @@ -0,0 +1,98 @@ +package com.habitrpg.android.habitica.helpers; + +import android.media.AudioManager; +import android.media.MediaPlayer; + +import com.habitrpg.android.habitica.HabiticaApplication; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import rx.Observable; +import rx.schedulers.Schedulers; + +public class SoundManager { + public static String SoundAchievementUnlocked = "Achievement_Unlocked"; + public static String SoundChat = "Chat"; + public static String SoundDaily = "Daily"; + public static String SoundDeath = "Death"; + public static String SoundItemDrop = "Item_Drop"; + public static String SoundLevelUp = "Level_Up"; + public static String SoundMinusHabit = "Minus_Habit"; + public static String SoundPlusHabit = "Plus_Habit"; + public static String SoundReward = "Reward"; + public static String SoundTodo = "ToDo"; + + @Inject + SoundFileLoader soundFileLoader; + private String soundTheme; + + private MediaPlayer mp = new MediaPlayer(); + private String currentSound = ""; + + public SoundManager(){ + HabiticaApplication.getInstance(HabiticaApplication.currentActivity).getComponent().inject(this); + } + + public void setSoundTheme(String soundTheme){ + this.soundTheme = soundTheme; + } + + public Observable> preloadAllFiles() { + if(soundTheme == "off") + { + return Observable.never(); + } + + ArrayList soundFiles = new ArrayList<>(); + + soundFiles.add(new SoundFile(soundTheme, SoundAchievementUnlocked)); + soundFiles.add(new SoundFile(soundTheme, SoundChat)); + soundFiles.add(new SoundFile(soundTheme, SoundDaily)); + soundFiles.add(new SoundFile(soundTheme, SoundDeath)); + soundFiles.add(new SoundFile(soundTheme, SoundItemDrop)); + soundFiles.add(new SoundFile(soundTheme, SoundLevelUp)); + soundFiles.add(new SoundFile(soundTheme, SoundMinusHabit)); + soundFiles.add(new SoundFile(soundTheme, SoundPlusHabit)); + soundFiles.add(new SoundFile(soundTheme, SoundReward)); + soundFiles.add(new SoundFile(soundTheme, SoundTodo)); + return soundFileLoader.download(soundFiles); + } + + public void loadAndPlayAudio(String type){ + if(soundTheme == "off") + { + return; + } + + ArrayList soundFiles = new ArrayList<>(); + + String soundFileKey = soundTheme+"_"+type; + + if(currentSound == soundFileKey){ + mp.start(); + } else { + soundFiles.add(new SoundFile(soundTheme, type)); + soundFileLoader.download(soundFiles).observeOn(Schedulers.newThread()).subscribe(audioFiles1 -> { + File file = soundFiles.get(0).getFile(); + String path = file.getPath(); + + try { + mp.setDataSource(path); + mp.setAudioStreamType(AudioManager.STREAM_MUSIC); + mp.prepare(); + currentSound = soundFileKey; + } + catch(Exception e){ + e.printStackTrace(); + } + + mp.start(); + }); + } + } + +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java index 1cf800389..c651eaa1d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java @@ -1,16 +1,16 @@ package com.habitrpg.android.habitica.modules; -import com.habitrpg.android.habitica.APIHelper; -import com.habitrpg.android.habitica.AudioFileLoader; -import com.habitrpg.android.habitica.HabiticaApplication; -import com.habitrpg.android.habitica.R; -import com.habitrpg.android.habitica.helpers.TagsHelper; - import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; import android.support.v7.preference.PreferenceManager; +import com.habitrpg.android.habitica.HabiticaApplication; +import com.habitrpg.android.habitica.R; +import com.habitrpg.android.habitica.helpers.SoundFileLoader; +import com.habitrpg.android.habitica.helpers.SoundManager; +import com.habitrpg.android.habitica.helpers.TagsHelper; + import javax.inject.Named; import javax.inject.Singleton; @@ -56,7 +56,12 @@ public class AppModule { } @Provides - public AudioFileLoader providesAudioFileLoad(){ - return new AudioFileLoader(); + public SoundFileLoader providesSoundFileLoader(){ + return new SoundFileLoader(); + } + + @Provides + public SoundManager providesSoundManager() { + return new SoundManager(); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java index 6d60f3846..05f475f0d 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java @@ -4,15 +4,12 @@ import android.app.AlarmManager; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.content.ComponentName; - import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; - -import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; import android.database.sqlite.SQLiteDoneException; import android.databinding.DataBindingUtil; @@ -24,7 +21,6 @@ import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.media.AudioAttributes; import android.media.AudioManager; -import android.media.MediaDataSource; import android.media.MediaPlayer; import android.media.SoundPool; import android.net.Uri; @@ -47,14 +43,13 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; -import com.amplitude.api.Amplitude; import com.habitrpg.android.habitica.APIHelper; -import com.habitrpg.android.habitica.AudioFile; -import com.habitrpg.android.habitica.AudioFileLoader; +import com.habitrpg.android.habitica.helpers.SoundFile; import com.habitrpg.android.habitica.HabiticaApplication; import com.habitrpg.android.habitica.HostConfig; import com.habitrpg.android.habitica.NotificationPublisher; import com.habitrpg.android.habitica.R; +import com.habitrpg.android.habitica.helpers.SoundFileLoader; import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback; import com.habitrpg.android.habitica.callbacks.ItemsCallback; import com.habitrpg.android.habitica.callbacks.MergeUserCallback; @@ -85,6 +80,7 @@ import com.habitrpg.android.habitica.events.commands.UnlockPathCommand; import com.habitrpg.android.habitica.events.commands.UpdateUserCommand; import com.habitrpg.android.habitica.helpers.AmplitudeManager; import com.habitrpg.android.habitica.helpers.LanguageHelper; +import com.habitrpg.android.habitica.helpers.SoundManager; import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager; import com.habitrpg.android.habitica.ui.AvatarView; import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel; @@ -142,14 +138,10 @@ import com.raizlabs.android.dbflow.structure.BaseModel; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; -import org.json.JSONException; -import org.json.JSONObject; import org.solovyev.android.checkout.ActivityCheckout; import org.solovyev.android.checkout.Checkout; import java.io.File; -import java.io.FileDescriptor; -import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -158,7 +150,6 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Objects; import java.util.TimeZone; import java.util.concurrent.TimeUnit; @@ -170,7 +161,6 @@ import rx.Observable; import rx.functions.Action1; import rx.schedulers.Schedulers; -import static com.habitrpg.android.habitica.AudioFileLoader.*; import static com.habitrpg.android.habitica.ui.helpers.UiUtils.SnackbarDisplayType; import static com.habitrpg.android.habitica.ui.helpers.UiUtils.showSnackbar; @@ -184,8 +174,9 @@ public class MainActivity extends BaseActivity implements Action1, Ha public ActivityCheckout checkout = null; @Inject public APIHelper apiHelper; + @Inject - public AudioFileLoader audioFileLoader; + public SoundManager soundManager; @Inject public MaintenanceApiService maintenanceService; public HabitRPGUser user; @@ -397,6 +388,8 @@ public class MainActivity extends BaseActivity implements Action1, Ha apiHelper.languageCode = preferences.getLanguage(); } + soundManager.setSoundTheme(preferences.getSound()); + Calendar calendar = new GregorianCalendar(); TimeZone timeZone = calendar.getTimeZone(); long offset = -TimeUnit.MINUTES.convert(timeZone.getOffset(calendar.getTimeInMillis()), TimeUnit.MILLISECONDS); @@ -858,76 +851,7 @@ public class MainActivity extends BaseActivity implements Action1, Ha MainActivity.this.setUserData(false); */ - // AudioManager audio settings for adjusting the volume - AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE); - - SoundPool soundPool; - - // For Android SDK >= 21 - if (Build.VERSION.SDK_INT >= 21 ) { - - AudioAttributes audioAttrib = new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_GAME) - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .build(); - - SoundPool.Builder builder= new SoundPool.Builder(); - builder.setAudioAttributes(audioAttrib).setMaxStreams(2); - - soundPool = builder.build(); - } - // for Android SDK < 21 - else { - // SoundPool(int maxStreams, int streamType, int srcQuality) - soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0); - } - - - MediaPlayer mp = new MediaPlayer(); - long start = System.currentTimeMillis(); - ArrayList audioFiles = new ArrayList<>(); - audioFiles.add(new AudioFile("danielTheBard", "Chat")); - audioFileLoader.download(audioFiles).observeOn(Schedulers.newThread()).subscribe(audioFiles1 -> { - showSnackbar(this, floatingMenuWrapper, audioFiles.get(0).getFileName()+" loaded in "+(System.currentTimeMillis()-start), SnackbarDisplayType.NORMAL); - - try { - File file = audioFiles.get(0).getFile(); -/* - mp.setDataSource("file://"+file.getAbsolutePath()); - mp.setAudioStreamType(AudioManager.STREAM_MUSIC); - mp.prepare();*/ - - // Current volumn Index of particular stream type. - float currentVolumeIndex = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); - - // Get the maximum volume index for a particular stream type. - float maxVolumeIndex = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - - // Volumn (0 --> 1) - float volume = currentVolumeIndex / maxVolumeIndex; - - - // When Sound Pool load complete. - soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() { - @Override - public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { - int streamId = soundPool.play(MainActivity.this.poolId,volume, volume, 1, 0, 1f); - } - }); - - - poolId = soundPool.load(file.getPath(),1 ); - - - - } catch (Exception e) { - e.printStackTrace(); - } - - //mp.start(); - }, throwable -> { - showSnackbar(this, floatingMenuWrapper, "Error: "+throwable.getMessage(), SnackbarDisplayType.NORMAL); - }); + soundManager.loadAndPlayAudio(SoundManager.SoundDaily); } diff --git a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/Preferences.java b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/Preferences.java index 4bd6fc991..3918dc849 100644 --- a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/Preferences.java +++ b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/Preferences.java @@ -33,7 +33,7 @@ public class Preferences extends BaseModel { @Column private boolean costume, toolbarCollapsed, advancedCollapsed, tagsCollapsed, newTaskEdit, disableClasses, stickyHeader, sleep, hideHeader; @Column - private String allocationMode, shirt, skin, size, background, chair, language; + private String allocationMode, shirt, skin, size, background, chair, language, sound; @Column private int dayStart, timezoneOffset; @@ -152,6 +152,14 @@ public class Preferences extends BaseModel { this.size = size; } + public String getSound() { + return sound; + } + + public void setSound(String sound) { + this.sound = sound; + } + public int getTimezoneOffset() { return timezoneOffset; } From 65cbf8af5e4db2c1d3b845d44f42887cdb1e9544 Mon Sep 17 00:00:00 2001 From: Negue Date: Tue, 18 Oct 2016 22:37:34 +0200 Subject: [PATCH 05/11] optimize playing sounds, without repreparing, refactor soundmanager, play sound on habit --- .../android/habitica/helpers/SoundFile.java | 37 +++++++++++++++++- .../habitica/helpers/SoundManager.java | 38 +++++++++---------- .../android/habitica/modules/AppModule.java | 1 + .../habitica/ui/activities/MainActivity.java | 7 +--- .../ui/fragments/BaseMainFragment.java | 4 ++ .../ui/fragments/tasks/TasksFragment.java | 3 ++ 6 files changed, 62 insertions(+), 28 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFile.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFile.java index 7ee91a79f..39117214b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFile.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFile.java @@ -1,16 +1,22 @@ package com.habitrpg.android.habitica.helpers; +import android.media.AudioManager; +import android.media.MediaPlayer; + import java.io.File; public class SoundFile { private String theme; private String fileName; private File file; + private MediaPlayer mp; + private Boolean playerPrepared = false; public SoundFile(String theme, String fileName){ this.theme = theme; this.fileName = fileName; + mp = new MediaPlayer(); } public String getTheme() { @@ -22,8 +28,7 @@ public class SoundFile { } public String getWebUrl(){ - return "https://habitica.com/assets/audio/"+ - getTheme()+"/"+getFileName()+".mp3"; + return "https://habitica.com/assets/audio/"+getTheme()+"/"+getFileName()+".mp3"; } public String getFilePath() { @@ -37,4 +42,32 @@ public class SoundFile { public void setFile(File file) { this.file = file; } + + public void prepareMediaPlayer(){ + if(playerPrepared) { + return; + } + + String path = file.getPath(); + + try { + mp.setDataSource(path); + mp.setAudioStreamType(AudioManager.STREAM_MUSIC); + mp.prepare(); + + playerPrepared = true; + } + catch(Exception e){ + e.printStackTrace(); + } + } + + public void play(){ + prepareMediaPlayer(); + if(mp.isPlaying()) { + mp.stop(); + } + + mp.start(); + } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java index 84e6e77cf..9bd1be960 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java @@ -2,11 +2,13 @@ package com.habitrpg.android.habitica.helpers; import android.media.AudioManager; import android.media.MediaPlayer; +import android.util.Log; import com.habitrpg.android.habitica.HabiticaApplication; import java.io.File; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import javax.inject.Inject; @@ -31,10 +33,13 @@ public class SoundManager { private String soundTheme; private MediaPlayer mp = new MediaPlayer(); - private String currentSound = ""; + + private HashMap loadedSoundFiles; public SoundManager(){ HabiticaApplication.getInstance(HabiticaApplication.currentActivity).getComponent().inject(this); + + loadedSoundFiles = new HashMap<>(); } public void setSoundTheme(String soundTheme){ @@ -62,36 +67,29 @@ public class SoundManager { return soundFileLoader.download(soundFiles); } + public void clearLoadedFiles(){ + loadedSoundFiles.clear(); + } + public void loadAndPlayAudio(String type){ if(soundTheme == "off") { return; } - ArrayList soundFiles = new ArrayList<>(); - - String soundFileKey = soundTheme+"_"+type; - - if(currentSound == soundFileKey){ - mp.start(); + if(loadedSoundFiles.containsKey(type)){ + loadedSoundFiles.get(type).play(); } else { + ArrayList soundFiles = new ArrayList<>(); + soundFiles.add(new SoundFile(soundTheme, type)); soundFileLoader.download(soundFiles).observeOn(Schedulers.newThread()).subscribe(audioFiles1 -> { - File file = soundFiles.get(0).getFile(); - String path = file.getPath(); + SoundFile file = soundFiles.get(0); - try { - mp.setDataSource(path); - mp.setAudioStreamType(AudioManager.STREAM_MUSIC); - mp.prepare(); - currentSound = soundFileKey; - } - catch(Exception e){ - e.printStackTrace(); - } + loadedSoundFiles.put(type, file); + file.play(); - mp.start(); - }); + }, throwable -> throwable.printStackTrace()); } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java index c651eaa1d..8fb00425b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.java @@ -61,6 +61,7 @@ public class AppModule { } @Provides + @Singleton public SoundManager providesSoundManager() { return new SoundManager(); } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java index 05f475f0d..b4f0b2810 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java @@ -846,14 +846,9 @@ public class MainActivity extends BaseActivity implements Action1, Ha int poolId = -1; @Override public void onUserReceived(HabitRPGUser user) { - /*this.user = user; + this.user = user; this.lastSync = new Date(); MainActivity.this.setUserData(false); -*/ - - soundManager.loadAndPlayAudio(SoundManager.SoundDaily); - - } public void setActiveFragment(BaseMainFragment fragment) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseMainFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseMainFragment.java index 7b7aefac9..250d53ed7 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseMainFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseMainFragment.java @@ -1,6 +1,7 @@ package com.habitrpg.android.habitica.ui.fragments; import com.habitrpg.android.habitica.APIHelper; +import com.habitrpg.android.habitica.helpers.SoundManager; import com.habitrpg.android.habitica.ui.activities.MainActivity; import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser; import com.raizlabs.android.dbflow.sql.builder.Condition; @@ -21,6 +22,9 @@ public abstract class BaseMainFragment extends BaseFragment { @Inject public APIHelper apiHelper; + @Inject + protected SoundManager soundManager; + public MainActivity activity; public TabLayout tabLayout; public FrameLayout floatingMenuWrapper; diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java index 184cb7267..b729ab23a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java @@ -23,6 +23,7 @@ import com.habitrpg.android.habitica.events.commands.FilterTasksByTagsCommand; import com.habitrpg.android.habitica.events.commands.RefreshUserCommand; import com.habitrpg.android.habitica.events.commands.TaskCheckedCommand; import com.habitrpg.android.habitica.events.commands.UpdateTagCommand; +import com.habitrpg.android.habitica.helpers.SoundManager; import com.habitrpg.android.habitica.helpers.TagsHelper; import com.habitrpg.android.habitica.ui.activities.MainActivity; import com.habitrpg.android.habitica.ui.activities.TaskFormActivity; @@ -437,6 +438,8 @@ public class TasksFragment extends BaseMainFragment implements OnCheckedChangeLi .compose(apiHelper.configureApiCallObserver()) .subscribe(new TaskScoringCallback(activity, event.habit.getId()), throwable -> { }); + + soundManager.loadAndPlayAudio(event.Up ? SoundManager.SoundPlusHabit : SoundManager.SoundMinusHabit); } @Subscribe From 3804a7ff9a719e975f76ed3926a56cc60ec560f8 Mon Sep 17 00:00:00 2001 From: Negue Date: Wed, 19 Oct 2016 21:33:00 +0200 Subject: [PATCH 06/11] play sounds on multiple events --- .../android/habitica/ui/activities/MainActivity.java | 11 +++++++++-- .../habitica/ui/fragments/tasks/TasksFragment.java | 9 +++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java index b4f0b2810..1393239e5 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java @@ -1003,6 +1003,7 @@ public class MainActivity extends BaseActivity implements Action1, Ha } else { snackbarMessage = getApplicationContext().getString(R.string.armoireExp); } + soundManager.loadAndPlayAudio(SoundManager.SoundItemDrop); } else if (!event.Reward.getId().equals("potion")) { EventBus.getDefault().post(new TaskRemovedEvent(event.Reward.getId())); } @@ -1032,6 +1033,7 @@ public class MainActivity extends BaseActivity implements Action1, Ha }, throwable -> { }); } else { + soundManager.loadAndPlayAudio(SoundManager.SoundReward); // user created Rewards apiHelper.apiService.postTaskDirection(rewardKey, TaskDirection.down.toString()) .compose(apiHelper.configureApiCallObserver()) @@ -1206,7 +1208,10 @@ public class MainActivity extends BaseActivity implements Action1, Ha private void showSnackBarForDataReceived(final TaskDirectionData data) { if (data.get_tmp() != null) { if (data.get_tmp().getDrop() != null) { - new Handler().postDelayed(() -> showSnackbar(MainActivity.this, floatingMenuWrapper, data.get_tmp().getDrop().getDialog(), SnackbarDisplayType.DROP), 3000L); + new Handler().postDelayed(() -> { + showSnackbar(MainActivity.this, floatingMenuWrapper, data.get_tmp().getDrop().getDialog(), SnackbarDisplayType.DROP); + soundManager.loadAndPlayAudio(SoundManager.SoundItemDrop); + }, 3000L); } } } @@ -1285,12 +1290,14 @@ public class MainActivity extends BaseActivity implements Action1, Ha }) .create(); - + soundManager.loadAndPlayAudio(SoundManager.SoundDeath); this.faintDialog.show(); } } private void displayLevelUpDialog(int level) { + soundManager.loadAndPlayAudio(SoundManager.SoundLevelUp); + SuppressedModals suppressedModals = user.getPreferences().getSuppressModals(); if (suppressedModals != null) { if (suppressedModals.getLevelUp()) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java index b729ab23a..4a9840469 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java @@ -422,6 +422,15 @@ public class TasksFragment extends BaseMainFragment implements OnCheckedChangeLi .compose(apiHelper.configureApiCallObserver()) .subscribe(new TaskScoringCallback(activity, event.Task.getId()), throwable -> { }); + + switch(event.Task.type){ + case Task.TYPE_DAILY: { + soundManager.loadAndPlayAudio(SoundManager.SoundDaily); + } break; + case Task.TYPE_TODO: { + soundManager.loadAndPlayAudio(SoundManager.SoundTodo); + } break; + } } @Subscribe From 26484dcea92e51ba06a80fd4b725036abd8df2f1 Mon Sep 17 00:00:00 2001 From: Negue Date: Thu, 20 Oct 2016 22:39:09 +0200 Subject: [PATCH 07/11] add audio preferences --- Habitica/res/values/strings.xml | 3 + Habitica/res/values/values.xml | 20 +++ Habitica/res/xml/preferences_fragment.xml | 9 +- .../android/habitica/helpers/SoundFile.java | 2 + .../habitica/helpers/SoundFileLoader.java | 4 - .../preferences/PreferencesFragment.java | 165 +++++++++++------- 6 files changed, 137 insertions(+), 66 deletions(-) diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index f455eafcc..0265e5770 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -415,4 +415,7 @@ To start, which parts of your life do you want to improve? Habitica Add Task Google play services could not be found. + + Audio Theme + Change Habitica\'s Audio Theme diff --git a/Habitica/res/values/values.xml b/Habitica/res/values/values.xml index f4a5b03ef..296e9e3b4 100644 --- a/Habitica/res/values/values.xml +++ b/Habitica/res/values/values.xml @@ -86,4 +86,24 @@ zh_TW + + + Off + Daniel the Bard + Watts\' Theme + Gokul Theme + LuneFox\'s Theme + Rosstavo\'s Theme + Dewin\'s Theme + + + + off + danielTheBard + wattsTheme + gokulTheme + luneFoxTheme + rosstavoTheme + dewinTheme + diff --git a/Habitica/res/xml/preferences_fragment.xml b/Habitica/res/xml/preferences_fragment.xml index 4cb93d582..60bd351f2 100644 --- a/Habitica/res/xml/preferences_fragment.xml +++ b/Habitica/res/xml/preferences_fragment.xml @@ -67,14 +67,19 @@ android:entries="@array/weekdays" android:entryValues="@array/weekdayValues" android:summary="@string/pref_first_day_of_the_week_summary" - android:order="4"/> + android:order="5"/> + - fileObservable = Observable.create(sub -> { - if (sub.isUnsubscribed()) { - return; - } - Request request = new Request.Builder().url(audioFile.getWebUrl()).build(); Response response; diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.java index 43ee90568..5465a5784 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.java @@ -8,6 +8,7 @@ import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Build; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.v7.app.AlertDialog; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; @@ -18,6 +19,7 @@ import com.habitrpg.android.habitica.NotificationPublisher; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.callbacks.MergeUserCallback; import com.habitrpg.android.habitica.helpers.LanguageHelper; +import com.habitrpg.android.habitica.helpers.SoundManager; import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager; import com.habitrpg.android.habitica.prefs.TimePreference; import com.habitrpg.android.habitica.ui.activities.ClassSelectionActivity; @@ -41,10 +43,15 @@ public class PreferencesFragment extends BasePreferencesFragment implements @Inject public APIHelper apiHelper; + + @Inject + public SoundManager soundManager; + private Context context; private TimePreference timePreference; private PreferenceScreen pushNotificationsPreference; private Preference classSelectionPreference; + private Preference audioThemePreference; private HabitRPGUser user; public MainActivity activity; private PushNotificationManager pushNotificationManager; @@ -73,7 +80,10 @@ public class PreferencesFragment extends BasePreferencesFragment implements ((HabiticaApplication) getActivity().getApplication()).getComponent().inject(this); context = getActivity(); - String userID = getPreferenceManager().getSharedPreferences().getString(context.getString(R.string.SP_userID), null); + android.support.v7.preference.PreferenceManager preferenceManager = getPreferenceManager(); + SharedPreferences sharedPreferences = preferenceManager.getSharedPreferences(); + + String userID = sharedPreferences.getString(context.getString(R.string.SP_userID), null); if (userID != null) { new Select().from(HabitRPGUser.class).where(Condition.column("id").eq(userID)).async().querySingle(userTransactionListener); } @@ -95,6 +105,8 @@ public class PreferencesFragment extends BasePreferencesFragment implements classSelectionPreference = findPreference("choose_class"); classSelectionPreference.setVisible(false); + + audioThemePreference = findPreference("audioTheme"); } @Override @@ -186,62 +198,88 @@ public class PreferencesFragment extends BasePreferencesFragment implements @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (key.equals("use_reminder")) { - boolean use_reminder = sharedPreferences.getBoolean(key, false); - timePreference.setEnabled(use_reminder); - if (use_reminder) { - scheduleNotifications(); - } else { + switch(key) { + case "use_reminder": { + boolean use_reminder = sharedPreferences.getBoolean(key, false); + timePreference.setEnabled(use_reminder); + if (use_reminder) { + scheduleNotifications(); + } else { + removeNotifications(); + } + } + break; + case "reminder_time": { removeNotifications(); + scheduleNotifications(); } - } else if (key.equals("reminder_time")) { - removeNotifications(); - scheduleNotifications(); - } else if (key.equals("usePushNotifications")) { - boolean userPushNotifications = sharedPreferences.getBoolean(key, false); - pushNotificationsPreference.setEnabled(userPushNotifications); - if (userPushNotifications) { - pushNotificationManager.addPushDeviceUsingStoredToken(); - } else { - pushNotificationManager.removePushDeviceUsingStoredToken(); + break; + case "usePushNotifications": { + boolean userPushNotifications = sharedPreferences.getBoolean(key, false); + pushNotificationsPreference.setEnabled(userPushNotifications); + if (userPushNotifications) { + pushNotificationManager.addPushDeviceUsingStoredToken(); + } else { + pushNotificationManager.removePushDeviceUsingStoredToken(); + } } - } else if (key.equals("language")) { - LanguageHelper languageHelper = new LanguageHelper(sharedPreferences.getString(key,"en")); + break; + case "language": { + LanguageHelper languageHelper = new LanguageHelper(sharedPreferences.getString(key, "en")); - Locale.setDefault(languageHelper.getLocale()); - Configuration configuration = new Configuration(); - if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN){ - configuration.locale = languageHelper.getLocale(); - } else { - configuration.setLocale(languageHelper.getLocale()); + Locale.setDefault(languageHelper.getLocale()); + Configuration configuration = new Configuration(); + if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) { + configuration.locale = languageHelper.getLocale(); + } else { + configuration.setLocale(languageHelper.getLocale()); + } + getActivity().getResources().updateConfiguration(configuration, + getActivity().getResources().getDisplayMetrics()); + + Map updateData = new HashMap<>(); + updateData.put("preferences.language", languageHelper.getLanguageCode()); + apiHelper.apiService.updateUser(updateData) + .compose(apiHelper.configureApiCallObserver()) + .subscribe(new MergeUserCallback(activity, user), throwable -> { + }); + + Preferences preferences = user.getPreferences(); + preferences.setLanguage(languageHelper.getLanguageCode()); + apiHelper.languageCode = preferences.getLanguage(); + apiHelper.apiService.getContent(apiHelper.languageCode) + .compose(apiHelper.configureApiCallObserver()) + .subscribe(contentResult -> { + }, throwable -> { + }); + + if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + Intent intent = new Intent(getActivity(), MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + } else { + Intent intent = new Intent(getActivity(), MainActivity.class); + this.startActivity(intent); + getActivity().finishAffinity(); + } } - getActivity().getResources().updateConfiguration(configuration, - getActivity().getResources().getDisplayMetrics()); + case "audioTheme": { + String newAudioTheme = sharedPreferences.getString(key, "off"); - Map updateData = new HashMap<>(); - updateData.put("preferences.language", languageHelper.getLanguageCode()); - apiHelper.apiService.updateUser(updateData) - .compose(apiHelper.configureApiCallObserver()) - .subscribe(new MergeUserCallback(activity, user), throwable -> { - }); + Map updateData = new HashMap<>(); + updateData.put("preferences.sound", newAudioTheme); + MergeUserCallback mergeUserCallback = new MergeUserCallback(activity, user); + apiHelper.apiService.updateUser(updateData) + .compose(apiHelper.configureApiCallObserver()) + .subscribe(mergeUserCallback, throwable -> { + }); - Preferences preferences = user.getPreferences(); - preferences.setLanguage(languageHelper.getLanguageCode()); - apiHelper.languageCode = preferences.getLanguage(); - apiHelper.apiService.getContent(apiHelper.languageCode) - .compose(apiHelper.configureApiCallObserver()) - .subscribe(contentResult -> { - }, throwable -> { - }); + Preferences preferences = user.getPreferences(); + preferences.setSound(newAudioTheme); - if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1){ - Intent intent = new Intent(getActivity(), MainActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - } else { - Intent intent = new Intent(getActivity(), MainActivity.class); - this.startActivity(intent); - getActivity().finishAffinity(); + soundManager.setSoundTheme(newAudioTheme); + + soundManager.preloadAllFiles(); } } } @@ -260,19 +298,26 @@ public class PreferencesFragment extends BasePreferencesFragment implements public void setUser(HabitRPGUser user) { this.user = user; - if (user != null && user.getFlags() != null && user.getStats() != null) { - if (user.getStats().getLvl() >= 10) { - if (user.getFlags().getClassSelected()) { - if (user.getPreferences().getDisableClasses()) { - classSelectionPreference.setTitle(getString(R.string.enable_class)); + if (user != null) { + if(user.getPreferences() != null){ + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.edit().putString("audioTheme", user.getPreferences().getSound()).apply(); + } + + if (user.getFlags() != null && user.getStats() != null) { + if (user.getStats().getLvl() >= 10) { + if (user.getFlags().getClassSelected()) { + if (user.getPreferences().getDisableClasses()) { + classSelectionPreference.setTitle(getString(R.string.enable_class)); + } else { + classSelectionPreference.setTitle(getString(R.string.change_class)); + classSelectionPreference.setSummary(getString(R.string.change_class_description)); + } + classSelectionPreference.setVisible(true); } else { - classSelectionPreference.setTitle(getString(R.string.change_class)); - classSelectionPreference.setSummary(getString(R.string.change_class_description)); + classSelectionPreference.setTitle(getString(R.string.enable_class)); + classSelectionPreference.setVisible(true); } - classSelectionPreference.setVisible(true); - } else { - classSelectionPreference.setTitle(getString(R.string.enable_class)); - classSelectionPreference.setVisible(true); } } } From 6f3f5e9169d9170275e8016cfb4acd042362678f Mon Sep 17 00:00:00 2001 From: Negue Date: Sat, 22 Oct 2016 14:32:20 +0200 Subject: [PATCH 08/11] clean up --- .../android/habitica/ui/activities/MainActivity.java | 2 +- .../ui/fragments/preferences/PreferencesFragment.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java index 1393239e5..c088ad36f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java @@ -843,7 +843,7 @@ public class MainActivity extends BaseActivity implements Action1, Ha } } } - int poolId = -1; + @Override public void onUserReceived(HabitRPGUser user) { this.user = user; diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.java index 5465a5784..d1a2dfc21 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.java @@ -80,10 +80,7 @@ public class PreferencesFragment extends BasePreferencesFragment implements ((HabiticaApplication) getActivity().getApplication()).getComponent().inject(this); context = getActivity(); - android.support.v7.preference.PreferenceManager preferenceManager = getPreferenceManager(); - SharedPreferences sharedPreferences = preferenceManager.getSharedPreferences(); - - String userID = sharedPreferences.getString(context.getString(R.string.SP_userID), null); + String userID = getPreferenceManager().getSharedPreferences().getString(context.getString(R.string.SP_userID), null); if (userID != null) { new Select().from(HabitRPGUser.class).where(Condition.column("id").eq(userID)).async().querySingle(userTransactionListener); } From 13a0313e4cc04c1bb6ddc8cbbd13ae7ec61b9f64 Mon Sep 17 00:00:00 2001 From: Negue Date: Sat, 22 Oct 2016 15:03:44 +0200 Subject: [PATCH 09/11] remove "isUnsubscribed" so that preloadAllFiles can work --- .../habitica/helpers/SoundFileLoader.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.java index 94d2d43f1..45355ab4f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundFileLoader.java @@ -47,21 +47,19 @@ public class SoundFileLoader { } if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { - if (!sub.isUnsubscribed()) { - try { - BufferedSink sink = Okio.buffer(Okio.sink(file)); - sink.writeAll(response.body().source()); - sink.flush(); - sink.close(); - } catch (IOException io) { - throw OnErrorThrowable.from(OnErrorThrowable.addValueAsLastCause(io, audioFile)); - } - - file.setReadable(true, false); - audioFile.setFile(file); - sub.onNext(audioFile); - sub.onCompleted(); + try { + BufferedSink sink = Okio.buffer(Okio.sink(file)); + sink.writeAll(response.body().source()); + sink.flush(); + sink.close(); + } catch (IOException io) { + throw OnErrorThrowable.from(OnErrorThrowable.addValueAsLastCause(io, audioFile)); } + + file.setReadable(true, false); + audioFile.setFile(file); + sub.onNext(audioFile); + sub.onCompleted(); } }); return fileObservable.subscribeOn(Schedulers.io()); From fae4ac2f971631c7791855c10806077edecb1b29 Mon Sep 17 00:00:00 2001 From: Negue Date: Sat, 22 Oct 2016 15:22:35 +0200 Subject: [PATCH 10/11] fix compile --- .../com/habitrpg/android/habitica/receivers/TaskReceiver.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/receivers/TaskReceiver.java b/Habitica/src/main/java/com/habitrpg/android/habitica/receivers/TaskReceiver.java index b285c1f94..c578ddc83 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/receivers/TaskReceiver.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/receivers/TaskReceiver.java @@ -13,6 +13,7 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.NotificationCompat; +import android.util.Log; /** * Created by keithholliday on 5/29/16. From 345b7d786bbd720a1cbc0775958f12bd968b04a3 Mon Sep 17 00:00:00 2001 From: Negue Date: Mon, 31 Oct 2016 14:41:48 +0100 Subject: [PATCH 11/11] requested changes / cleanup --- .../habitica/helpers/SoundManager.java | 5 ++- .../habitica/ui/activities/MainActivity.java | 11 ++++++ .../ui/fragments/tasks/TasksFragment.java | 35 ------------------- 3 files changed, 13 insertions(+), 38 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java index 9bd1be960..1e14120ca 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/SoundManager.java @@ -47,9 +47,8 @@ public class SoundManager { } public Observable> preloadAllFiles() { - if(soundTheme == "off") - { - return Observable.never(); + if(soundTheme == "off") { + return Observable.empty(); } ArrayList soundFiles = new ArrayList<>(); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java index 8e294158f..2ce3b1571 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java @@ -1487,6 +1487,15 @@ public class MainActivity extends BaseActivity implements Action1, Ha .compose(apiHelper.configureApiCallObserver()) .subscribe(new TaskScoringCallback(this, event.Task.getId()), throwable -> { }); + + switch(event.Task.type){ + case Task.TYPE_DAILY: { + soundManager.loadAndPlayAudio(SoundManager.SoundDaily); + } break; + case Task.TYPE_TODO: { + soundManager.loadAndPlayAudio(SoundManager.SoundTodo); + } break; + } } @Subscribe @@ -1503,6 +1512,8 @@ public class MainActivity extends BaseActivity implements Action1, Ha .compose(apiHelper.configureApiCallObserver()) .subscribe(new TaskScoringCallback(this, event.habit.getId()), throwable -> { }); + + soundManager.loadAndPlayAudio(event.Up ? SoundManager.SoundPlusHabit : SoundManager.SoundMinusHabit); } @Subscribe diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java index 0d216291d..749658d6b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.java @@ -416,41 +416,6 @@ public class TasksFragment extends BaseMainFragment implements OnCheckedChangeLi } } - @Subscribe - public void onEvent(TaskCheckedCommand event) { - apiHelper.apiService.postTaskDirection(event.Task.getId(), (event.Task.getCompleted() ? TaskDirection.down : TaskDirection.up).toString()) - .compose(apiHelper.configureApiCallObserver()) - .subscribe(new TaskScoringCallback(activity, event.Task.getId()), throwable -> { - }); - - switch(event.Task.type){ - case Task.TYPE_DAILY: { - soundManager.loadAndPlayAudio(SoundManager.SoundDaily); - } break; - case Task.TYPE_TODO: { - soundManager.loadAndPlayAudio(SoundManager.SoundTodo); - } break; - } - } - - @Subscribe - public void onEvent(ChecklistCheckedCommand event) { - apiHelper.apiService.scoreChecklistItem(event.task.getId(), event.item.getId()) - .compose(apiHelper.configureApiCallObserver()) - .subscribe(new TaskUpdateCallback(), throwable -> { - }); - } - - @Subscribe - public void onEvent(HabitScoreEvent event) { - apiHelper.apiService.postTaskDirection(event.habit.getId(), (event.Up ? TaskDirection.up : TaskDirection.down).toString()) - .compose(apiHelper.configureApiCallObserver()) - .subscribe(new TaskScoringCallback(activity, event.habit.getId()), throwable -> { - }); - - soundManager.loadAndPlayAudio(event.Up ? SoundManager.SoundPlusHabit : SoundManager.SoundMinusHabit); - } - @Subscribe public void onEvent(AddNewTaskCommand event) { openNewTaskActivity(event.ClassType.toLowerCase());