I am posting this question here after it having been determined to be "off-topic" for stackoverflow, and "too hypothetical" for codereview.

I am experimenting with different singleton-style design patterns for an app component having to do with app-wide sound effects and speech.

My theory is that while often frowned upon, by making these types of objects global/static/singleton-like will have advantages such as:

- Memory use being more stable/constant with a predictable baseline, making OOM errors easier to foresee.
- Expensive initializations within these objects (such as TTS engines and large audio buffers) will happen once only.
- Sounds are not cut short by activity transitions.
- Memory leaks caused by constant and laggy de-and-re-initializations of objects (for example the Google TTS engine) can be avoided by having a single global instance.

My question is: "Is the design pattern shown in my code sample feasible / acceptable / solid?" ... and by this I don't mean in your opinion -- I mean is there someone out there with more experience than me (not hard to find) that can see some reason why this code would be bug-prone?

I have mainly used the help of [this article][1].

manifest:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.boober.speechsingletonsimplifiedunit">
    
        <application
            android:name="App"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity"
                >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name=".SettingsActivity"
                >
    
            </activity>
        </application>
    
        <!-- android:screenOrientation="portrait" -->
    </manifest>

Application Class:

    package com.example.boober.speechsingletonsimplifiedunit;
    
    import android.app.Application;
    import android.content.Context;
    import android.util.Log;
    
    import com.squareup.leakcanary.LeakCanary;
    
    public class App extends Application {
    
        private static Context appContext;
    
        public static GodOfSpeechSingleton GOSS;
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            // BEGIN LEAK CANARY CODE:
            if (LeakCanary.isInAnalyzerProcess(this)) {
                // This process is dedicated to LeakCanary for heap analysis.
                // You should not init your app in this process.
                return;
            }
            LeakCanary.install(this);
            // END LEAK CANARY CODE, PROCEED...
    
            Log.i("XXX", "App.onCreate() called.");
            appContext = this;
            GOSS = new GodOfSpeechSingleton();
        }
    
        public static Context getAppContext() {
            return appContext;
        }
    
    }

The "GOSS":

    package com.example.boober.speechsingletonsimplifiedunit;
    
    import android.speech.tts.TextToSpeech;
    import android.util.Log;
    
    import java.util.HashMap;
    import java.util.Locale;
    import java.util.Random;
    
    public class GodOfSpeechSingleton { // aka "the GOSS"
    
        private boolean thisClassHasBeenInitAlready = false;
        TextToSpeech tts1;
        boolean tts1IsInit;
    
        public GodOfSpeechSingleton() {
            Log.i("XXX", "GOSS constructor called.");
        }
    
        // This method body was created/moved (execution delayed) from the constructor to here
        // because when constructor was called from Application.onCreate(),
        // the code "android.content.Context.getPackageManager()" inside the TTS
        // causes a null pointer exception.
        public void initFromMainActivity(String caller) {
            if (!caller.equals("MainActivity")) { return; }
            if (thisClassHasBeenInitAlready) {
                Log.i("XXX", "GOSS init already.");
                return; }
            thisClassHasBeenInitAlready = true;
    
            tts1 = new TextToSpeech(App.getAppContext(), new TextToSpeech.OnInitListener() {
                @Override
                public void onInit(int i) {
                    tts1IsInit = true;
                }
            }, "com.google.android.tts");
    
        }
    
        public void speak(String stringToSpeak, Locale localeToUseForThisUtterance) {
            if (!tts1IsInit) {
                Log.i("XXX", "speak() called, but tts1 not init yet!");
                return;
            }
            tts1.setLanguage(localeToUseForThisUtterance);
            tts1.speak(stringToSpeak, TextToSpeech.QUEUE_FLUSH,  null);
        }
    
    }

MainActivity:

    package com.example.boober.speechsingletonsimplifiedunit;
    
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    
    import java.util.Locale;
    
    public class MainActivity extends AppCompatActivity {
    
        // LIFECYCLE
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Log.i("XXX", "Main.onCreate() called.");
            App.GOSS.initFromMainActivity("MainActivity");
    
        }
    
        @Override
        protected void onDestroy() {
            Log.i("XXX", "Main.onDestroy() called.");
            super.onDestroy();
        }
    
    
        // BUTTON PRESSES
        public void settingsButtonPressed(View ignored) {
            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
        }
    
        public void speakButtonPressed(View ignored) {
            App.GOSS.speak("you are in the main activity!",new Locale("en"));
        }
    
    
    }

SettingsActivity:

    package com.example.boober.speechsingletonsimplifiedunit;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    
    import java.util.Locale;
    
    public class SettingsActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_settings);
    
        }
    
        // BUTTON PRESSES
        public void speakButtonPressed(View ignored) {
            App.GOSS.speak("you are in the settings activity!", new Locale("en"));
        }
    
    }

  [1]: https://nfrolov.wordpress.com/2014/07/12/android-using-context-statically-and-in-singletons/