com.abhijitvalluri.android.fitnotifications.setup.AppIntroActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.abhijitvalluri.android.fitnotifications.setup.AppIntroActivity.java

Source

/*
   Copyright 2017 Abhijit Kiran Valluri
    
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
    
 http://www.apache.org/licenses/LICENSE-2.0
    
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package com.abhijitvalluri.android.fitnotifications.setup;

import android.app.ActivityOptions;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.NotificationCompat;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.abhijitvalluri.android.fitnotifications.AppChoicesActivity;
import com.abhijitvalluri.android.fitnotifications.R;
import com.abhijitvalluri.android.fitnotifications.SettingsActivity;
import com.abhijitvalluri.android.fitnotifications.services.NLService;
import com.abhijitvalluri.android.fitnotifications.utils.Constants;
import com.abhijitvalluri.android.fitnotifications.utils.Func;
import com.heinrichreimersoftware.materialintro.app.IntroActivity;
import com.heinrichreimersoftware.materialintro.slide.FragmentSlide;
import com.heinrichreimersoftware.materialintro.slide.SimpleSlide;

import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * Intro activity to display a helpful setup tutorial
 */
public class AppIntroActivity extends IntroActivity {

    private final Integer NOTIFICATION_ID = (int) ((new Date().getTime() / 1000L) % Integer.MAX_VALUE);
    private static final int ENABLE_NOTIFICATION_ACCESS_INTENT = 1;
    private static final int INSTALL_FITBIT_INTENT = 2;
    private static final int LAUNCH_FITBIT_INTENT = 3;
    private static final int APP_CHOICES_INTENT = 4;

    private Bundle LAUNCH_ACTIVITY_ANIM_BUNDLE;

    private FragmentSlide mEnableNotificationSlide;
    private FragmentSlide mFitbitInstallSlide;
    private FragmentSlide mLaunchFitbitSlide;
    private FragmentSlide mAppChoicesSlide;
    private PackageManager mPackageManager;

    public static Intent newIntent(Context packageContext) {
        return new Intent(packageContext, AppIntroActivity.class);
    }

