de.gebatzens.sia.SIAApp.java Source code

Java tutorial

Introduction

Here is the source code for de.gebatzens.sia.SIAApp.java

Source

/*
 * Copyright 2015 - 2016 Hauke Oldsen
 *
 * 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 de.gebatzens.sia;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Application;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Color;
import android.os.Build;
import android.preference.PreferenceManager;
import android.provider.CalendarContract;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatDelegate;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;

import com.google.firebase.messaging.FirebaseMessaging;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.TimeZone;

import de.gebatzens.sia.data.Exams;
import de.gebatzens.sia.data.Filter;
import de.gebatzens.sia.data.Subst;
import de.gebatzens.sia.data.Mensa;
import de.gebatzens.sia.data.News;
import de.gebatzens.sia.data.StaticData;
import de.gebatzens.sia.fragment.RemoteDataFragment;
import de.gebatzens.sia.fragment.SubstFragment;

public class SIAApp extends Application {

    public static final int UPDATE_DISABLE = 0, UPDATE_WLAN = 1, UPDATE_ALL = 2;
    public static SIAApp SIA_APP;

    public MainActivity activity;
    public SiaAPI api;
    public School school;

    public SharedPreferences preferences;

    public Filter.FilterList filters = new Filter.FilterList();
    public HashMap<String, String> subjects = new HashMap<>();

    public LifecycleHandler lifecycle;

    public WearDataProvider wearData;

    @Override
    public void onCreate() {
        super.onCreate();
        SIA_APP = this;
        api = new SiaAPI();
        preferences = PreferenceManager.getDefaultSharedPreferences(this);
        //SIABroadcast.createAlarm(this, true);
        filters = FilterActivity.loadFilter();
        loadSubjectMap();
        School.loadList();

        //copy school: this is required because SetupActivity might change the school in background which leads to inconsistent states.
        school = School.getBySID(preferences.getString("sid", null));
        if (school != null) {
            school = new School(school);
        }

        loadSavedData();
        lifecycle = new LifecycleHandler();
        registerActivityLifecycleCallbacks(lifecycle);

        //1.3 upgrade
        if (preferences.contains("notification_led")) {
            preferences.edit()
                    .putString("notification_led_color",
                            preferences.getBoolean("notification_led", true) ? "#2196F3" : "#000000")
                    .remove("notification_led").apply();
        }

        if (school != null) {
            FirebaseMessaging.getInstance().subscribeToTopic("sia_sid_" + school.sid);
        }

        FirebaseMessaging.getInstance().subscribeToTopic("news");

        wearData = new WearDataProvider();
        wearData.updateMainFilters(filters.including);

    }

    /**
     * Loads saved data (if present) for each fragment
     */
    private void loadSavedData() {
        if (school != null) {
            for (FragmentData frag : school.fragments) {

                RemoteDataFragment.RemoteData rd = null;

                switch (frag.type) {
                case PLAN:
                    rd = new Subst.GGPlans();
                    break;
                case EXAMS:
                    rd = new Exams();
                    break;
                case NEWS:
                    rd = new News();
                    break;
                case MENSA:
                    rd = new Mensa();
                    break;
                case PDF:
                    rd = new StaticData();
                    ((StaticData) rd).name = frag.params;
                    break;
                }

                if (!rd.load())
                    rd = null;

                frag.setData(rd);
            }
        }

    }

    private void loadSubjectMap() {
        subjects.clear();
        String[] array = getResources().getStringArray(R.array.subjects);
        for (String s : array) {
            String[] parts = s.split("\\|");
            String value = parts[parts.length - 1];
            for (int i = 0; i < parts.length - 1; i++) {
                subjects.put(parts[i], value);
            }
        }
    }

    public void createNotification(int icon, String title, String message, Intent intent, int id,
            String... strings) {
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this).setSmallIcon(icon)
                .setContentTitle(title).setContentText(message);
        if (strings.length > 1) {
            NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
            inboxStyle.setBigContentTitle(strings[0]);

            boolean b = true;
            for (String s : strings) {
                if (!b) {
                    inboxStyle.addLine(s);
                }
                b = false;
            }

            mBuilder.setStyle(inboxStyle);
        }
        mBuilder.setColor(SIAApp.SIA_APP.school.getDarkColor());
        if (Color.parseColor(getLedColor()) != Color.BLACK) {
            mBuilder.setLights(Color.parseColor(getLedColor()), 1000, 1000);
        }

        String vibration = preferences.getString("vibration", "off");
        switch (vibration) {
        case "short":
            mBuilder.setVibrate(new long[] { 0, 500 });
            break;
        case "default":
            mBuilder.setVibrate(new long[] { 0, 200, 200, 200, 200, 200 });
            break;
        case "long":
            mBuilder.setVibrate(new long[] { 0, 200, 100, 400, 200, 800, 300, 1000, 1200, 200 });
            break;
        }

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(MainActivity.class);
        stackBuilder.addNextIntent(intent);
        PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(resultPendingIntent);
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(
                Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(id, mBuilder.build());
    }

    public long getCalendarId() {
        //TODO select default calendar and try catch

        boolean hasPermission = ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED;

        if (!hasPermission && lifecycle.isAppInForeground()) {
            ActivityCompat.requestPermissions(activity,
                    new String[] { Manifest.permission.WRITE_CALENDAR, Manifest.permission.READ_CALENDAR }, 1);
            return -2;
        } else if (hasPermission) {
            String[] projection = new String[] { CalendarContract.Calendars._ID, CalendarContract.Calendars.NAME };
            Cursor cursor = getContentResolver().query(CalendarContract.Calendars.CONTENT_URI, projection, null,
                    null, null);
            if (cursor.moveToFirst()) {
                long id = cursor.getLong(0);
                cursor.close();
                return id;
            }
        }

        Log.w("ggvp", "No calendar available");
        return -1;

    }

    @SuppressWarnings("MissingPermission")
    public void addToCalendar(long calId, Date date, String title) {
        //TODO getTime should be enough
        long start = date.getTime() + 1000 * 60 * 60 * 6;
        ContentValues values = new ContentValues();
        values.put(CalendarContract.Events.DTSTART, start);
        values.put(CalendarContract.Events.DTEND, start);
        values.put(CalendarContract.Events.CALENDAR_ID, calId);
        values.put(CalendarContract.Events.ACCESS_LEVEL, CalendarContract.Events.ACCESS_DEFAULT);
        values.put(CalendarContract.Events.ALL_DAY, 1);
        values.put(CalendarContract.Events.TITLE, title);
        values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
        getContentResolver().insert(CalendarContract.Events.CONTENT_URI, values).getLastPathSegment();
    }

    public int translateUpdateType(String s) {
        switch (s) {
        case "disable":
            return UPDATE_DISABLE;
        case "wifi":
            return UPDATE_WLAN;
        case "all":
            return UPDATE_ALL;
        }
        return UPDATE_DISABLE;
    }

    public int getUpdateType() {
        if (preferences.getBoolean("notifications", true))
            return translateUpdateType(preferences.getString("background_updates", "all"));
        else
            return UPDATE_DISABLE;
    }

    public int getFragmentIndex() {
        return preferences.getInt("fragindex", 0);
    }

    public void setFragmentIndex(int index) {
        preferences.edit().putInt("fragindex", index).apply();
    }

    public String getLedColor() {
        return preferences.getString("notification_led_color", "#2196F3");
    }

    public void setLedColor(String ledColor) {
        preferences.edit().putString("notification_led_color", ledColor).apply();
    }

    public String getCustomThemeName() {
        return preferences.getString("customTheme", null);
    }

    public void setCustomThemeName(String customTheme) {
        preferences.edit().putString("customTheme", customTheme).apply();
    }

    public int getThemeMode() {
        return preferences.getInt("themeMode", AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
    }

    public void setThemeMode(int e) {
        preferences.edit().putInt("themeMode", e).apply();
        AppCompatDelegate.setDefaultNightMode(e);
    }

    public void setSchool(String sid) {
        preferences.edit().putString("sid", sid).apply();
        if (sid == null)
            return;

        School b = school;
        school = School.getBySID(sid);
        if (school != null) {
            school = new School(school);
        }

        if (activity != null && b != null && !b.equals(school)) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    activity.recreate();
                }
            });

        }

    }

    public String getCurrentThemeName() {
        String s = getCustomThemeName();
        return s == null ? school.themeName : s;
    }

    public void refreshAsync(final Runnable finished, final boolean updateFragments, final FragmentData frag) {
        new Thread() {
            @Override
            public void run() {
                if (activity != null) {
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            activity.resetShareToolbar();
                        }
                    });
                }

                boolean update = false;
                switch (frag.type) {
                case PLAN:
                    Subst.GGPlans oldPlans = (Subst.GGPlans) frag.getData();
                    final Subst.GGPlans plans = api.getPlans(updateFragments);
                    frag.setData(plans);
                    if (plans.throwable == null)
                        plans.save();

                    if (activity != null && (oldPlans == null || plans.size() != oldPlans.size())) {
                        update = true;
                    } else if (updateFragments) {
                        update = oldPlans.shouldRecreateView(plans);

                    }

                    if (activity != null) {
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Fragment frag = activity.mContent;
                                if (frag instanceof SubstFragment)
                                    ((SubstFragment) frag).updateTime(plans.loadDate);
                            }
                        });

                    }

                    break;
                case NEWS:
                    News on = (News) frag.getData();
                    News news = api.getNews(updateFragments);
                    frag.setData(news);
                    if (news.throwable == null)
                        on.save();
                    update = on == null || !on.equals(news);
                    break;
                case MENSA:
                    Mensa om = (Mensa) frag.getData();
                    Mensa mensa = api.getMensa(updateFragments);
                    frag.setData(mensa);
                    if (mensa.throwable == null)
                        mensa.save();
                    update = om == null || !om.equals(mensa);
                    break;
                case EXAMS:
                    Exams newExams = api.getExams(updateFragments);
                    Exams exams = (Exams) frag.getData();
                    if (exams != null) {
                        exams.reuseSelected(newExams);
                    }
                    exams = newExams;
                    frag.setData(exams);
                    if (exams.throwable == null)
                        exams.save();
                    update = true;
                    break;
                case PDF:
                    StaticData od = (StaticData) frag.getData();
                    StaticData data = api.downloadStaticFile(frag.getParams(), updateFragments);
                    frag.setData(data);
                    if (data.throwable == null)
                        data.save();

                    update = data.throwable == null;
                    break;
                }

                if (activity != null && updateFragments && update)
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            activity.mContent.updateFragment();
                        }
                    });

                if (activity != null && finished != null)
                    activity.runOnUiThread(finished);
            }
        }.start();
    }

    public String getSeasonTheme() {
        int m = Calendar.getInstance().get(Calendar.MONTH);
        switch (m) {
        case Calendar.OCTOBER:
        case Calendar.NOVEMBER:
        case Calendar.DECEMBER:
        case Calendar.JANUARY:
        case Calendar.FEBRUARY:
        case Calendar.MARCH:
            return "Winter";
        default:
            return "Summer";
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public void setStatusBarColorTransparent(Window w) {
        w.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        w.setStatusBarColor(ContextCompat.getColor(this, R.color.transparent));
    }

    public static String deleteNonAlphanumeric(String s) {
        return s.replaceAll("\\W", "").toLowerCase();
    }

}