I have been trying deeplinking in a react-native application and trying to directly open a screen inside a navigator. I use react-native-deep-linking and react-navigation as libraries. Also nested navigators are used. Deeplinking works correctly except I have some problems with the android:launchMode property.
This is the results I get for each of the android:launchMode options.
android:launchMode="standard" - App opens using the deeplink but opens up an entirely new application.
android:launchMode="singleTask" - App opens using the deeplink. If I open the app using another link. App comes to the foreground but it directs to the previous link.
android:launchMode="singleTop" - App opens using the deeplink but opens up an entirely new application.
android:launchMode="singleInstance" - App opens using the deeplink but opens up an entirely new application.
If I remove the android:launchMode property, again the same thing happens as the "standard" mode because it is the default.
What option can I use to resolve this problem? Is there any #override that I can do inside the main activity?
Below is my AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<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"/>
<category android:name="android.intent.category.VIEW"/>
<data android:scheme="https" android:host="*.myapplive.com" android:pathPrefix="/"/>
<data android:scheme="https" android:host="*.myapp.com" android:pathPrefix="/"/>
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
</application>
Not sure if still relevant but may help someone in future.
The reason is that when activity is in any mode other than standard, re-opening the app from the background will not replace the original intent used to launch the app from the killed state. Instead, those new intents will be directed to the onNewIntent(Intent intent) method. There, you can call setIntent(Intent intent) in order to replace activity's intent with the new one.
You can override this method in your MainActivity. (Note that when overriding this method in React I had to make it public and not protected as I would usually do in Android. Not sure why yet)
Read more here - https://developer.android.com/reference/android/app/Activity#onNewIntent(android.content.Intent)
MY PLIGHT EXPLAINED
I cannot figure out or find out to stop my Activity from launching itself. This is necessary as I am making a dir manager that has intent filter to open any file, in attempt to easily locate and rename it. For instance clicking a file from notification to be opened by my app for renaming.
MY PLIGHT SUMMARIESED
But it makes no sense to run this intent if you are already in my app. Thus I want to programatically stop my app from being a choice in this case.
MY TRIES FOR SOLUTION
I have tried many stuff. Google, android reference on ActivityInfo. I even tried creating my own activity chooser dialog. Which doesnt work 100% accurately. If it did I could simply omit my activity from the list.
I humbly seek assistance.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="jav.android.dir_mgr">
<uses-sdk android:minSdkVersion="12" android:targetSdkVersion="27" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
android:icon="#mipmap/app_icon"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".DirectoryExplorer"
android:screenOrientation="portrait" >
<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" />
<data android:scheme="file" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
<activity
android:name=".SelectionWindow"
android:screenOrientation="portrait"
android:label="Selection Window"
android:allowEmbedded="true">
<intent-filter>
. <action android:name="jav.android.dir_mgr.SELECT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
You can use EXTRA_EXCLUDE_COMPONENTS to exclude your own application from the list shown to the user. See the documentation which states:
You can exclude specific targets by providing
Intent.EXTRA_EXCLUDE_COMPONENTS. This is to be used only to remove
targets you have control over. A common use case is to hide your app’s
share targets when your users share from within your app as their
intent is likely to share outside your app.
Add Intent.EXTRA_EXCLUDE_COMPONENTS to your intent after calling
Intent.createChooser()
So, from what I understand, you need a way to check if your app is in focus or not. If that's so, try using ActivityManager.getRunningAppProcesses() which will return a list of application processes that are running on the device.
From there you can iterate through processes that are running on the device and check if your app is listed there and that it's of RunningAppProcessInfo.IMPORTANCE_FOREGROUND.
EDIT: I assume you are using pending intents, then you won't be able to check if your app is already running in the above way. Try using a "launch intent" for your app as explained in this answer.
I hope I understood your plight correctly.
One way to solve your problem is to programmatically unregister your activity from listening to a certain intent-filter value. So let's say you have an activity declared as:
<activity android:name=".FileHandlerActivity">
<intent-filter>
<action android:name="you-file-rename-action-name-here"/>
</intent-filter>
</activity>
Do this in your app:
PackageManager pm = getApplicationContext().getPackageManager();
ComponentName component = new ComponentName(getPackageName(),
getPackageName()+".FileHandlerActivity");
pm.setComponentEnabledSetting(component,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
Please let me know if this works.
I have two apps. From the first, I want to launch the second one by deep linking. It works but the problem is that the second one starts inside the first one. I would like to start the second one in a new instance.
The code of the first app to open the second app:
String uri = "deeplinkTestTom://token/123456";
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
startActivity(intent);
The manifest of the second app:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data
android:scheme="deeplinkTestTom" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
</application>
When I try to launch Facebook app from my first app (String uri = "facebook://facebook.com/inbox";), it launch facebook in a new app and not inside my first app. So I suppose that something is missig in the manifest of my second app, but I can't find what.
What should I do ?
I believe you're talking about new Task instead of "new app".
Read Tasks and Back Stack
You need to use Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) to start an Activity in a new Task.
For your case, use
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
I run my application "A" normally with the launch icon in the "Applications" menu.
I press the home button, so my application "A" is still running on my phone.
Now I browse my files presents in my phone, and I use the share action to share this file with my application "A".
The file is sharing perfectly, but instead of using the instance of my application already opened, it opens a new instance of my application "A".
If I quit this new instance, the first instance is still running and it's a problem concerning the security goal of my application.
I try to use the FLAG_ACTIVITY_CLEAR_TOP to use the activity in the first instance, but it doesn't work because it isn't the same application which is launched by the OS.
Is there a way to do this ? And if yes can you give me some hints or some leads to follow ?
My manifest :
<?xml version="1.0" encoding="utf-8"?>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar" >
<activity android:name=".SplashScreenActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ExplorerActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="#android:style/Theme.Light.NoTitleBar" >
</activity>
<activity
android:name=".ChooseDialogActivity"
android:theme="#android:style/Theme.Translucent.NoTitleBar" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
Here is my manifest. Usual process : SplashScreenActivity -> ExplorerActivity
Share process : ChooseDialogActivity -> ExplorerActivity
What I want, it's that the second ExplorerActivity has to be the same that the first ExplorerActivity if this activity already exists.
Please don't use launchMode="singleInstance". This is not what you want. singleInstance is only for HOME-screens and similar apps.
Try instead to use Intent.FLAG_ACTIVITY_NEW_TASK when sharing. This will separate your application from the files-browsing application and may get the behaviour you want. You may also need to add FLAG_ACTIVIY_CLEAR_TOP as well, depending on how you've programmed your app.
EDIT
When you launch ExplorerActivity from ChooserActivity, do this (or something similar):
Intent intent = new Intent(this, ChooserActivity.class);
intent.addFlags(Intent.ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
If there is already a task running that contains the ChooserActivity, this should bring that task to the foreground instead of creating a new instace of ChooserActivity.
use the launchmode this will keep one instance from your main activity so make this change for the home activity .
<activity ..
...
..
android:launchMode="singleInstance" />
try android:launchMode="singleInstance"
I am writing a simple program of Android, and getting these no errors, I don't know what they are. My program is right, but showing not output.
I think it is because of these two lines:
[2005-01-06 19:56:38 - my_Android] No Launcher activity found!
[2005-01-06 19:56:38 - my_Android] The launch will only sync the application package on the device!
Here's an example from AndroidManifest.xml. You need to specify the MAIN and LAUNCHER in the intent filter for the activity you want to start on launch
<application android:label="#string/app_name" android:icon="#drawable/icon">
<activity android:name="ExampleActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Multiple action tags in a single intent-filter tag will also cause the same error.
Like Gusdor said above, "Multiple action tags in a single intent-filter tag will also cause the same error." (Give him the credit! I could just kiss Gusdor for this!)
I didn't find any docs for this fact!
I had added a new (USB) action and being clever, I lumped it in the same intent-filter. And it broke the launch.
Like Gusdor said, one intent filter, one action!
Apparently each action should go in its own intent filter.
It should look like this...
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
When I did this, WAZOO! it worked!
Do you have an activity set up the be the launched activity when the application starts?
This is done in your Manifest.xml file, something like:
<activity android:name=".Main" android:label="#string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Check your manifest.xml. Make sure you have the category LAUNCHER there.
<activity android:name=".myActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
It means you didn't specify an Activity for Android to launch as the default when the app opens from the launcher. You have to add an Intent Filter in the Manifest for the Activity you would like to act as the default when the app is being launched.
Read http://developer.android.com/guide/topics/intents/intents-filters.html#ccases for more details.
I fixed the problem by adding activity block in the application tag. I created the project using wizard, I don't know why my AdroidManifest.xml file was not containing application block? I added the application block:
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".ToDoListActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
And I get the desired output on the emulator.
As has been pointed out, this error is likely caused by a missing or incorrect intent-filter.
I would just like to add that this error also shows up if you set android:exported="false" on your launcher activity (in the manifest).
I had this same problem and it turns out I had a '\' instead of a '/' in the xml tag. It still gave the same error but just due to a syntax problem.
If you are using the standard eclipse IDE provided by google for Android development, you can check the "Launcher Activity" check-box while creating a new Activity. Please find below:
In Eclipse when can do this:
But it is preferable make the corresponding changes inside the Android manifest file.
You missed in specifying the intent filter elements in your manifest file.Manifest file is:
<application android:label="#string/app_name" android:icon="#drawable/icon">
<activity android:name="Your Activity Name"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Add and check this correctly. Hope this will help..
Manifest is case sensitive, so please compare this lines for any case mismatch especially the word MAIN in:
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
You can add launcher to activity in eclipse manifest visual editor:
MAIN will decide the first activity that will used when the application will start.
Launcher will add application in the application dashboard.
If you have them already and you are still getting the error message but maybe its because you might be using more than more category or action in an intent-filter. In an intent filter there can only be one such tag. To add another category, put it in another intent filter, like the following
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!--
TODO - Add necessary intent filter information so that this
Activity will accept Intents with the
action "android.intent.action.VIEW" and with an "http"
schemed URL
-->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="http" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
just add this to your aplication tag in AndroidManifest.xml file
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
and also edit the uses-sdk tag from android:targetSdkVersion="16" to 17
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
You have not included Launcher intent filter in activity you want to appear first, so it does not know which activity to start when application launches, for this tell the system by including launcher filter intent in manifest.xml