I'm having a problem where multiple instances of an activity are present in the backstack.
e.g.
Stack: A > B > C
Press home and use some other apps then relaunch my app
Stack: A > B > C > A
I would expect my app to resume with activity C, which in most cases it does, but occasionally it resumes with activity A and then when i press back it goes to activity C.
I know this problem is not caused by android killing my app as if this was the case it would resume with activity A as the root.
I have tried altering the launchMode attribute to singleTask and singleInstance but this results in activity A being resumed as the root, which is not the behaviour that i want, i want it to go back to the previously viewed activity with the backstack intact (I understand this is not always possible if the OS kills the app, which is fine).
I dont believe setting the launchMode attribute to singleTop would be useful either as this would prevent A > A situations but not A > B > A or A > B > C > A etc
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package=""
android:versionCode="1"
android:versionName="1.0"
android:installLocation="auto"
>
<application android:label="#string/app_name" android:debuggable="false"
android:name=""
android:icon="#drawable/icon" android:theme="#style/CustomTheme"
android:targetSdkVersion="8" android:minSdkVersion="4">
<activity android:name=".activity.A"
android:windowSoftInputMode="stateUnchanged|adjustPan"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activity.B"
android:screenOrientation="portrait"/>
<activity android:name=".activity.C"
android:screenOrientation="portrait" />
<activity android:name=".activity.D"
android:screenOrientation="landscape"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen" />
<activity android:name=".activity.E"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen" />
<service android:name=".service.S" />
<uses-library android:name="com.google.android.maps" />
</application>
<uses-sdk android:minSdkVersion="4"
android:targetSdkVersion="8"
/>
<supports-screens
android:largeScreens="false"
android:normalScreens="true"
android:smallScreens="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Any advice would be greatly appreciated
David
The behavior you're looking for is what singleTask was meant for.
The problem, then, is why resuming your app pops back to the root. If it's just due to the usual way the system works (e.g., 30-minute timeout), and you really want to prevent that, you could use android:alwaysRetainTaskState="true".
Related
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>
I am moving from SDK version 30 to 31 and I add android:exported in intent-filter but still I am getting this error:
Merging Errors: Error: android:exported needs to be explicitly specified for . Apps targeting Android 12 and higher are required to specify an explicit value for android:exported when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
<?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="com.mycompany.webviewapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<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">
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
<activity android:name="com.mycompany.webviewapp.SplashActivity"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.mycompany.webviewapp.MainActivity"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.VIEW"></action>
</intent-filter>
</activity>
<service android:name="com.mycompany.webviewapp.FCM.MyFirebaseMessagingService">
</service>
<meta-data android:name="applovin.sdk.key"
android:value="sdk api here"/>
</application>
</manifest>
The reason is because some of the dependency libraries that you're using have elements which do not have "android:exported" attribute.
You need to do this:
Lower the version in your gradle to 30 and sync and build.
Go to your AndroidManifest.xml file and click on "Merged Manifest".
Find items such as Activity, Receiver, Service, etc that don't have "android:exported" attribute.
Then add them to your AndroidManifest.xml file in this way.
<activity
android:name="SomeActivity"
android:exported="false"
tools:node="merge"
tools:replace="android:exported" />
Now you can increase your version to 31.
I resolve my issue. I just check the merged manifest and look for reciver. In onesignal, I found out reciver with intent filter defined without android:exported. I just add android:exported="false".
i used webview to create app and implemented deep linking like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ariagp.myapplication">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
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>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="mysitename.com" />
</intent-filter>
</activity>
</application>
</manifest>
it will asking my for open with my application before open the links, but the problem is:
two applications will open in the phone task manager (the application does not open in the previous application which is running):
what is the solution?
Add android:launchMode="singleTask" in declared activity in AndroidManifest.xml.
And then, in your activity, you should override onNewIntent() method and you will get arguments there.
Ok, so you don't actually have a problem here.
This is just how deep links work. If you open one in a certain app, the deep link will open your app but in the same window the deep link was originally in.
Your app will have two instances in a way.
You could go to you web brower app and click share and any app that pops up. They all open in the web browsing app window. So there is nothing to worry about. I had the same problem myself before I realised that it is just how things work.
Some apps are just verified to open other apps if they implement the browsability.
Add android:launchMode="singleTask" in declared activity in AndroidManifest.xml.
And then, in your activity, you should override onNewIntent() method and call mNavController.handleDeepLink(intent) there.
It is worth mentioning that you are now able to get your arguments using, private val args: XFragmentArgs by navArgs()in your fragment.
I really have very big problem with my project. When my phone is connected to the computer via USB cable, everything works fine, but when the phone is disconnected the app doesn't work as I expected. So, I have already tried with android.os.Debug.waitForDebugger(), I removed the all #SuppressLint("NewApi"), also USB debugger is activated on my phone, but I think the problem can be in the Manifest file. Can someone tell me, what can be done in this case?
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androproject"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="#drawable/fritz_logo"
android:label="#string/app_name"
android:theme="#style/AppTheme"
>
<activity
android:windowSoftInputMode="adjustPan"
android:name="com.example.androproject.MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/ThemeWithCorners"
android:configChanges="keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.androproject.RegisterDnsAndUser"
android:screenOrientation="portrait"
android:theme="#style/ThemeWithCorners"
android:configChanges="keyboardHidden|orientation"/>
<activity
android:name="com.example.androproject.MenuApp"
android:screenOrientation="portrait"
android:theme="#style/ThemeWithCorners"
android:configChanges="keyboardHidden|orientation"/>
</application>
</manifest>
I am using the following, handler code. When I put 40000 ms, the app works, but when I put 60000 ms, my application doesn't work if the cable is disconnected.
handler.postDelayed(myRunnable = new Runnable(){
#Override
public void run() {
if(btnToggle.isChecked()){
btnToggle.setChecked(false);
btnToggleTimer.setChecked(false);
}else{
btnToggle.setChecked(true);
btnToggleTimer.setChecked(false);
}
}
}, min*60000);
Most likely you have enabled the "Stay awake"-mode in the Developer options in the settings menu. When you disconnect the phone from the charger it will go into sleep mode after a few seconds.
The solution is to either use a partial wake-lock using the PowerManager or (in the above case) use a PendingIntent and the AlarmManager to trigger a event at a later time.
as the title says, when the next line of code
android:screenOrientation="portrait"
is entered in my Manifest file then when I start my app and, for example, dragging the gallery app to it then its not activating the multi window feature which splits the screen... but just replace my app with the gallery app, meaning the gallery app takes all the screen instead of taking only half of it.
If I first open the gallery app and then dragging my app then its working fine.
Also if I remove the above line of code then its working fine.
This is my Manifest.xml file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.samsunmultiwindowstest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.samsunmultiwindowstest.MainActivity"
android:screenOrientation="portrait"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER"/>
</intent-filter>
</activity>
<uses-library android:required="false" android:name="com.sec.android.app.multiwindow"> </uses-library>
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632.0dip" />
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H" android:value="598.0dip" />
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_W" android:value="632.0dip" />
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H" android:value="598.0dip" />
</application>
how can I force portrait mode and get the multi window feature?
Thank you and sorry for my English.
Check out this Link Screen Orientation. It will help you understand different kinds of screen orientation. Also check this and this. will help you to enable multi window feature
I simply took out the size settings to solve my multiWindow issues.
IE: Remove these lines altogether.
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632.0dip" />
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H" android:value="598.0dip" />
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_W" android:value="632.0dip" />
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H" android:value="598.0dip" />