0

I am working on an well-being app that shuts your phone up for a given period of time (eg. 30min, 1hr, 1.5hr)

In this state user can only see a screen with remaining time on it and cannot

  • Access QS tiles
  • Access Volume panel
  • Navigate out of the Activity

something similar to Oneplus Zen mode

things i have thought of for doing this

  • Killing the SystemUI process.(by doing so the QS and volume panel would be dealt with most probably, maybe need root for that tho? also SystemUI automatically restarts itself, quite stubborn)

  • Making app a launcher Dynamically?(technically you can't navigate out of a launcher and on reboot you come back to it)

how can I get around accomplishing this? any ideas?

Brijraj
  • 33
  • 1
  • 5

1 Answers1

1

Making application the default launcher of the phone is more practical solution to what you're trying to achieve. I've done this previously in a Flutter application which was going to be installed on kiosk devices to get orders from customers and it worked perfectly. It's a bit tricky to make it work and there's lots of things to do. Here is a list of things I did back then:

  1. Use FLAG_SHOW_WHEN_LOCKED flag to the window to bypass the lock screen.

  2. Inside of onResume add FLAG_FULLSCREEN flags to hide the status bar.

  3. Make your MainActivity launcher by adding LAUNCHER category to in AndroidManifest.xml. Also you can add other attributes I used (Search for them if you don't know what are they supposed to do).

    <activity
        android:name=".MainActivity"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:excludeFromRecents="true"
        android:hardwareAccelerated="true"
        android:launchMode="singleInstance"
        android:showOnLockScreen="true"
        android:showWhenLocked="true"
        android:theme="@style/LaunchTheme"
        android:turnScreenOn="true"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
    
            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.HOME" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
    
  4. Listen for window focus changes in your MainActivity and bring your application to front if it lost the focus.

    private fun moveToFront() {
      val closeDialog = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
      sendBroadcast(closeDialog)
      (activity.applicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager)
              .moveTaskToFront(activity.taskId, ActivityManager.MOVE_TASK_WITH_HOME)
      window.setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
    
    override fun onWindowFocusChanged(hasFocus: Boolean) {
      super.onWindowFocusChanged(hasFocus)
      if (!hasFocus) {
        moveToFront()
      }
    }
    
  5. I was also checking if my application is the default launcher.

    private fun isAppDefault(): Boolean {
      val intent = Intent(Intent.ACTION_MAIN)
      intent.addCategory(Intent.CATEGORY_HOME)
      val res: ResolveInfo = packageManager.resolveActivity(intent, 0)
      return res.activityInfo != null && (packageName
            == res.activityInfo.packageName)
    }
    
  6. And you're gonna need to communicate between Flutter and the platform using MethodChannel to enable and disable force mode and get the state of the application.

Amir_P
  • 8,322
  • 5
  • 43
  • 92
  • I agree, launcher seems to be the answer, any ideas on how can I make the app a launcher dynamically? for i.e. when user sets a timer the app would make itself a default launcher and step away as soon as the timer completes, I'm guessing I would have to give the app permission to edit system settings. – Brijraj Oct 12 '21 at 09:22
  • There is no way you can make your app the default launcher without user consent. But you can show a prompt based on the result of `isAppDefault` for user to remove if there is another default launcher and then you can start an `Intent` to prompt the user for choosing default launcher. check this: https://stackoverflow.com/questions/27786828/how-to-bring-up-the-set-default-launcher-prompt @Brijraj – Amir_P Oct 12 '21 at 12:46