diff --git a/app/build.gradle b/app/build.gradle
index ba1d689d..0ffbfa37 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -140,8 +140,8 @@ dependencies {
//noinspection GradleDynamicVersion
compile 'com.anjlab.android.iab.v3:library:1.0.+'
compile 'de.psdev.licensesdialog:licensesdialog:1.8.0'
- compile 'com.github.kabouzeid:AppIntro:3.3.0k'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
compile 'com.github.kabouzeid:RecyclerView-FastScroll:v1.6-kmod'
+ compile 'com.heinrichreimersoftware:material-intro:1.0'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 55eaffce..623b4ce7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -149,7 +149,8 @@
android:label="@string/action_about" />
diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/ChangelogDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/ChangelogDialog.java
index a982b4ef..af1a9e22 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/ChangelogDialog.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/ChangelogDialog.java
@@ -2,6 +2,7 @@ package com.kabouzeid.gramophone.dialogs;
import android.annotation.SuppressLint;
import android.app.Dialog;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -56,13 +57,8 @@ public class ChangelogDialog extends DialogFragment {
.showListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
- try {
- PackageInfo pInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0);
- int currentVersion = pInfo.versionCode;
- PreferenceUtil.getInstance(getActivity()).setLastChangeLogVersion(currentVersion);
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
+ if (getActivity() != null)
+ setChangelogRead(getActivity());
}
})
.build();
@@ -93,6 +89,16 @@ public class ChangelogDialog extends DialogFragment {
return dialog;
}
+ public static void setChangelogRead(@NonNull Context context) {
+ try {
+ PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+ int currentVersion = pInfo.versionCode;
+ PreferenceUtil.getInstance(context).setLastChangeLogVersion(currentVersion);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
private static String colorToHex(int color) {
return Integer.toHexString(color).substring(2);
}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AboutActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AboutActivity.java
index 4b19cf68..ab04100c 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AboutActivity.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AboutActivity.java
@@ -23,6 +23,7 @@ import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.dialogs.ChangelogDialog;
import com.kabouzeid.gramophone.dialogs.DonationDialog;
import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity;
+import com.kabouzeid.gramophone.ui.activities.intro.AppIntroActivity;
import butterknife.Bind;
import butterknife.ButterKnife;
@@ -224,7 +225,7 @@ public class AboutActivity extends AbsBaseActivity implements View.OnClickListen
} else if (v == licenses) {
showLicenseDialog();
} else if (v == intro) {
- startActivity(new Intent(this, IntroActivity.class));
+ startActivity(new Intent(this, AppIntroActivity.class));
} else if (v == addToGooglePlusCircles) {
openUrl(GOOGLE_PLUS);
} else if (v == followOnTwitter) {
diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/IntroActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/IntroActivity.java
deleted file mode 100644
index de368542..00000000
--- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/IntroActivity.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.kabouzeid.gramophone.ui.activities;
-
-import android.Manifest;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v4.content.ContextCompat;
-import android.widget.Toast;
-
-import com.github.paolorotolo.appintro.AppIntro;
-import com.github.paolorotolo.appintro.AppIntroFragment;
-import com.kabouzeid.appthemehelper.ATH;
-import com.kabouzeid.appthemehelper.util.ColorUtil;
-import com.kabouzeid.gramophone.R;
-import com.kabouzeid.gramophone.util.PreferenceUtil;
-
-/**
- * @author Karim Abou Zeid (kabouzeid)
- */
-public class IntroActivity extends AppIntro {
- @Override
- public void init(Bundle savedInstanceState) {
- int color = ContextCompat.getColor(this, R.color.blue_grey_700);
-
- ATH.setStatusbarColor(this, ColorUtil.darkenColor(color));
- ATH.setTaskDescriptionColor(this, color);
-
- showSkipButton(false);
-
- setDoneText(getString(R.string.action_done).toUpperCase());
- setGrantText(getString(R.string.action_grant).toUpperCase());
-
- addSlide(AppIntroFragment.newInstance(getString(R.string.app_name), getString(R.string.welcome_to_phonograph), R.drawable.icon_web, color));
- if (!hasExternalStoragePermission()) {
- addSlide(AppIntroFragment.newInstance(getString(R.string.label_storage), getString(R.string.storage_permission_explaination), R.drawable.ic_folder_web, color));
- askForPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
- }
- addSlide(AppIntroFragment.newInstance(getString(R.string.label_playing_queue), getString(R.string.open_playing_queue_instruction), R.drawable.tutorial_queue_swipe_up, color));
- addSlide(AppIntroFragment.newInstance(getString(R.string.label_playing_queue), getString(R.string.rearrange_playing_queue_instruction), R.drawable.tutorial_rearrange_queue, color));
- }
-
- private boolean hasExternalStoragePermission() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- return checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
- }
- return true;
- }
-
- boolean doubleBackToExitPressedOnce = false;
-
- @Override
- public void onBackPressed() {
- if (doubleBackToExitPressedOnce) {
- onSkipPressed();
- return;
- }
-
- doubleBackToExitPressedOnce = true;
- Toast.makeText(this, R.string.press_back_again_to_exit_intro, Toast.LENGTH_SHORT).show();
-
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- doubleBackToExitPressedOnce = false;
- }
- }, 2000);
- }
-
- @Override
- public void onSkipPressed() {
- super.onSkipPressed();
- PreferenceUtil.getInstance(this).setIntroShown();
- }
-
- @Override
- public void onDonePressed() {
- super.onDonePressed();
- PreferenceUtil.getInstance(this).setIntroShown();
- }
-}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java
index 8794c6de..c580f5d1 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java
@@ -56,6 +56,7 @@ import com.kabouzeid.gramophone.loader.SongLoader;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity;
+import com.kabouzeid.gramophone.ui.activities.intro.AppIntroActivity;
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.AbsMainActivityFragment;
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.AbsMainActivityRecyclerViewCustomGridSizeFragment;
import com.kabouzeid.gramophone.util.NavigationUtil;
@@ -94,7 +95,7 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
private PagerAdapter pagerAdapter;
private MaterialCab cab;
- private boolean introActivityHandlingPermissions;
+ private boolean blockRequestPermissions;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -116,17 +117,18 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
setUpToolbar();
setUpViewPager();
- checkChangelog();
-
if (!PreferenceUtil.getInstance(this).introShown()) {
- // let the app intro handle getting the permissions first
- introActivityHandlingPermissions = true;
+ PreferenceUtil.getInstance(this).setIntroShown();
+ ChangelogDialog.setChangelogRead(this);
+ blockRequestPermissions = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
- startActivityForResult(new Intent(MainActivity.this, IntroActivity.class), APP_INTRO_REQUEST);
+ startActivityForResult(new Intent(MainActivity.this, AppIntroActivity.class), APP_INTRO_REQUEST);
}
}, 200);
+ } else {
+ checkShowChangelog();
}
}
@@ -134,16 +136,16 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == APP_INTRO_REQUEST) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- // app intro is done, recreate to refresh permissions
- onPermissionsChanged();
+ blockRequestPermissions = false;
+ if (!hasPermissions()) {
+ requestPermissions();
}
}
}
@Override
protected void requestPermissions() {
- if (!introActivityHandlingPermissions) super.requestPermissions();
+ if (!blockRequestPermissions) super.requestPermissions();
}
@Override
@@ -574,7 +576,7 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
}
- private void checkChangelog() {
+ private void checkShowChangelog() {
try {
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
int currentVersion = pInfo.versionCode;
diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsBaseActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsBaseActivity.java
index 70cfb646..edbf8be9 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsBaseActivity.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsBaseActivity.java
@@ -58,16 +58,20 @@ public abstract class AbsBaseActivity extends AbsThemeActivity implements KabVie
if (hasPermissions() != createdWithPermissionsGranted) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- // the handler is necessary to avoid "java.lang.RuntimeException: Performing pause of activity that is not resumed"
onPermissionsChanged();
}
}
}
protected void onPermissionsChanged() {
+ postRecreate();
+ }
+
+ @Override
+ public void postRecreate() {
if (!recreating) {
recreating = true;
- postRecreate();
+ super.postRecreate();
}
}
@@ -86,7 +90,7 @@ public abstract class AbsBaseActivity extends AbsThemeActivity implements KabVie
/**
* Should be overwritten and re enable all {@link android.view.View} to ensure they are accessible again
- *
+ *
* This is necessary because of a bug with the shared element transition
*/
@Override
@@ -96,7 +100,7 @@ public abstract class AbsBaseActivity extends AbsThemeActivity implements KabVie
/**
* Should be overwritten and disable all views that start a new activity on click to prevent opening an activity multiple times
- *
+ *
* This is necessary because of a bug with the shared element transition
*/
@Override
diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/intro/AppIntroActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/intro/AppIntroActivity.java
new file mode 100644
index 00000000..7bf75fcd
--- /dev/null
+++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/intro/AppIntroActivity.java
@@ -0,0 +1,60 @@
+package com.kabouzeid.gramophone.ui.activities.intro;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+
+import com.kabouzeid.gramophone.R;
+
+/**
+ * @author Karim Abou Zeid (kabouzeid)
+ */
+public class AppIntroActivity extends com.heinrichreimersoftware.materialintro.app.IntroActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ setFullscreen(false);
+ super.onCreate(savedInstanceState);
+
+ addSlide(new PhonographSimpleSlide.Builder()
+ .title(R.string.app_name)
+ .description(R.string.welcome_to_phonograph)
+ .image(R.drawable.icon_web)
+ .background(R.color.md_blue_grey_500)
+ .backgroundDark(R.color.md_blue_grey_600)
+ .build());
+ addSlide(new PhonographSimpleSlide.Builder()
+ .title(R.string.label_playing_queue)
+ .description(R.string.open_playing_queue_instruction)
+ .image(R.drawable.tutorial_queue_swipe_up)
+ .background(R.color.md_purple_500)
+ .backgroundDark(R.color.md_purple_600)
+ .build());
+ addSlide(new PhonographSimpleSlide.Builder()
+ .title(R.string.label_playing_queue)
+ .description(R.string.rearrange_playing_queue_instruction)
+ .image(R.drawable.tutorial_rearrange_queue)
+ .background(R.color.md_deep_purple_500)
+ .backgroundDark(R.color.md_deep_purple_600)
+ .build());
+
+ if (!hasExternalStoragePermission()) {
+ addSlide(new PhonographSimpleSlide.Builder()
+ .title(R.string.label_storage)
+ .description(R.string.storage_permission_explaination)
+ .image(R.drawable.ic_folder_web)
+ .background(R.color.md_indigo_500)
+ .backgroundDark(R.color.md_indigo_600)
+ .build());
+ }
+ }
+
+ private boolean hasExternalStoragePermission() {
+ //noinspection SimplifiableIfStatement
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ return checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
+ }
+ return true;
+ }
+}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/intro/PhonographSimpleSlide.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/intro/PhonographSimpleSlide.java
new file mode 100644
index 00000000..43128666
--- /dev/null
+++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/intro/PhonographSimpleSlide.java
@@ -0,0 +1,151 @@
+package com.kabouzeid.gramophone.ui.activities.intro;
+
+import android.os.Bundle;
+import android.support.annotation.ColorRes;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.graphics.ColorUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.heinrichreimersoftware.materialintro.slide.Slide;
+import com.kabouzeid.gramophone.R;
+
+public class PhonographSimpleSlide extends Slide {
+
+ private final Fragment fragment;
+ @ColorRes
+ private final int background;
+ @ColorRes
+ private final int backgroundDark;
+
+ private PhonographSimpleSlide(Builder builder) {
+ fragment = Fragment.newInstance(builder.title, builder.description, builder.image, builder.background);
+ background = builder.background;
+ backgroundDark = builder.backgroundDark;
+ }
+
+ @Override
+ public Fragment getFragment() {
+ return fragment;
+ }
+
+ @Override
+ public int getBackground() {
+ return background;
+ }
+
+ @Override
+ public int getBackgroundDark() {
+ return backgroundDark;
+ }
+
+ public static class Builder {
+ @ColorRes
+ private int background = 0;
+ @ColorRes
+ private int backgroundDark = 0;
+ @StringRes
+ private int title = 0;
+ @StringRes
+ private int description = 0;
+ @DrawableRes
+ private int image = 0;
+
+ public Builder background(int background) {
+ this.background = background;
+ return this;
+ }
+
+ public Builder backgroundDark(int backgroundDark) {
+ this.backgroundDark = backgroundDark;
+ return this;
+ }
+
+ public Builder title(int title) {
+ this.title = title;
+ return this;
+ }
+
+ public Builder description(int description) {
+ this.description = description;
+ return this;
+ }
+
+ public Builder image(int image) {
+ this.image = image;
+ return this;
+ }
+
+ public PhonographSimpleSlide build() {
+ if (background == 0 || title == 0)
+ throw new IllegalArgumentException("You must set at least a title and background.");
+ return new PhonographSimpleSlide(this);
+ }
+ }
+
+ public static class Fragment extends android.support.v4.app.Fragment {
+ private static final String ARGUMENT_TITLE_RES =
+ "com.kabouzeid.gramophone.SimpleFragment.ARGUMENT_TITLE_RES";
+ private static final String ARGUMENT_DESCRIPTION_RES =
+ "com.kabouzeid.gramophone.SimpleFragment.ARGUMENT_DESCRIPTION_RES";
+ private static final String ARGUMENT_IMAGE_RES =
+ "com.kabouzeid.gramophone.SimpleFragment.ARGUMENT_IMAGE_RES";
+ private static final String ARGUMENT_BACKGROUND_RES =
+ "com.kabouzeid.gramophone.SimpleFragment.ARGUMENT_BACKGROUND_RES";
+
+ public static Fragment newInstance(@StringRes int title, @StringRes int description, @DrawableRes int image, @ColorRes int background) {
+ Fragment fragment = new Fragment();
+
+ Bundle arguments = new Bundle();
+ arguments.putInt(ARGUMENT_TITLE_RES, title);
+ arguments.putInt(ARGUMENT_DESCRIPTION_RES, description);
+ arguments.putInt(ARGUMENT_IMAGE_RES, image);
+ arguments.putInt(ARGUMENT_BACKGROUND_RES, background);
+ fragment.setArguments(arguments);
+
+ return fragment;
+ }
+
+ public Fragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View fragment = inflater.inflate(R.layout.fragment_intro_slide, container, false);
+
+ TextView title = (TextView) fragment.findViewById(R.id.mi_title);
+ TextView description = (TextView) fragment.findViewById(R.id.mi_description);
+ ImageView image = (ImageView) fragment.findViewById(R.id.mi_image);
+
+ Bundle arguments = getArguments();
+
+ title.setText(arguments.getInt(ARGUMENT_TITLE_RES));
+ description.setText(arguments.getInt(ARGUMENT_DESCRIPTION_RES));
+ image.setImageResource(arguments.getInt(ARGUMENT_IMAGE_RES));
+
+ int background = ContextCompat.getColor(getContext(),
+ arguments.getInt(ARGUMENT_BACKGROUND_RES));
+ if (ColorUtils.calculateLuminance(background) > 0.4) {
+ //Use dark text color
+ title.setTextColor(ContextCompat.getColor(getContext(),
+ R.color.mi_text_color_primary_light));
+ description.setTextColor(ContextCompat.getColor(getContext(),
+ R.color.mi_text_color_secondary_light));
+ } else {
+ //Use light text color
+ title.setTextColor(ContextCompat.getColor(getContext(),
+ R.color.mi_text_color_primary_dark));
+ description.setTextColor(ContextCompat.getColor(getContext(),
+ R.color.mi_text_color_secondary_dark));
+ }
+
+ return fragment;
+ }
+ }
+}
diff --git a/app/src/main/res/layout/fragment_intro_slide.xml b/app/src/main/res/layout/fragment_intro_slide.xml
new file mode 100644
index 00000000..9c3e76fc
--- /dev/null
+++ b/app/src/main/res/layout/fragment_intro_slide.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c67f077d..2ca0da40 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -231,7 +231,7 @@
Storage
Swipe the card in the now playing screen up to reveal the full playing queue.
Rearrange the playing queue by dragging a song from its track number.
- The storage permission is required for Phonograph to read your music library.
+ Phonograph will now ask you to grant the storage permission. The permission is required in order to read your music library.
Library
Folders
Saved playlist to %s.