From 41df142c1386131b41426b7f46ed9dc4316f5666 Mon Sep 17 00:00:00 2001 From: Balaji R Date: Fri, 16 Aug 2019 12:35:32 +0530 Subject: [PATCH 1/8] feat: music player shuffle and repeat features --- build.gradle | 4 +- .../activity/ServerFileAudioActivity.java | 106 +++++++++++++++--- .../amahi/anywhere/service/AudioService.java | 103 +++++++++++++++-- .../org/amahi/anywhere/util/Preferences.java | 18 +++ .../res/layout/activity_server_file_audio.xml | 4 +- .../res/layout/exo_player_control_view.xml | 23 ++-- 6 files changed, 216 insertions(+), 42 deletions(-) diff --git a/build.gradle b/build.gradle index 8a17b8158..235541901 100644 --- a/build.gradle +++ b/build.gradle @@ -164,8 +164,8 @@ dependencies { implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever:1.0.14' - implementation 'com.google.android.exoplayer:exoplayer-core:2.7.3' - implementation 'com.google.android.exoplayer:exoplayer-ui:2.7.3' + implementation 'com.google.android.exoplayer:exoplayer-core:2.9.0' + implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.0' implementation 'android.arch.persistence.room:runtime:' + rootProject.archRoomVersion annotationProcessor 'android.arch.persistence.room:compiler:' + rootProject.archRoomVersion diff --git a/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java b/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java index 0921638b8..3edf18340 100644 --- a/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java +++ b/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java @@ -34,6 +34,7 @@ import androidx.core.graphics.drawable.DrawableCompat; import androidx.viewpager.widget.ViewPager; import androidx.appcompat.app.AppCompatActivity; + import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -77,6 +78,7 @@ import org.amahi.anywhere.util.FileManager; import org.amahi.anywhere.util.Fragments; import org.amahi.anywhere.util.Intents; +import org.amahi.anywhere.util.Preferences; import java.util.ArrayList; import java.util.Arrays; @@ -98,6 +100,10 @@ public class ServerFileAudioActivity extends AppCompatActivity implements View.OnClickListener, SessionManagerListener { private static final Set SUPPORTED_FORMATS; + private static final int REPEAT_ALL = 0; + private static final int REPEAT_ONE = 1; + private int REPEAT_MODE = 0; + static { SUPPORTED_FORMATS = new HashSet<>(Arrays.asList( @@ -355,8 +361,11 @@ private void setUpAudioControls() { getPlayerControlView().setPlayer(audioService.getAudioPlayer()); getNextButton().setOnClickListener(this); getPreviousButton().setOnClickListener(this); + getRepeatButton().setOnClickListener(this); + getPlayerControlView().setShowShuffleButton(true); audioControlsAvailable = true; } + setUpRepeatToggleIcon(); getPlayerControlView().setShowTimeoutMs(0); } @@ -372,6 +381,21 @@ private ImageButton getPreviousButton() { return getPlayerControlView().findViewById(R.id.exo_prev); } + private ImageButton getRepeatButton() { + return getPlayerControlView().findViewById(R.id.m_exo_repeat_toggle); + } + + private void setUpRepeatToggleIcon() { + if (Preferences.getAudioRepeatMode(this) == REPEAT_ONE) { + REPEAT_MODE = REPEAT_ONE; + getRepeatButton().setImageResource(R.drawable.exo_controls_repeat_one); + } else { + REPEAT_MODE = REPEAT_ALL; + getRepeatButton().setImageResource(R.drawable.exo_controls_repeat_all); + } + + } + private boolean areAudioControlsAvailable() { return audioControlsAvailable; } @@ -389,6 +413,7 @@ private void setUpAudioPlayback() { } audioService.startAudio(getShare(), getAudioFiles(), getFile()); + audioService.enableShuffle(Preferences.getAudioShuffleMode(this)); audioService.setPlayPosition(0); } @@ -415,15 +440,27 @@ public void onAudioPrepared(AudioPreparedEvent event) { @Subscribe public void onNextAudio(AudioControlNextEvent event) { + int audioPosition; + if (REPEAT_MODE == REPEAT_ONE) { + audioPosition = getAudioPager().getCurrentItem(); + } else if (audioService.isShuffleEnabled()) { + List shuffledAudioFiles = audioService.getShuffledAudioFiles(); + audioPosition = shuffledAudioFiles.indexOf(getFile()) + 1; + if (audioPosition == shuffledAudioFiles.size()) { + audioPosition = 0; + } - int audioPosition = getAudioPager().getCurrentItem(); - audioPosition += 1; - if (audioPosition == getAudioFiles().size()) { - audioPosition = 0; + audioPosition = getAudioFiles().indexOf(shuffledAudioFiles.get(audioPosition)); + } else { + audioPosition = getAudioPager().getCurrentItem(); + audioPosition += 1; + if (audioPosition == getAudioFiles().size()) { + audioPosition = 0; + } } changeAudio = false; getAudioPager().setCurrentItem(audioPosition); - saveAudioFileState(getFiles().get(audioPosition)); + saveAudioFileState(getAudioFiles().get(audioPosition)); } private void saveAudioFileState(ServerFile file) { @@ -432,14 +469,27 @@ private void saveAudioFileState(ServerFile file) { @Subscribe public void onPreviousAudio(AudioControlPreviousEvent event) { - int audioPosition = getAudioPager().getCurrentItem(); - audioPosition -= 1; - if (audioPosition == -1) { - audioPosition = getAudioFiles().size() - 1; + int audioPosition; + if (REPEAT_MODE == REPEAT_ONE) { + audioPosition = getAudioPager().getCurrentItem(); + } else if (audioService.isShuffleEnabled()) { + List shuffledAudioFiles = audioService.getShuffledAudioFiles(); + audioPosition = shuffledAudioFiles.indexOf(getFile()) - 1; + if (audioPosition == -1) { + audioPosition = shuffledAudioFiles.size() - 1; + } + + audioPosition = getAudioFiles().indexOf(shuffledAudioFiles.get(audioPosition)); + } else { + audioPosition = getAudioPager().getCurrentItem(); + audioPosition -= 1; + if (audioPosition == -1) { + audioPosition = getAudioFiles().size() - 1; + } } changeAudio = false; getAudioPager().setCurrentItem(audioPosition); - saveAudioFileState(getFiles().get(audioPosition)); + saveAudioFileState(getAudioFiles().get(audioPosition)); } @Subscribe @@ -451,13 +501,29 @@ public void onChangeAudio(AudioControlChangeEvent event) { @Subscribe public void onAudioCompleted(AudioCompletedEvent event) { - int audioPosition = getAudioPager().getCurrentItem(); - audioPosition += 1; - if (audioPosition == getAudioFiles().size()) { - audioPosition = 0; + + int audioPosition; + if (REPEAT_MODE == REPEAT_ONE) { + audioPosition = getAudioPager().getCurrentItem(); + } else if (audioService.isShuffleEnabled()) { + List shuffledAudioFiles = audioService.getShuffledAudioFiles(); + audioPosition = shuffledAudioFiles.indexOf(getFile()) + 1; + if (audioPosition == shuffledAudioFiles.size()) { + audioPosition = 0; + } + + audioPosition = getAudioFiles().indexOf(shuffledAudioFiles.get(audioPosition)); + } else { + audioPosition = getAudioPager().getCurrentItem(); + audioPosition += 1; + if (audioPosition == getAudioFiles().size()) { + audioPosition = 0; + } + } changeAudio = false; getAudioPager().setCurrentItem(audioPosition); + saveAudioFileState(getAudioFiles().get(audioPosition)); } @Override @@ -846,5 +912,17 @@ public void onClick(View v) { if (v == getPreviousButton()) { BusProvider.getBus().post(new AudioControlPreviousEvent()); } + if (v == getRepeatButton()) { + if (isAudioServiceAvailable()) { + if (REPEAT_MODE == REPEAT_ALL) { + REPEAT_MODE = REPEAT_ONE; + getRepeatButton().setImageResource(R.drawable.exo_controls_repeat_one); + } else if (REPEAT_MODE == REPEAT_ONE) { + REPEAT_MODE = REPEAT_ALL; + getRepeatButton().setImageResource(R.drawable.exo_controls_repeat_all); + } + Preferences.setAudioRepeatMode(this, REPEAT_MODE); + } + } } } diff --git a/src/main/java/org/amahi/anywhere/service/AudioService.java b/src/main/java/org/amahi/anywhere/service/AudioService.java index e0bc20c33..d0f3b3b5e 100644 --- a/src/main/java/org/amahi/anywhere/service/AudioService.java +++ b/src/main/java/org/amahi/anywhere/service/AudioService.java @@ -31,12 +31,18 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; + import android.support.v4.media.MediaBrowserCompat; + import androidx.media.MediaBrowserServiceCompat; + import android.support.v4.media.MediaMetadataCompat; + import androidx.media.session.MediaButtonReceiver; + import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import android.text.TextUtils; @@ -51,6 +57,7 @@ import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.ExtractorMediaSource; +import com.google.android.exoplayer2.source.LoopingMediaSource; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; @@ -89,6 +96,8 @@ import org.amahi.anywhere.util.Preferences; import java.io.File; +import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; @@ -111,11 +120,15 @@ public class AudioService extends MediaBrowserServiceCompat implements private ServerShare audioShare; private List audioFiles; + private List shuffledAudioFiles = new ArrayList<>(); + private ServerFile audioFile; private boolean isPreparing = false; private AudioMetadataFormatter audioMetadataFormatter; private Bitmap audioAlbumArt; + private static final int REPEAT_ALL = 0; + private static final int REPEAT_ONE = 1; @Override public IBinder onBind(Intent intent) { @@ -166,7 +179,7 @@ private void setUpBus() { private void setUpAudioPlayer() { audioPlayer = - ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(this), new DefaultTrackSelector(), new DefaultLoadControl()); + ExoPlayerFactory.newSimpleInstance(this, new DefaultRenderersFactory(this), new DefaultTrackSelector(), new DefaultLoadControl()); audioPlayer.addListener(this); audioPlayer.setPlayWhenReady(true); audioPlayer.setVolume(1.0f); @@ -416,13 +429,30 @@ private void startNextAudio() { setUpAudioMetadata(); } + public List getShuffledAudioFiles() { + return shuffledAudioFiles; + } + private ServerFile getNextAudioFile() { - int audioPosition = audioFiles.indexOf(audioFile); - if (audioPosition == audioFiles.size() - 1) { - return audioFiles.get(0); + if (getRepeatModePreference() == REPEAT_ONE) { + return audioFile; } - return audioFiles.get(audioPosition + 1); + + if (!isShuffleEnabled()) { + int audioPosition = audioFiles.indexOf(audioFile); + if (audioPosition == audioFiles.size() - 1) { + return audioFiles.get(0); + } + return audioFiles.get(audioPosition + 1); + } else { + int audioPosition = shuffledAudioFiles.indexOf(audioFile); + if (audioPosition == shuffledAudioFiles.size() - 1) { + return shuffledAudioFiles.get(0); + } + return shuffledAudioFiles.get(audioPosition + 1); + } + } private void startPreviousAudio() { @@ -434,17 +464,52 @@ private void startPreviousAudio() { } private ServerFile getPreviousAudioFile() { - int audioPosition = audioFiles.indexOf(audioFile); - if (audioPosition == 0) { - audioPosition = audioFiles.size(); + if (getRepeatModePreference() == REPEAT_ONE) { + return audioFile; + } + + if (!isShuffleEnabled()) { + int audioPosition = audioFiles.indexOf(audioFile); + if (audioPosition == 0) { + audioPosition = audioFiles.size(); + } + return audioFiles.get(audioPosition - 1); + } else { + int audioPosition = shuffledAudioFiles.indexOf(audioFile); + if (audioPosition == 0) { + audioPosition = shuffledAudioFiles.size(); + } + return shuffledAudioFiles.get(audioPosition - 1); + } - return audioFiles.get(audioPosition - 1); } @Subscribe public void onAudioCompleted(AudioCompletedEvent event) { - startNextAudio(); + if (getRepeatModePreference() == REPEAT_ONE) { + playAudioInLoop(); + } else { + startNextAudio(); + } + } + + public int getRepeatModePreference() { + return Preferences.getAudioRepeatMode(this); + } + + public void playAudioInLoop() { + MediaSource mediaSource; + if (isFileAvailableOffline(getAudioFile())) { + mediaSource = new ExtractorMediaSource.Factory( + new DefaultDataSourceFactory(this, Identifier.getUserAgent(this))) + .createMediaSource(getOfflineFileUri(getAudioFile().getName())); + } else { + mediaSource = buildMediaSource(getAudioUri()); + } + LoopingMediaSource loopingMediaSource = new LoopingMediaSource(mediaSource); + audioPlayer.prepare(loopingMediaSource, true, true); + } public void playAudio() { @@ -459,6 +524,19 @@ public void pauseAudio() { setMediaPlaybackState(PlaybackStateCompat.STATE_PAUSED); } + public void enableShuffle(boolean isShuffleEnabled) { + audioPlayer.setShuffleModeEnabled(isShuffleEnabled); + } + + public boolean isShuffleEnabled() { + return audioPlayer.getShuffleModeEnabled(); + } + + public void shuffleAudioList() { + shuffledAudioFiles = new ArrayList<>(audioFiles); + Collections.shuffle(shuffledAudioFiles); + } + private void setMediaPlaybackState(int state) { PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder(); playbackStateBuilder.setActions(getAvailableActions()); @@ -627,6 +705,11 @@ public void onRepeatModeChanged(int repeatMode) { @Override public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { + if (shuffleModeEnabled) { + shuffleAudioList(); + } + Preferences.setAudioShuffleMode(this, shuffleModeEnabled); + } diff --git a/src/main/java/org/amahi/anywhere/util/Preferences.java b/src/main/java/org/amahi/anywhere/util/Preferences.java index b62bddbd6..df7a78e27 100644 --- a/src/main/java/org/amahi/anywhere/util/Preferences.java +++ b/src/main/java/org/amahi/anywhere/util/Preferences.java @@ -122,6 +122,22 @@ public static void setSortOption(Context context, int filesSort) { getPreference(context).edit().putInt(Defaults.SORTING_OPTION, filesSort).apply(); } + public static void setAudioShuffleMode(Context context, boolean mode) { + getPreference(context).edit().putBoolean(Defaults.AUDIO_SHUFFLE, mode).apply(); + } + + public static boolean getAudioShuffleMode(Context context) { + return getPreference(context).getBoolean(Defaults.AUDIO_SHUFFLE, false); + } + + public static void setAudioRepeatMode(Context context, int mode) { + getPreference(context).edit().putInt(Defaults.AUDIO_REPEAT, mode).apply(); + } + + public static int getAudioRepeatMode(Context context) { + return getPreference(context).getInt(Defaults.AUDIO_REPEAT, 0); + } + private static final class Locations { public static final String COOKIE = "cookie"; @@ -132,6 +148,8 @@ private Locations() { private static final class Defaults { public static final String STRING = ""; public static final String SORTING_OPTION = "sorting_option"; + public static final String AUDIO_SHUFFLE = "audio_shuffle"; + public static final String AUDIO_REPEAT = "audio_repeat"; private Defaults() { } diff --git a/src/main/res/layout/activity_server_file_audio.xml b/src/main/res/layout/activity_server_file_audio.xml index 55b2bcde5..c7894db6a 100644 --- a/src/main/res/layout/activity_server_file_audio.xml +++ b/src/main/res/layout/activity_server_file_audio.xml @@ -18,6 +18,7 @@ --> + android:layout_gravity="bottom" + app:repeat_toggle_modes="all" /> - - - - + style="@style/ExoMediaButton.Shuffle" /> - + style="@style/ExoMediaButton.Previous"/> - - + + From 3405bd803b6f01281d63b5feb2079786d1b209ee Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Tue, 7 Jul 2020 02:36:37 +0530 Subject: [PATCH 2/8] clean code --- build.gradle | 8 ++--- .../activity/ServerFileAudioActivity.java | 26 ++++++--------- .../amahi/anywhere/service/AudioService.java | 22 ++++--------- .../org/amahi/anywhere/util/Preferences.java | 32 +++++++++---------- 4 files changed, 36 insertions(+), 52 deletions(-) diff --git a/build.gradle b/build.gradle index 88e32d785..2f7960490 100644 --- a/build.gradle +++ b/build.gradle @@ -147,7 +147,6 @@ dependencies { implementation 'com.squareup.retrofit2:converter-gson:2.3.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0' - implementation 'org.videolan:libvlc:2.1.1' implementation 'pub.devrel:easypermissions:3.0.0' testImplementation 'org.robolectric:robolectric:3.1.2' @@ -163,10 +162,11 @@ dependencies { compileOnly 'com.squareup.dagger:dagger-compiler:1.2.5' annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.5' - implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever:1.0.14' - implementation 'com.google.android.exoplayer:exoplayer-core:2.9.0' - implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.0' + + def EXOPLAYER_VERSION = "2.9.0" + implementation "com.google.android.exoplayer:exoplayer-core:${EXOPLAYER_VERSION}" + implementation "com.google.android.exoplayer:exoplayer-ui:${EXOPLAYER_VERSION}" implementation 'android.arch.persistence.room:runtime:' + rootProject.archRoomVersion annotationProcessor 'android.arch.persistence.room:compiler:' + rootProject.archRoomVersion diff --git a/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java b/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java index fb7a2a63d..2deea40d7 100644 --- a/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java +++ b/src/main/java/org/amahi/anywhere/activity/ServerFileAudioActivity.java @@ -28,13 +28,6 @@ import android.os.Bundle; import android.os.IBinder; import android.os.Parcelable; - -import androidx.appcompat.widget.Toolbar; -import androidx.core.content.res.ResourcesCompat; -import androidx.core.graphics.drawable.DrawableCompat; -import androidx.viewpager.widget.ViewPager; -import androidx.appcompat.app.AppCompatActivity; - import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -84,8 +77,8 @@ import org.amahi.anywhere.util.FileManager; import org.amahi.anywhere.util.Fragments; import org.amahi.anywhere.util.Intents; -import org.amahi.anywhere.util.Preferences; import org.amahi.anywhere.util.LocaleHelper; +import org.amahi.anywhere.util.Preferences; import java.util.ArrayList; import java.util.Arrays; @@ -109,8 +102,7 @@ public class ServerFileAudioActivity extends AppCompatActivity implements private static final Set SUPPORTED_FORMATS; private static final int REPEAT_ALL = 0; private static final int REPEAT_ONE = 1; - private int REPEAT_MODE = 0; - + private static final String AUDIO_LIST_VISIBLE = "audio_list_visible"; static { SUPPORTED_FORMATS = new HashSet<>(Arrays.asList( @@ -123,6 +115,7 @@ public class ServerFileAudioActivity extends AppCompatActivity implements @Inject ServerClient serverClient; + private int REPEAT_MODE = 0; private CastContext mCastContext; private CastSession mCastSession; private AudioMetadataFormatter metadataFormatter; @@ -130,7 +123,6 @@ public class ServerFileAudioActivity extends AppCompatActivity implements private AudioService audioService; private boolean changeAudio = true; private boolean audioControlsAvailable = false; - private static final String AUDIO_LIST_VISIBLE = "audio_list_visible"; private boolean audioListVisible = false; public static boolean supports(String mime_type) { @@ -164,7 +156,7 @@ private void setUpInjections() { private void setUpHomeNavigation() { Toolbar toolbar = findViewById(R.id.toolbar_audio); setSupportActionBar(toolbar); - if(getSupportActionBar()!=null) { + if (getSupportActionBar() != null) { getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } @@ -908,11 +900,6 @@ private String getRemoteUri(ServerFile serverFile) { } } - private enum PlaybackLocation { - LOCAL, - REMOTE - } - @Override public void onClick(View v) { if (v == getNextButton()) { @@ -939,4 +926,9 @@ public void onClick(View v) { protected void attachBaseContext(Context newBase) { super.attachBaseContext(LocaleHelper.onAttach(newBase)); } + + private enum PlaybackLocation { + LOCAL, + REMOTE + } } diff --git a/src/main/java/org/amahi/anywhere/service/AudioService.java b/src/main/java/org/amahi/anywhere/service/AudioService.java index d0f3b3b5e..3ff2c474f 100644 --- a/src/main/java/org/amahi/anywhere/service/AudioService.java +++ b/src/main/java/org/amahi/anywhere/service/AudioService.java @@ -31,22 +31,17 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import android.support.v4.media.MediaBrowserCompat; - -import androidx.media.MediaBrowserServiceCompat; - import android.support.v4.media.MediaMetadataCompat; - -import androidx.media.session.MediaButtonReceiver; - import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import android.text.TextUtils; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.media.MediaBrowserServiceCompat; +import androidx.media.session.MediaButtonReceiver; + import com.google.android.exoplayer2.DefaultLoadControl; import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.ExoPlaybackException; @@ -111,24 +106,21 @@ public class AudioService extends MediaBrowserServiceCompat implements AudioManager.OnAudioFocusChangeListener, Player.EventListener { + private static final int REPEAT_ALL = 0; + private static final int REPEAT_ONE = 1; @Inject ServerClient serverClient; private MediaNotificationManager mMediaNotificationManager; private SimpleExoPlayer audioPlayer; private MediaSessionCompat mediaSession; private AudioFocus audioFocus; - private ServerShare audioShare; private List audioFiles; private List shuffledAudioFiles = new ArrayList<>(); - private ServerFile audioFile; private boolean isPreparing = false; - private AudioMetadataFormatter audioMetadataFormatter; private Bitmap audioAlbumArt; - private static final int REPEAT_ALL = 0; - private static final int REPEAT_ONE = 1; @Override public IBinder onBind(Intent intent) { diff --git a/src/main/java/org/amahi/anywhere/util/Preferences.java b/src/main/java/org/amahi/anywhere/util/Preferences.java index e7f4243f9..4356f2750 100644 --- a/src/main/java/org/amahi/anywhere/util/Preferences.java +++ b/src/main/java/org/amahi/anywhere/util/Preferences.java @@ -98,22 +98,6 @@ public static Preferences ofCookie(Context context) { return new Preferences(context, Locations.COOKIE); } - public String getAppCookies(String appHost) { - return getString(appHost); - } - - private String getString(String key) { - return preferences.getString(key, Defaults.STRING); - } - - public void setAppCookies(String appHost, String appCookies) { - setString(appHost, appCookies); - } - - private void setString(String key, String value) { - preferences.edit().putString(key, value).apply(); - } - public static int getSortOption(Context context) { return getPreference(context).getInt(Defaults.SORTING_OPTION, ServerFilesFragment.SORT_MODIFICATION_TIME); } @@ -138,6 +122,22 @@ public static int getAudioRepeatMode(Context context) { return getPreference(context).getInt(Defaults.AUDIO_REPEAT, 0); } + public String getAppCookies(String appHost) { + return getString(appHost); + } + + private String getString(String key) { + return preferences.getString(key, Defaults.STRING); + } + + public void setAppCookies(String appHost, String appCookies) { + setString(appHost, appCookies); + } + + private void setString(String key, String value) { + preferences.edit().putString(key, value).apply(); + } + private static final class Locations { public static final String COOKIE = "cookie"; From adad44dd0fabbd6af1008acf0e58099c7317a315 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Tue, 7 Jul 2020 15:59:50 +0530 Subject: [PATCH 3/8] App Introduction Improvements (#555) * Move to AppIntro2 * Optimize imports --- .../activity/IntroductionActivity.java | 22 +++--- .../org/amahi/anywhere/util/SampleSlide.java | 78 ------------------- .../res/layout-land/intro_first_layout.xml | 54 ------------- src/main/res/layout/intro_first_layout.xml | 53 ------------- src/main/res/values-fr/strings.xml | 2 +- src/main/res/values/strings.xml | 2 +- 6 files changed, 13 insertions(+), 198 deletions(-) delete mode 100644 src/main/java/org/amahi/anywhere/util/SampleSlide.java delete mode 100644 src/main/res/layout-land/intro_first_layout.xml delete mode 100644 src/main/res/layout/intro_first_layout.xml diff --git a/src/main/java/org/amahi/anywhere/activity/IntroductionActivity.java b/src/main/java/org/amahi/anywhere/activity/IntroductionActivity.java index 01c900d01..618bc2a65 100644 --- a/src/main/java/org/amahi/anywhere/activity/IntroductionActivity.java +++ b/src/main/java/org/amahi/anywhere/activity/IntroductionActivity.java @@ -27,26 +27,26 @@ import androidx.fragment.app.Fragment; import androidx.core.content.ContextCompat; -import com.github.paolorotolo.appintro.AppIntro; -import com.github.paolorotolo.appintro.AppIntroFragment; +import com.github.paolorotolo.appintro.AppIntro2; +import com.github.paolorotolo.appintro.AppIntro2Fragment; import org.amahi.anywhere.R; import org.amahi.anywhere.util.CheckTV; import org.amahi.anywhere.util.LocaleHelper; import org.amahi.anywhere.util.Preferences; -import org.amahi.anywhere.util.SampleSlide; -public class IntroductionActivity extends AppIntro { +public class IntroductionActivity extends AppIntro2 { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - addSlide(SampleSlide.newInstance(R.layout.intro_first_layout)); - addSlide(AppIntroFragment.newInstance(getString(R.string.intro_title_2), getString(R.string.intro_desc_2), R.drawable.network, ContextCompat.getColor(this, R.color.intro_2))); - addSlide(AppIntroFragment.newInstance(getString(R.string.intro_title_3), getString(R.string.intro_desc_phone_3), R.drawable.photos, Color.DKGRAY)); - addSlide(AppIntroFragment.newInstance(getString(R.string.intro_title_4), getString(R.string.intro_desc_phone_4), R.drawable.music, ContextCompat.getColor(this, R.color.intro_4))); - addSlide(AppIntroFragment.newInstance(getString(R.string.intro_title_5), getString(R.string.intro_desc_phone_5), R.drawable.movies, ContextCompat.getColor(this, R.color.intro_5))); - addSlide(AppIntroFragment.newInstance(getString(R.string.intro_title_6), getString(R.string.intro_desc_6), R.drawable.tick, ContextCompat.getColor(this, R.color.intro_6))); - setFlowAnimation(); + addSlide(AppIntro2Fragment.newInstance(getString(R.string.intro_phone_1), getString(R.string.intro_desc_phone_1), R.drawable.ic_banner_white, ContextCompat.getColor(this, R.color.intro_1))); + addSlide(AppIntro2Fragment.newInstance(getString(R.string.intro_title_2), getString(R.string.intro_desc_2), R.drawable.network, ContextCompat.getColor(this, R.color.intro_2))); + addSlide(AppIntro2Fragment.newInstance(getString(R.string.intro_title_3), getString(R.string.intro_desc_phone_3), R.drawable.photos, Color.DKGRAY)); + addSlide(AppIntro2Fragment.newInstance(getString(R.string.intro_title_4), getString(R.string.intro_desc_phone_4), R.drawable.music, ContextCompat.getColor(this, R.color.intro_4))); + addSlide(AppIntro2Fragment.newInstance(getString(R.string.intro_title_5), getString(R.string.intro_desc_phone_5), R.drawable.movies, ContextCompat.getColor(this, R.color.intro_5))); + addSlide(AppIntro2Fragment.newInstance(getString(R.string.intro_title_6), getString(R.string.intro_desc_6), R.drawable.tick, ContextCompat.getColor(this, R.color.intro_6))); + setColorTransitionsEnabled(true); + setFadeAnimation(); } @Override diff --git a/src/main/java/org/amahi/anywhere/util/SampleSlide.java b/src/main/java/org/amahi/anywhere/util/SampleSlide.java deleted file mode 100644 index 7b989279f..000000000 --- a/src/main/java/org/amahi/anywhere/util/SampleSlide.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2014 Amahi - * - * This file is part of Amahi. - * - * Amahi is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Amahi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Amahi. If not, see . - */ - -package org.amahi.anywhere.util; - -import android.os.Bundle; -import androidx.annotation.ColorInt; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.core.content.ContextCompat; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.github.paolorotolo.appintro.ISlideBackgroundColorHolder; - -import org.amahi.anywhere.R; - -public class SampleSlide extends Fragment implements ISlideBackgroundColorHolder { - - private static final String ARG_LAYOUT_RES_ID = "layoutResId"; - ViewGroup mContainer; - private int layoutResId; - - public static SampleSlide newInstance(int layoutResId) { - SampleSlide sampleSlide = new SampleSlide(); - - Bundle args = new Bundle(); - args.putInt(ARG_LAYOUT_RES_ID, layoutResId); - sampleSlide.setArguments(args); - - return sampleSlide; - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (getArguments() != null && getArguments().containsKey(ARG_LAYOUT_RES_ID)) { - layoutResId = getArguments().getInt(ARG_LAYOUT_RES_ID); - } - } - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - mContainer = container; - return inflater.inflate(layoutResId, container, false); - } - - @Override - public int getDefaultBackgroundColor() { - return ContextCompat.getColor(getContext(), R.color.intro_1); - } - - @Override - public void setBackgroundColor(@ColorInt int i) { - if (mContainer != null) - mContainer.setBackgroundColor(i); - } -} diff --git a/src/main/res/layout-land/intro_first_layout.xml b/src/main/res/layout-land/intro_first_layout.xml deleted file mode 100644 index 296b1279b..000000000 --- a/src/main/res/layout-land/intro_first_layout.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/src/main/res/layout/intro_first_layout.xml b/src/main/res/layout/intro_first_layout.xml deleted file mode 100644 index 545d7319f..000000000 --- a/src/main/res/layout/intro_first_layout.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/src/main/res/values-fr/strings.xml b/src/main/res/values-fr/strings.xml index db51cec49..44d9ee8b2 100644 --- a/src/main/res/values-fr/strings.xml +++ b/src/main/res/values-fr/strings.xml @@ -144,7 +144,7 @@ Bienvenue à Amahi pour Android TV - Bienvenue à Amahi pour Android. + Bienvenue à Amahi pour Android Une app Android qui vous permet d\'accéder à vos fichiers dans votre Amahi Home Server. Accéder à votre HDA diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 69b752e70..4137e2cad 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -151,7 +151,7 @@ Welcome to Amahi for Android TV - Welcome to Amahi for Android. + Welcome to Amahi for Android An Android app that lets you access the files in your Amahi Home Server. Access your HDA From 303f0dfe9c7c50b619ba14bbdce90b6feb5ad3b5 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Mon, 13 Jul 2020 16:45:27 +0530 Subject: [PATCH 4/8] Fix App Not Loading (#561) --- .../anywhere/activity/ServerAppActivity.java | 51 +++++++++++++++---- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/amahi/anywhere/activity/ServerAppActivity.java b/src/main/java/org/amahi/anywhere/activity/ServerAppActivity.java index 386a4731b..7f7fc1712 100644 --- a/src/main/java/org/amahi/anywhere/activity/ServerAppActivity.java +++ b/src/main/java/org/amahi/anywhere/activity/ServerAppActivity.java @@ -22,7 +22,6 @@ import android.content.Context; import android.graphics.Bitmap; import android.os.Bundle; -import androidx.appcompat.app.AppCompatActivity; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; @@ -31,6 +30,13 @@ import android.webkit.WebView; import android.webkit.WebViewClient; +import androidx.appcompat.app.AppCompatActivity; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.resource.drawable.GlideDrawable; +import com.bumptech.glide.request.animation.GlideAnimation; +import com.bumptech.glide.request.target.SimpleTarget; + import org.amahi.anywhere.AmahiApplication; import org.amahi.anywhere.R; import org.amahi.anywhere.server.client.ServerClient; @@ -54,6 +60,8 @@ public class ServerAppActivity extends AppCompatActivity { @Inject ServerClient serverClient; + Context ctx; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -67,6 +75,7 @@ protected void onCreate(Bundle savedInstanceState) { private void setUpInjections() { AmahiApplication.from(this).inject(this); + ctx = this; } private void setUpApp(Bundle state) { @@ -83,7 +92,7 @@ private void setUpAppWebCookie() { String appCookies = Preferences.ofCookie(this).getAppCookies(appHost); for (String appCookie : TextUtils.split(appCookies, ";")) { - CookieManager.getInstance().setCookie(getAppUrl(), appCookie); + CookieManager.getInstance().setCookie(getServerUrl(), appCookie); } } @@ -91,10 +100,19 @@ private ServerApp getApp() { return getIntent().getParcelableExtra(Intents.Extras.SERVER_APP); } - private String getAppUrl() { + private String getServerUrl() { return serverClient.getServerAddress(); } + private String getAppUrl() { + String host = getApp().getHost(); + if (host.matches("^(http|https)://")) { + return host; + } else { + return "http://" + host; + } + } + private void setUpAppWebAgent() { getWebView().getSettings().setUserAgentString(getAppWebAgent()); } @@ -130,6 +148,18 @@ private void setUpAppWebTitle() { getSupportActionBar().setTitle(getApp().getName()); } + private void setUpAppWebIcon() { + getSupportActionBar().setIcon(R.drawable.ic_launcher); + if (!TextUtils.isEmpty(getApp().getLogoUrl())) { + Glide.with(ctx).load(getApp().getLogoUrl()).into(new SimpleTarget() { + @Override + public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) { + getSupportActionBar().setIcon(resource); + } + }); + } + } + private void setUpAppWebContent(Bundle state) { if (state == null) { getWebView().loadUrl(getAppUrl()); @@ -192,9 +222,8 @@ protected void onPause() { @Override protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - getWebView().saveState(outState); + super.onSaveInstanceState(outState); } @Override @@ -210,7 +239,7 @@ protected void onDestroy() { private void tearDownAppWebCookie() { String appHost = getApp().getHost(); - String appCookies = CookieManager.getInstance().getCookie(getAppUrl()); + String appCookies = CookieManager.getInstance().getCookie(getServerUrl()); Preferences.ofCookie(this).setAppCookies(appHost, appCookies); @@ -227,6 +256,11 @@ private void showApp() { ViewDirector.of(this, R.id.animator).show(R.id.web_content); } + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.onAttach(newBase)); + } + private static final class AppWebAgentField { public static final String HOST = "Vhost"; @@ -255,9 +289,4 @@ public void onPageFinished(WebView appWebView, String appUrl) { activity.showApp(); } } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(LocaleHelper.onAttach(newBase)); - } } From e7888e9a04130989891f8ee3d9ef601d3d65bdfc Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Sat, 18 Jul 2020 01:27:41 +0530 Subject: [PATCH 5/8] Add release to gitignore (#562) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5ecda83bd..78acf215a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Gradle .gradle/ build/ +release/ # Android Studio .idea/ From f0bf41f4b1f95f11c5f86b9d27a3886edee7a4a5 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Mon, 20 Jul 2020 16:47:34 +0530 Subject: [PATCH 6/8] Update README with better badges (#568) * Update README with badges --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9a9e7001b..f77b1e253 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,17 @@ -# Amahi Android App [![Build Status](https://travis-ci.org/amahi/android.svg?branch=master)](https://travis-ci.org/amahi/android) +

Amahi Amahi Android App

+

+ + Get it on Google Play + +

+ +[![Build Status](https://travis-ci.org/amahi/android.svg?branch=master)](https://travis-ci.org/amahi/android) +[![Twitter](https://img.shields.io/twitter/follow/amahi.svg?style=social&label=@amahi)](https://twitter.com/amahi) +[![#amahi on Freenode](https://img.shields.io/badge/chat-on%20freenode-brightgreen)](https://webchat.freenode.net/?channels=amahi) This repository contains the source code for the Amahi Android app. -You will need JDK 1.7+ installed to work with it. Gradle, Android SDK, and project dependencies will be downloaded automatically. +You will need JDK 1.8+ installed to work with it. Gradle, Android SDK, and project dependencies will be downloaded automatically. ## Building the app @@ -20,7 +29,7 @@ You will need JDK 1.7+ installed to work with it. Gradle, Android SDK, and proje chromecast.app.id = APP_ID ``` -This is something to keep **private** and you obtain it by sending a message to `support at Amahi dot org`. +This is something to keep **private** and you obtain it by sending a message to . 2. Build the application using a command line or using GUI. From 761a34e8a5d9ddb1bb35f295b711334a615358d6 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Mon, 20 Jul 2020 16:48:31 +0530 Subject: [PATCH 7/8] Application Crash Reports (#565) * Add ACRA for Crash Reporting during development --- .gitignore | 3 ++ .travis.yml | 4 +- README.md | 16 ++++++-- acra.properties.sample | 4 ++ build.gradle | 26 ++++++++++--- fakeAcra.properties | 5 +++ fakeApi.properties | 2 + fakeSigning.properties | 2 + gradle/wrapper/gradle-wrapper.properties | 4 +- src/main/AndroidManifest.xml | 1 + .../org/amahi/anywhere/AmahiApplication.java | 38 ++++++++++++++++++- .../java/org/amahi/anywhere/server/Api.java | 4 ++ src/main/res/values/strings.xml | 2 + 13 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 acra.properties.sample create mode 100644 fakeAcra.properties diff --git a/.gitignore b/.gitignore index 78acf215a..e8751f9f1 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ signing.properties amahi-release-key.keystore .DS* + +# Acra +acra.properties diff --git a/.travis.yml b/.travis.yml index bb4eb1c6d..a2d460a82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,13 @@ language: android before_install: + - yes | sdkmanager "platforms;android-29" - yes | sdkmanager "platforms;android-28" + - yes | sdkmanager "platforms;android-19" jdk: - oraclejdk8 -sudo: required android: components: - tools @@ -14,7 +15,6 @@ android: - platform-tools - build-tools-28.0.3 - android-28 - - android-26 - android-19 - extra-android-support - extra-android-m2repository diff --git a/README.md b/README.md index f77b1e253..c5a85eaa5 100644 --- a/README.md +++ b/README.md @@ -31,16 +31,24 @@ You will need JDK 1.8+ installed to work with it. Gradle, Android SDK, and proje This is something to keep **private** and you obtain it by sending a message to . +2. Set ACRA information -2. Build the application using a command line or using GUI. + ``` + $ vim acra.properties + ``` + ``` + mailto.email = myemail@mydomain.com + ``` + +Enter your personal email in place of `myemail@mydomain.com` + +3. Build the application using a command line or using GUI. ``` $ ./gradlew clean assembleDebug - ``` - -3. Once you have built the application, you will be needing credentials to use the application. Go to Amahi website and create your account, once the account is activated, you will see the description on how to set up the Amahi server. However, this is not strictly needed, as we have a set up of a demo server called "Welcome to Amahi" which you should see even without your own server installed. +4. Once you have built the application, you will be needing credentials to use the application. Go to Amahi website and create your account, once the account is activated, you will see the description on how to set up the Amahi server. However, this is not strictly needed, as we have a set up of a demo server called "Welcome to Amahi" which you should see even without your own server installed. ## Code Style Convention diff --git a/acra.properties.sample b/acra.properties.sample new file mode 100644 index 000000000..1cbfc975a --- /dev/null +++ b/acra.properties.sample @@ -0,0 +1,4 @@ +# Set ACRA mailing information in acra.properties. +# This is something to keep private and can be created by following steps in README.md + +mailto.email = myemail@mydomain.com diff --git a/build.gradle b/build.gradle index b7c5f9285..d6f726fd8 100644 --- a/build.gradle +++ b/build.gradle @@ -6,8 +6,8 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.4.1' - classpath 'io.fabric.tools:gradle:1.26.1' + classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'io.fabric.tools:gradle:1.28.1' } } @@ -52,10 +52,13 @@ android { targetSdkVersion 28 def apiFile = file("api.properties") + def acraFile = file("acra.properties") def apiProperties = new Properties() + def acraProperties = new Properties() - // NOTE-cpg: this fake api is here for the tests to pass + // NOTE-cpg: this fakeApi and fakeAcra is here for the tests to pass def fakeApiFile = file("fakeApi.properties") + def fakeAcraFile = file("fakeAcra.properties") if (apiFile.exists()) { apiProperties.load(apiFile.newInputStream()) @@ -63,11 +66,18 @@ android { apiProperties.load(fakeApiFile.newInputStream()) } + if (acraFile.exists()) { + acraProperties.load(acraFile.newInputStream()) + } else { + acraProperties.load(fakeAcraFile.newInputStream()) + } + buildConfigField "String", "API_URL_AMAHI", formatStringField(apiProperties["url.amahi"]) buildConfigField "String", "API_URL_PROXY", formatStringField(apiProperties["url.proxy"]) buildConfigField "String", "API_CLIENT_ID", formatStringField(apiProperties["client.id"]) buildConfigField "String", "API_CLIENT_SECRET", formatStringField(apiProperties["client.secret"]) buildConfigField "String", "CHROMECAST_APP_ID", formatStringField(apiProperties["chromecast.app.id"]) + buildConfigField "String", "ACRA_EMAIL", formatStringField(acraProperties["mailto.email"]) testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -88,8 +98,8 @@ android { } } compileOptions { - targetCompatibility 1.8 - sourceCompatibility 1.8 + targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_1_8 } } @@ -171,6 +181,12 @@ dependencies { implementation 'android.arch.persistence.room:runtime:' + rootProject.archRoomVersion annotationProcessor 'android.arch.persistence.room:compiler:' + rootProject.archRoomVersion + def acraVersion = '5.6.1' + implementation "ch.acra:acra-mail:$acraVersion" + implementation "ch.acra:acra-dialog:$acraVersion" + implementation "ch.acra:acra-notification:$acraVersion" + implementation "ch.acra:acra-toast:$acraVersion" + // Uncomment the dependencies below to enable Chuck Interceptor for logging /* debugImplementation 'com.readystatesoftware.chuck:library:1.1.0' diff --git a/fakeAcra.properties b/fakeAcra.properties new file mode 100644 index 000000000..eaeda3d7c --- /dev/null +++ b/fakeAcra.properties @@ -0,0 +1,5 @@ +# Set ACRA mailing information in acra.properties. +# This is something to keep private and can be created by following steps in README.md +# Purpose: This file is required for Tests and Travis checks to pass + +mailto.email = myemail@mydomain.com diff --git a/fakeApi.properties b/fakeApi.properties index 5d0473ebe..b0f2d2482 100644 --- a/fakeApi.properties +++ b/fakeApi.properties @@ -1,6 +1,8 @@ # Set API information in api.properties. # This is something to keep private and you obtain it by asking in the Amahi IRC channel or # send a message to support at Amahi dot org +# Purpose: This file is required for Tests and Travis checks to pass + url.amahi=https://amahi.org url.proxy=https://amahi.org client.id=1234567890 diff --git a/fakeSigning.properties b/fakeSigning.properties index 86d6879d8..5bb671b88 100644 --- a/fakeSigning.properties +++ b/fakeSigning.properties @@ -1,6 +1,8 @@ # Set API information in api.properties. # This is something to keep private and you obtain it by asking in the Amahi IRC channel or # send a message to support at Amahi dot org +# Purpose: This file is required for Tests and Travis checks to pass + keystore.file=debug.keystore keystore.password=android key.alias=androiddebugkey diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fe7c2b518..ea4655882 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Jun 09 01:34:57 IST 2019 +#Sat Jul 18 05:49:07 IST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index fd718f4bf..d6626655c 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -33,6 +33,7 @@ + diff --git a/src/main/java/org/amahi/anywhere/AmahiApplication.java b/src/main/java/org/amahi/anywhere/AmahiApplication.java index f3446dd94..41e4b3845 100644 --- a/src/main/java/org/amahi/anywhere/AmahiApplication.java +++ b/src/main/java/org/amahi/anywhere/AmahiApplication.java @@ -27,13 +27,21 @@ import android.os.Build; import android.os.StrictMode; import android.preference.PreferenceManager; + import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatDelegate; import com.crashlytics.android.Crashlytics; +import org.acra.ACRA; +import org.acra.ReportField; +import org.acra.config.CoreConfigurationBuilder; +import org.acra.config.MailSenderConfigurationBuilder; +import org.acra.config.ToastConfigurationBuilder; +import org.acra.data.StringFormat; import org.amahi.anywhere.job.NetConnectivityJob; import org.amahi.anywhere.job.PhotosContentJob; +import org.amahi.anywhere.server.Api; import dagger.ObjectGraph; import io.fabric.sdk.android.Fabric; @@ -43,6 +51,7 @@ * Application declaration. Basically sets things up at the startup time, * such as dependency injection, logging, crash reporting and possible ANR detecting. */ + public class AmahiApplication extends Application { private ObjectGraph injector; @@ -162,7 +171,34 @@ private void createNotificationChannel() { NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(uploadChannel); notificationManager.createNotificationChannel(downloadChannel); - } + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + if (isDebugging()) { + + CoreConfigurationBuilder builder = new CoreConfigurationBuilder(this) + .setBuildConfigClass(BuildConfig.class) + .setReportFormat(StringFormat.JSON) + .setAlsoReportToAndroidFramework(true) + .setReportContent(ReportField.APP_VERSION_CODE) + .setReportContent(ReportField.APP_VERSION_NAME) + .setReportContent(ReportField.ANDROID_VERSION) + .setReportContent(ReportField.PHONE_MODEL) + .setReportContent(ReportField.CUSTOM_DATA) + .setReportContent(ReportField.STACK_TRACE) + .setReportContent(ReportField.LOGCAT); + + builder.getPluginConfigurationBuilder(MailSenderConfigurationBuilder.class) + .setMailTo(Api.getAcraEmail()) + .setEnabled(true); + + builder.getPluginConfigurationBuilder(ToastConfigurationBuilder.class) + .setResText(R.string.acra_report_toast) + .setEnabled(true); + + ACRA.init(this, builder); + } + } } diff --git a/src/main/java/org/amahi/anywhere/server/Api.java b/src/main/java/org/amahi/anywhere/server/Api.java index 2ef21718d..e25b87b5f 100644 --- a/src/main/java/org/amahi/anywhere/server/Api.java +++ b/src/main/java/org/amahi/anywhere/server/Api.java @@ -43,4 +43,8 @@ public static String getClientId() { public static String getClientSecret() { return BuildConfig.API_CLIENT_SECRET; } + + public static String getAcraEmail() { + return BuildConfig.ACRA_EMAIL; + } } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 4137e2cad..769b6ac8b 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -320,4 +320,6 @@ Go back Select the type of connection you want. You can set it as Auto detect, remote or local area network. + ACRA Log Report Sent! + From e02c2ce6bb6f27a366b81b90d0186cb2e11e592a Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Tue, 28 Jul 2020 00:59:15 +0530 Subject: [PATCH 8/8] enable multidex --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 8777af371..edc93039e 100644 --- a/build.gradle +++ b/build.gradle @@ -79,6 +79,8 @@ android { buildConfigField "String", "CHROMECAST_APP_ID", formatStringField(apiProperties["chromecast.app.id"]) buildConfigField "String", "ACRA_EMAIL", formatStringField(acraProperties["mailto.email"]) + multiDexEnabled true + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" }