0

I'm currently working on an app that is supposed to replace the devices whole UI. Therefore I'm using <category android:name="android.intent.category.HOME"/> in order to call it whenever I press the home button, replacing the devices launcher. This app should always have just one instance of its MainActivity running and when the home button is pressed, it shouldn't start a new Activity but resume to the existing one.

I've played with the different launchModes a bit and it looks like singleInstance is by best bet. But for some reason the home button gets rendered useless and I'm unabled to return the launcher. Sporadically sometimes it works and when it works, it works just like I've intended it to be.

standard launchmode starts a new instance of the launcher whenever I press the home button, which leads to several issues, since the launcher is supposed to do some things, like opening other apps and resuming to the launcher, whenever the MainActivity is created. This leads to a loop: launcher starts apps -> resumes to launcher by creating a new Activity -> launcher starts apps... That behaviour could be fixed somehow, but still it doesn't solve the root of its cause

singleTop does the same.

singleTask does the same.

singleInstance retains the Activity and whenever I press the home button, the launcher just resumes with its last state. BUT for some reason, the home button sometimes doesn't work. Meaning that the App won't come to the foreground. Even closing all apps doesn't return me to the launcher -> the device kind of gets bricked since you can't do anything

Edit: Couldn't really find a solution. I'm pretty sure it's a bug on googles side. I couldn't find the cause, but I've settled with a workaround.

I've created a new activitiy called "LoadingActivity" which literally only loads the activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_loading);
}

@Override
protected void onResume() {
    super.onResume();
    startActivity(new Intent(LoadingActivity.this,MainActivity.class));
}

The LoadingActivitys launchMode is "standard" while the "MainActivity" remains "singleInstance". This fixes everything for now. If I find a better solution in the future, I can simply delete the Activity and make the MainActivity the main activity again.

Edit2, per request, here's the manifest prior to the workaround:

<?xml version="1.0" encoding="utf-8"?>
<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="[package]">
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    <uses-permission android:name="android.permission.READ_LOGS" tools:ignore="ProtectedPermissions" />
    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/logo"
        android:label="@string/app_name"
        android:roundIcon="@drawable/logo"
        android:supportsRtl="false"
        android:requestLegacyExternalStorage="true"
        android:theme="@style/AppTheme">
        <activity
          android:name="[package].MainActivity"
          android:launchMode="singleInstance"
          android:excludeFromRecents="true"
          android:alwaysRetainTaskState="true"
          android:configChanges="uiMode|fontScale">
          <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>


        <service android:name=".MediaServiceBrowser">
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_BUTTON" />
                <action android:name="android.media.AUDIO_BECOMING_NOISY" />
                <action android:name="android.media.browse.MediaBrowserService" />
            </intent-filter>
        </service>

        <service android:name=".LocationService" />

        <service
            android:name=".NotificationListener"
            android:enabled="true"
            android:exported="true" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
            <intent-filter>
            <action android:name="android.service.notification.NotificationListenerService" />
            </intent-filter>
        </service>

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                 android:resource="@xml/provider_paths" />
        </provider>
    </application>

</manifest>
Mumbira
  • 1
  • 1
  • Strange. For a HOME-screen replacement, `singleInstance` is the correct launch mode. Please edit your question and post your manifest. – David Wasser Apr 01 '22 at 14:42
  • Was a little hard to format, but got it. – Mumbira Apr 02 '22 at 08:31
  • Sounds super strange. The only thing that I can think of is that the MainActivity is stuck (ie: the main/UI thread is somehow blocked. This would make it appear that your app is not being brought forward. You may want to attach a debugger and get a thread dump of the process when it is in this state and check if your main thread is blocked or if you have a deadlock somewhere. – David Wasser Apr 02 '22 at 08:56
  • It works perfectly fine, if I use something to manually bring the MainActivity back. Like making a simple handler that posts delayed and go out of the app. Home button doesn't work, but after the chosen time the MainActivity comes back. (and resumes from last state, doesn't restart) So I don't think it's stuck in a weird way. Only the home button is effected. And it looks like the system isn't abled to resume the app either. If I close all apps, I get a blackscreen, normally android should automatically restart the default launcher app, but it can't for some reason. – Mumbira Apr 03 '22 at 03:53

0 Answers0