From f4680fdb448fec2e0e36ab5b39f35e7a1cffab9e Mon Sep 17 00:00:00 2001 From: Karim Abou Zeid Date: Sun, 21 Feb 2016 18:20:35 +0100 Subject: [PATCH] Added new IntroActivity. --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 3 +- .../gramophone/dialogs/ChangelogDialog.java | 20 ++- .../ui/activities/AboutActivity.java | 3 +- .../ui/activities/IntroActivity.java | 81 ---------- .../ui/activities/MainActivity.java | 24 +-- .../ui/activities/base/AbsBaseActivity.java | 12 +- .../ui/activities/intro/AppIntroActivity.java | 60 +++++++ .../intro/PhonographSimpleSlide.java | 151 ++++++++++++++++++ .../main/res/layout/fragment_intro_slide.xml | 42 +++++ app/src/main/res/values/strings.xml | 2 +- 11 files changed, 293 insertions(+), 107 deletions(-) delete mode 100644 app/src/main/java/com/kabouzeid/gramophone/ui/activities/IntroActivity.java create mode 100644 app/src/main/java/com/kabouzeid/gramophone/ui/activities/intro/AppIntroActivity.java create mode 100644 app/src/main/java/com/kabouzeid/gramophone/ui/activities/intro/PhonographSimpleSlide.java create mode 100644 app/src/main/res/layout/fragment_intro_slide.xml 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.