    private void addIntroSlide() {
        addSlide(new SimpleSlide.Builder().layout(R.layout.fragment_intro).title(R.string.intro_welcome_title)
                .description(R.string.intro_welcome_desc).image(R.drawable.intro_welcome)
                .background(R.color.colorPrimary).backgroundDark(R.color.colorPrimaryDark).canGoBackward(true)
                .buttonCtaLabel(R.string.intro_get_started_button)
                .buttonCtaClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        nextSlide();
                    }
                }).build());
    }

    private void addFitbitInstallSlide() {
        if (!isFitbitAppInstalled()) {
            mFitbitInstallSlide = createFitbitInstallSlide();
            addSlide(mFitbitInstallSlide);
        }
    }

    private boolean isFitbitAppInstalled() {
        List<String> packageNames = Func.getInstalledPackageNames(mPackageManager);
        return packageNames.contains(Constants.FITBIT_PACKAGE_NAME);
    }

    private void addEnableNotificationAccessSlide() {
        Set<String> EnabledListenerPackagesSet = NotificationManagerCompat.getEnabledListenerPackages(this);
        if (EnabledListenerPackagesSet.contains(Constants.PACKAGE_NAME)
                && EnabledListenerPackagesSet.contains(Constants.FITBIT_PACKAGE_NAME)) {
            CustomSlideFragment fragment = new CustomSlideFragment();
            fragment.setCanGoForward(true).setCanGoBackward(true)
                    .setTitleText(R.string.intro_enable_access_success_title)
                    .setDescriptionText(R.string.intro_enable_access_success_desc)
                    .setImage(R.drawable.intro_enable_notifications);

            mEnableNotificationSlide = new FragmentSlide.Builder().fragment(fragment)
                    .background(R.color.purple_intro).backgroundDark(R.color.purpleDark_intro).build();
        } else {
            CustomSlideFragment fragment = new CustomSlideFragment();
            fragment.setCanGoForward(false).setCanGoBackward(true).setTitleText(R.string.intro_enable_access_title)
                    .setDescriptionText(R.string.intro_enable_access_desc)
                    .setImage(R.drawable.intro_enable_notifications);

            mEnableNotificationSlide = new FragmentSlide.Builder().fragment(fragment)
                    .background(R.color.purple_intro).backgroundDark(R.color.purpleDark_intro)
                    .buttonCtaLabel(R.string.enable_notification_access)
                    .buttonCtaClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Set<String> EnabledListenerPackagesSet = NotificationManagerCompat
                                    .getEnabledListenerPackages(AppIntroActivity.this);
                            if (!EnabledListenerPackagesSet.contains(Constants.PACKAGE_NAME)
                                    || !EnabledListenerPackagesSet.contains(Constants.FITBIT_PACKAGE_NAME)) {
                                startActivityForResult(
                                        new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"),
                                        ENABLE_NOTIFICATION_ACCESS_INTENT);
                            }
                        }
                    }).build();
        }

        addSlide(mEnableNotificationSlide);
    }

    private void addDemoSlide() {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        final boolean dismissPlaceholderNotif = preferences
                .getBoolean(getString(R.string.dismiss_placeholder_notif_key), false);
        final int placeholderNotifDismissDelayMillis = preferences
                .getInt(getString(R.string.placeholder_dismiss_delay_key), Constants.DEFAULT_DELAY_SECONDS) * 1000;
        final Handler handler = new Handler();

        // Demo
        addSlide(new SimpleSlide.Builder().layout(R.layout.fragment_intro).title(R.string.intro_done_title)
                .description(R.string.intro_done_desc).image(R.drawable.intro_done).background(R.color.colorAccent)
                .backgroundDark(R.color.colorAccentDark).buttonCtaLabel(R.string.test_notification)
                .buttonCtaClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Bundle newExtra = new Bundle();

                        NotificationCompat.Builder builder = new NotificationCompat.Builder(AppIntroActivity.this);
                        String notificationText = "Sample notification subject";
                        String notificationBigText = "Sample notification body. This is where the details of the notification will be shown.";

                        StringBuilder sb = new StringBuilder();
                        sb.append("[").append("example").append("] ");
                        sb.append(notificationText);
                        if (notificationBigText.length() > 0) {
                            sb.append(" -- ").append(notificationBigText);
                        }

                        RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification);
                        contentView.setTextViewText(R.id.customNotificationText,
                                getString(R.string.placeholder_notification_text));
                        builder.setSmallIcon(R.drawable.ic_sms_white_24dp).setContentText(sb.toString())
                                .setExtras(newExtra).setContentTitle("Sample Notification Title")
                                .setContent(contentView);

                        // Creates an explicit intent for the SettingsActivity in the app
                        Intent settingsIntent = new Intent(AppIntroActivity.this, SettingsActivity.class);

                        // The stack builder object will contain an artificial back stack for the
                        // started Activity.
                        // This ensures that navigating backward from the Activity leads out of
                        // the application to the Home screen.
                        TaskStackBuilder stackBuilder = TaskStackBuilder.create(AppIntroActivity.this);
                        // Adds the back stack for the Intent (but not the Intent itself)
                        stackBuilder.addParentStack(SettingsActivity.class);
                        // Adds the Intent that starts the Activity to the top of the stack
                        stackBuilder.addNextIntent(settingsIntent);
                        PendingIntent settingsPendingIntent = stackBuilder.getPendingIntent(0,
                                PendingIntent.FLAG_UPDATE_CURRENT);
                        builder.setContentIntent(settingsPendingIntent).setAutoCancel(true);

                        ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID,
                                builder.build());

                        Toast.makeText(AppIntroActivity.this, getString(R.string.test_notification_sent),
                                Toast.LENGTH_LONG).show();

                        if (dismissPlaceholderNotif) {
                            handler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    ((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
                                            .cancel(NOTIFICATION_ID);
                                }
                            }, placeholderNotifDismissDelayMillis);
                        }
                    }
                }).build());
    }

    private void addStartServiceSlide() {
        SimpleSlide startServiceSlide = new SimpleSlide.Builder().layout(R.layout.fragment_intro)
                .title(R.string.intro_start_service_title).description(R.string.intro_start_service_desc)
                .image(R.drawable.intro_check).background(R.color.colorAccent)
                .backgroundDark(R.color.colorAccentDark).canGoForward(true).buttonCtaLabel(R.string.start_service)
                .buttonCtaClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        startService(new Intent(AppIntroActivity.this, NLService.class));
                        NLService.setEnabled(true);
                        nextSlide();
                    }
                }).build();
        addSlide(startServiceSlide);
    }

    private void addDNDModeSlide() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            addSlide(new SimpleSlide.Builder().layout(R.layout.fragment_intro).title(R.string.intro_dnd_mode_title)
                    .description(R.string.intro_dnd_mode_desc).image(R.drawable.intro_dnd_mode_info)
                    .background(R.color.black).backgroundDark(R.color.grey)
                    .buttonCtaLabel(R.string.intro_dnd_mode_button)
                    .buttonCtaClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            AlertDialog dialog = new AlertDialog.Builder(AppIntroActivity.this)
                                    .setTitle(getString(R.string.intro_dnd_mode_button))
                                    .setPositiveButton("Configure", new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            Intent intent = new Intent();
                                            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                            Uri uri = Uri.fromParts("package", Constants.PACKAGE_NAME, null);
                                            intent.setData(uri);
                                            startActivity(intent);
                                        }
                                    }).setNegativeButton("CANCEL", null).create();
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                dialog.setMessage(getString(R.string.intro_dnd_mode_nougat_message));
                            } else {
                                dialog.setMessage(getString(R.string.intro_dnd_mode_message));
                            }
                            dialog.show();
                        }
                    }).build());
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LAUNCH_ACTIVITY_ANIM_BUNDLE = ActivityOptions
                .makeCustomAnimation(AppIntroActivity.this, R.transition.left_in, R.transition.left_out).toBundle();
        mPackageManager = getPackageManager();

        // Introduction slide
        addIntroSlide();

        // Fitbit install slide
        addFitbitInstallSlide();

        // Enable notifications slide
        addEnableNotificationAccessSlide();

        // Fitbit setup - 3 steps (3 slides)
        // Step 1
        addSlide(new SimpleSlide.Builder().layout(R.layout.fragment_intro).title(R.string.intro_setup_fitbit_title1)
                .description(R.string.intro_setup_fitbit_desc1).image(R.drawable.step_one)
                .background(R.color.fitbitColor_intro).backgroundDark(R.color.fitbitColorDark_intro)
                .buttonCtaLabel(R.string.intro_setup_fitbit_toast_button)
                .buttonCtaClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(AppIntroActivity.this, getString(R.string.intro_setup_fitbit_toast_text1),
                                Toast.LENGTH_LONG).show();
                    }
                }).build());

        // Step 2
        addSlide(new SimpleSlide.Builder().layout(R.layout.fragment_intro).title(R.string.intro_setup_fitbit_title2)
                .description(R.string.intro_setup_fitbit_desc2).image(R.drawable.step_two)
                .background(R.color.fitbitColor_intro).backgroundDark(R.color.fitbitColorDark_intro).build());

        // Step 3
        mLaunchFitbitSlide = createLaunchFitbitSlide();
        addSlide(mLaunchFitbitSlide);

        // App Choices slide
        mAppChoicesSlide = createAppChoicesSlide();
        addSlide(mAppChoicesSlide);

        // Start service
        addStartServiceSlide();

        // Do not disturb mode announcement slide
        addDNDModeSlide();

        // Demo Slide
        addDemoSlide();

        setButtonBackVisible(true);
        setButtonBackFunction(BUTTON_BACK_FUNCTION_BACK);
        setButtonNextVisible(true);
        setButtonNextFunction(BUTTON_NEXT_FUNCTION_NEXT_FINISH);
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        overridePendingTransition(R.transition.right_in, R.transition.right_out);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        case ENABLE_NOTIFICATION_ACCESS_INTENT: {
            Set<String> EnabledListenerPackagesSet = NotificationManagerCompat.getEnabledListenerPackages(this);
            if (EnabledListenerPackagesSet.contains(Constants.PACKAGE_NAME)
                    && EnabledListenerPackagesSet.contains(Constants.FITBIT_PACKAGE_NAME)) {
                CustomSlideFragment fragment = (CustomSlideFragment) mEnableNotificationSlide.getFragment();
                fragment.setCanGoForward(true).setTitleText(R.string.intro_enable_access_update_title)
                        .setDescriptionText(R.string.intro_enable_access_update_desc);
            }
            return;
        }
        case INSTALL_FITBIT_INTENT: {
            if (isFitbitAppInstalled()) {
                CustomSlideFragment fragment = (CustomSlideFragment) mFitbitInstallSlide.getFragment();
                fragment.setCanGoForward(true);
                nextSlide();
            }
            return;
        }
        case LAUNCH_FITBIT_INTENT: {
            CustomSlideFragment fragment = (CustomSlideFragment) mLaunchFitbitSlide.getFragment();
            fragment.setCanGoForward(true);
            return;
        }
        case APP_CHOICES_INTENT: {
            CustomSlideFragment fragment = (CustomSlideFragment) mAppChoicesSlide.getFragment();
            fragment.setCanGoForward(true);
            return;
        }
        default:
        }
    }

    private FragmentSlide createAppChoicesSlide() {
        CustomSlideFragment fragment = new CustomSlideFragment();
        fragment.setCanGoForward(false).setCanGoBackward(true).setTitleText(R.string.app_choices)
                .setDescriptionText(R.string.intro_select_apps_desc).setImage(R.drawable.view_list);

        return new FragmentSlide.Builder().fragment(fragment).background(R.color.colorPrimary)
                .backgroundDark(R.color.colorPrimaryDark).buttonCtaLabel(R.string.app_choices_activity_title)
                .buttonCtaClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        startActivityForResult(AppChoicesActivity.newIntent(AppIntroActivity.this),
                                APP_CHOICES_INTENT, LAUNCH_ACTIVITY_ANIM_BUNDLE);
                    }
                }).build();
    }

    private FragmentSlide createLaunchFitbitSlide() {
        CustomSlideFragment fragment = new CustomSlideFragment();
        fragment.setCanGoForward(false).setCanGoBackward(true).setTitleText(R.string.intro_setup_fitbit_title3)
                .setDescriptionText(R.string.intro_setup_fitbit_desc3).setImage(R.drawable.step_three);

        return new FragmentSlide.Builder().fragment(fragment).background(R.color.fitbitColor_intro)
                .backgroundDark(R.color.fitbitColorDark_intro).buttonCtaLabel(R.string.intro_setup_fitbit_button3)
                .buttonCtaClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        try {
                            Intent i = mPackageManager.getLaunchIntentForPackage(Constants.FITBIT_PACKAGE_NAME);
                            startActivityForResult(i, LAUNCH_FITBIT_INTENT);

                        } catch (ActivityNotFoundException e) {
                            Toast.makeText(AppIntroActivity.this, getString(R.string.intro_get_fitbit_toast_text3),
                                    Toast.LENGTH_LONG).show();
                        }
                    }
                }).build();
    }

    private FragmentSlide createFitbitInstallSlide() {
        CustomSlideFragment fragment = new CustomSlideFragment();
        fragment.setCanGoForward(false).setCanGoBackward(true).setTitleText(R.string.intro_get_fitbit_title)
                .setDescriptionText(R.string.intro_get_fitbit_desc).setImage(R.drawable.get_app);

        return new FragmentSlide.Builder().fragment(fragment).background(R.color.fitbitColor_intro)
                .backgroundDark(R.color.fitbitColorDark_intro).buttonCtaLabel(R.string.intro_get_fitbit_button)
                .buttonCtaClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (!isFitbitAppInstalled()) {
                            try {
                                startActivityForResult(
                                        new Intent(Intent.ACTION_VIEW,
                                                Uri.parse("market://details?id=" + Constants.FITBIT_PACKAGE_NAME)),
                                        INSTALL_FITBIT_INTENT);
                            } catch (android.content.ActivityNotFoundException e) {
                                startActivityForResult(new Intent(Intent.ACTION_VIEW,
                                        Uri.parse("https://play.google.com/store/apps/details?id="
                                                + Constants.FITBIT_PACKAGE_NAME)),
                                        INSTALL_FITBIT_INTENT);
                            }
                        }
                    }
                }).build();
    }
}