tm.android.chronos.services.TimerRunner.java Source code

Java tutorial

Introduction

Here is the source code for tm.android.chronos.services.TimerRunner.java

Source

/*
 * TimerRunner
 *
 *   Copyright (c) 2018 Thierry Margenstern under MIT license
 *   http://opensource.org/licenses/MIT
 */
package tm.android.chronos.services;

import android.app.ActivityManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import tm.android.chronos.R;
import tm.android.chronos.activity.Chronos;
import tm.android.chronos.activity.TimerActivity;
import tm.android.chronos.audio.AudioProperties;
import tm.android.chronos.audio.CommonMediaPlayer;
import tm.android.chronos.core.Clock;
import tm.android.chronos.core.ClockTimer;
import tm.android.chronos.core.Units;
import tm.android.chronos.preference.PreferenceCst;
import tm.android.chronos.sql.DbConstant;
import tm.android.chronos.sql.DbLiveObject;
import tm.android.chronos.util.Couple;
import tm.android.chronos.util.Permissions;

import java.util.List;

/**
 * This class do the task when a timer reached his end :
 * check the state of the app and decide if notification is needed or not
 * Launch (if possible) sound or vibrate, then if needed the notification
 */
@SuppressWarnings("ConstantConditions")
class TimerRunner {
    private boolean launchNotification = false;
    private boolean playSound = false;
    private Context context;
    private Intent intent;
    private AudioProperties audioProperties;

    TimerRunner(Context context) {
        this.context = context;
    }

    private void setActivityState() {
        //Log.i("Timer Service", "Entering setActivityState at " + ftime.format(System.currentTimeMillis()));
        int importance = 230;
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

        for (ActivityManager.RunningAppProcessInfo appProcessInfo : activityManager.getRunningAppProcesses())
            for (String pkg : appProcessInfo.pkgList)
                if (pkg.equals(context.getPackageName()))
                    importance = appProcessInfo.importance;

        // only this value ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND say that the application is visible on the foreground
        launchNotification = importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
    }

    private void createNotification(long duration) {
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);

        String channelId = "channel-01";

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            String channelName = "Chronos Channel";
            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel mChannel = new NotificationChannel(channelId, channelName, importance);
            notificationManager.createNotificationChannel(mChannel);
        }

        int min = (int) (duration / 60000);
        if (Units.hasNoResources())
            Units.setResources(context.getResources());
        String text = Units.getLocalizedTextWithParams("timer_notification", min + "", (min > 1 ? "s" : ""));//"Timer of " + min + " minute" + (min > 1 ? "s" : "") + " is finished";
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, channelId)
                .setSmallIcon(R.drawable.icon)
                .setContentTitle(context.getResources().getString(R.string.app_name_timer)).setContentText(text)
                .setPriority(NotificationCompat.PRIORITY_MAX)
                // Set the intent that will fire when the user taps the notification
                .setContentIntent(pendingIntent).setAutoCancel(true).setCategory(NotificationCompat.CATEGORY_ALARM);

        notificationManager.notify(0, mBuilder.build());
    }

    private void prepareSound() {
        playSound = false;
        if (Permissions.Instance().hasReadWriteExternalStorage(context)) {
            Couple<Boolean, Integer> result = Permissions.Instance().checkZenModeAccess(context);
            if (result.getValue() == AudioManager.RINGER_MODE_NORMAL
                    || (result.getValue() != AudioManager.RINGER_MODE_NORMAL) && result.getKey()) {
                playSound = true;
            }
        }
        if (playSound) {
            audioProperties = new AudioProperties();
            audioProperties.loadFromPref(PreferenceCst.PREFIX_TIMER, context);
            CommonMediaPlayer.build(context);
        }
    }

    private void prepareIntent() {
        intent = new Intent(context, Chronos.class);
        intent.putExtra(Chronos.DIRECT_CALL, TimerActivity.class.getName());
    }

    void run() {
        Log.i(Chronos.name + "-TimerRunner", "Entering run at " + Chronos.ftime.format(System.currentTimeMillis()));
        //preferences = context.getSharedPreferences(PreferenceCst.PREF_STORE_NAME, Context.MODE_PRIVATE);

        DbLiveObject<Clock> dbLiveObject = new DbLiveObject<>(context);
        List<Clock> list = dbLiveObject.getRunningLiveObjects(DbConstant.RUNNING_TIMER_TABLE_NAME);
        ClockTimer clockTimer1 = (ClockTimer) list.get(0);
        dbLiveObject.close();

        long duration = clockTimer1.getDuration();
        Log.i(Chronos.name + "-TimerRunner", "Timer duration : " + duration);
        ClockTimer clockTimer = new ClockTimer();
        clockTimer.setDuration(duration);
        clockTimer.start(clockTimer1.getStartTime());

        setActivityState();
        prepareIntent();
        prepareSound();

        if (playSound && audioProperties.isPlaysound()) {
            if (audioProperties.isVolumeVariable()) {
                CommonMediaPlayer.Instance().setVariableVolumeAndStart(audioProperties.getMinVolumeVariable(),
                        audioProperties.getMaxVolumeVariable(), audioProperties.getVolumeVariableDuration(),
                        audioProperties.getVolumeVariableStep());
            } else {
                CommonMediaPlayer.Instance().setFixedVolumeLevel(audioProperties.getLevelVolumeFixe());
            }

            CommonMediaPlayer.Instance().setVariableDurationAndStart(audioProperties.getDataSource(),
                    audioProperties.getSoundDuration(), audioProperties.getSoundRepeatCount());
            Log.i(Chronos.name + "-TimerRunner", "CommonMediaPlayer started");
        }

        if (audioProperties.isVibrate())
            CommonMediaPlayer.Instance().startVibrator(audioProperties.getVibrateDuration());

        if (launchNotification) {
            createNotification(duration);
        } else {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);

        }

        while (clockTimer1.isRunning()) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
            }
        }
        Log.i(Chronos.name + "-TimerRunner", "Finished at " + Chronos.ftime.format(System.currentTimeMillis()));
    }
}