I have some problems with intent filter of dynamic link.
I use Firebase Dynamic Link for deferred deep linking, so I add intent filter in my activity at manifest file.
I already use custom scheme and add dynamic link scheme after my custom scheme in same activity.
It works fine when I launch app first time and keep that first instance.
In that time, when I click dynamic link at samsung note app, my app and chrome browser are listed in chooser intent.
But after some hours without using my app so system restart my app when my app bring to foreground, my dynamic deep link intent filter not working.
In this time, when I click dynamic link at samsung note app(I think it works with implicit intent), my app doesn't listed in chooser intent and also can't receive intent filter of dynamic link.
But in same time, my custom scheme deep link working well.
Only dynamic deep link scheme not working.
And also something strange one is that it only happens in my product flavor's release mode app.
I have another flavor for develop so that flavor package name is my origin package name + ".develop" and it's debug mode.
I do same thing in same time, my develop app's dynamic deep link intent filter working fine but only my product app doesn't work.
Is this happen relative with release mode or flavor? Or I just did something wrong with adding intent filter? I really don't know why this happen.
+) I test it at real devices, Galaxy Note8(Android 9, Pie) and Galaxy A32(Android 11).
manifest file of activity:
<activity
android:name=".xxx.XxxActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<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" />
<!-- custom scheme -->
<data
android:host="xxx"
android:scheme="xxx" />
</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"/>
<!-- Dynamic link -->
<data
android:host="xxx.page.link"
android:scheme="https"/>
</intent-filter>
</activity>
I have added applinks to my app and have uploaded assetlinks.json file already to my domain. Using the App Link Support, clicking on Link and Verify gives me the following:
So far so good. Now when I install the app and filter IntentFilterIntentOp in Logcat, I am getting a completely random host being added to the list of my domains. The host name is string and I get the following error.
java.net.MalformedURLException: Input host is not valid.
My activity in android manifest looks like this:
<activity
android:name=".mainactivity.MainActivity"
android:launchMode="singleInstance">
<nav-graph android:value="#navigation/nav_host_main" />
<intent-filter android:autoVerify="true">
<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="my-url" />
</intent-filter>
</activity>
My question is where is the domain string coming from?
The logcat filter for IntentFilterIntentOp looks like this:
Verifying IntentFilter. verificationId:89 scheme:"https" hosts:"my-url string" package:"my-package". [CONTEXT service_id=244 ]
I figured out the problem.
I was trying to also include variables in deeplinks in the navigation component.
so my deeplink in the fragment looked like
<fragment
...
<deepLink
android:id="#+id/deepLink6"
app:uri="#string/deeplink_setpassword_verify_email" />
</fragment>
This was the place where Android took it as a string. So I had to write actual URLs here.
I am working on adding an OAuth flow to a Trello integration within my app. The idea is using deep linking to consume the response within the app itself (there is no server between the app and the database - I am using room).
I have everything working up to this point except the callback redirect portion, and it works on my real device, rather than the emulator.
This is the code that begins the OAuth flow.
val connection = object:CustomTabsServiceConnection() {
override fun onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) {
val builder = CustomTabsIntent.Builder()
val customTabsIntent = builder.build()
client.warmup(0)
var authUrl = "$TOKEN_URL?key=$API_KEY&scope=read&callback_method=fragment&return_url=${AuthenticationManager.HTTPS_REDIRECT_URL}&expiration=never&name=$NAME&integration=${integration.id}"
customTabsIntent.launchUrl(context, Uri.parse(authUrl))
}
override fun onServiceDisconnected(name: ComponentName?) {
}
}
bindCustomTabsService(context, "com.android.chrome", connection);
Manifest
<activity
android:name="com.myapp.MainActivity"
android:screenOrientation="sensor"
android:windowSoftInputMode="adjustPan"
android:launchMode="singleTop"
android:configChanges="uiMode">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="pomodoro" android:host="oauth.myapp.com"/>
<data android:scheme="https" android:host="myapp.com"/>
</intent-filter>
</activity>
At this point it is redirected to my webpage, which I verified on my real device redirects to my app (so it can consume the intent and get the necessary token). I am wondering if when I selected Always use for the chrome browser (when initially opening a webpage in the emulator), that this basically overrides my deep link? Is that possible? Also using a different scheme isn't possible, as Trello forces uses to use https/http as the trusted redirect/callback urls?
This is related to my misunderstanding of deeplinks vs AppLinks. I want to treat this more as an AppLink vs a deeplink, meaning the verification has already happened that this URL belongs to my app (via a file on my domain). For this verification to happen I need the verification file at the appropriate url, if it is not there - the verification cannot happen. Which happens for each host/scheme, and must verify all match.
The solution was to remove the scheme/host that isn't associated with the app/domain, to allow AutoVerify.
"Only if the system finds a matching Digital Asset Links file for all hosts in the manifest does it then establish your app as the default handler for the specified URL patterns." https://developer.android.com/training/app-links/verify-site-associations
After updating my manifest to the below it worked as expected, and redirected the OAuth flow as expected.
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="https" android:host="myapp.com"/>
</intent-filter>
I have this scheme testapp in my manifest as below
<!-- Branch URI Scheme -->
<intent-filter>
<data android:scheme="testapp" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
and same i have in branch dashboard setting in Android URI Scheme : testapp:// still i am getting this error.
specified in Branch dashboard doesn't match with the deep link intent in manifest file.
Note : Keys i have checked and it is correct.
For me, even after following the above, it did not work even after double verifying everyone. However, it worked after:
flutter clean
For me the solution was not to have :// in android scheme.
android:scheme="myappname"
Can anybody please guide me regarding how to launch my android application from the android browser?
Use an <intent-filter> with a <data> element. For example, to handle all links to twitter.com, you'd put this inside your <activity> in your AndroidManifest.xml:
<intent-filter>
<data android:scheme="http" android:host="twitter.com"/>
<action android:name="android.intent.action.VIEW" />
</intent-filter>
Then, when the user clicks on a link to twitter in the browser, they will be asked what application to use in order to complete the action: the browser or your application.
Of course, if you want to provide tight integration between your website and your app, you can define your own scheme:
<intent-filter>
<data android:scheme="my.special.scheme" />
<action android:name="android.intent.action.VIEW" />
</intent-filter>
Then, in your web app you can put links like:
<a href="my.special.scheme://other/parameters/here">
And when the user clicks it, your app will be launched automatically (because it will probably be the only one that can handle my.special.scheme:// type of uris). The only downside to this is that if the user doesn't have the app installed, they'll get a nasty error. And I'm not sure there's any way to check.
Edit: To answer your question, you can use getIntent().getData() which returns a Uri object. You can then use Uri.* methods to extract the data you need. For example, let's say the user clicked on a link to http://twitter.com/status/1234:
Uri data = getIntent().getData();
String scheme = data.getScheme(); // "http"
String host = data.getHost(); // "twitter.com"
List<String> params = data.getPathSegments();
String first = params.get(0); // "status"
String second = params.get(1); // "1234"
You can do the above anywhere in your Activity, but you're probably going to want to do it in onCreate(). You can also use params.size() to get the number of path segments in the Uri. Look to javadoc or the android developer website for other Uri methods you can use to extract specific parts.
All above answers didn't work for me with CHROME as of 28 Jan 2014
my App launched properly from http://example.com/someresource/ links from apps like hangouts, gmail etc but not from within chrome browser.
to solve this, so that it launches properly from CHROME you have to set intent filter like this
<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:host="example.com"
android:pathPrefix="/someresource/"
android:scheme="http" />
<data
android:host="www.example.com"
android:pathPrefix="/someresource/"
android:scheme="http" />
</intent-filter>
note the pathPrefix element
your app will now appear inside activity picker whenever user requests http://example.com/someresource/ pattern from chrome browser by clicking a link from google search results or any other website
Please see my comment here: Make a link in the Android browser start up my app?
We strongly discourage people from using their own schemes, unless they are defining a new world-wide internet scheme.
In my case I had to set two categories for the <intent-filter> and then it worked:
<intent-filter>
<data android:scheme="my.special.scheme" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
For example, You have next things:
A link to open your app: http://example.com
The package name of your app: com.example.mypackage
Then you need to do next:
Add an intent filter to your Activity
(Can be any activity you want. For more info check the documentation).
<activity
android:name=".MainActivity">
<intent-filter android:label="#string/filter_title_view_app_from_web">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "http://example.com" -->
<data
android:host="example.com"
android:scheme="http" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Create a HTML file to test the link or use this methods.
Open your Activity directly (just open your Activity, without a choosing dialog).
Open this link with browser or your programm (by choosing dialog).
Use Mobile Chrome to test
That's it.
And its not necessary to publish app in market to test deep linking =)
Also, for more information, check documentation and useful presentation.
There should also be <category android:name="android.intent.category.BROWSABLE"/> added to the intent filter to make the activity recognized properly from the link.
The following link gives information on launching the app (if installed) directly from browser. Otherwise it directly opens up the app in play store so that user can seamlessly download.
https://developer.chrome.com/multidevice/android/intents
Please note if your icon is disappear from android launcher when you implement this feature, than you have to split intent-filter.
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<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="your-own-uri" />
</intent-filter>
</activity>
Yeah, Chrome searches instead of looking for scheme. If you want to launch your App through URI scheme, use this cool utility App on the Play store. It saved my day :)
https://play.google.com/store/apps/details?id=com.naosim.urlschemesender
Xamarin port of Felix's answer
In your MainActivity, add this (docs: Android.App.IntentFilterAttribute Class):
....
[IntentFilter(new[] {
Intent.ActionView },
Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
DataScheme = "my.special.scheme")
]
public class MainActivity : Activity
{
....
Xamarin will add following in the AndroidManifest.xml for you:
<activity
android:label="Something"
android:screenOrientation="portrait"
android:theme="#style/MyTheme"
android:name="blah.MainActivity">
<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="my.special.scheme" />
</intent-filter>
</activity>
And in order to get params (I tested in OnCreate of MainActivity):
var data = Intent.Data;
if (data != null)
{
var scheme = data.Scheme;
var host = data.Host;
var args = data.PathSegments;
if (args.Count > 0)
{
var first = args[0];
var second = args[1];
...
}
}
As far as I know, above can be added in any activity, not only MainActivity
Notes:
When user click on the link, Android OS relaunch your app (kill prev instance, if any, and run new one), means the OnCreate event of app's MainLauncher Activity will be fired again.
With this link: <a href="my.special.scheme://host/arg1/arg2">, in above last code snippet values will be:
scheme: my.special.scheme
host: host
args: ["arg1", "arg2"]
first: arg1
second: arg2
Update: if android creates new instance of your app, you should add android:launchMode="singleTask" too.
Felix's approach to handling deep links is the typical approach to handling deep links. I would also suggest checking out this library to handle the routing and parsing of your deep links:
https://github.com/airbnb/DeepLinkDispatch
You can use annotations to register your Activity for a particular deep link URI, and it will extract out the parameters for you without having to do the usual rigmarole of getting the path segments, matching it, etc. You could simply annotate and activity like this:
#DeepLink("somePath/{someParameter1}/{someParameter2}")
public class MainActivity extends Activity {
...
}
Hey I got the solution. I did not set the category as "Default". Also I was using the Main activity for the intent Data. Now i am using a different activity for the intent data. Thanks for the help. :)
You need to add a pseudo-hostname to the CALLBACK_URL 'app://' doesn't make sense as a URL and cannot be parsed.
example.php:
<?php
if(!isset($_GET['app_link'])){ ?>
<iframe src="example.php?app_link=YourApp://blabla" style="display:none;" scrolling="no" frameborder="0"></iframe>
<iframe src="example.php?full_link=http://play.google.com/xyz" style="display:none;" scrolling="no" frameborder="0"></iframe>
<?php
}
else { ?>
<script type="text/javascript">
self.window.location = '<?php echo $_GET['app_link'];?>';
window.parent.location.href = '<?php echo $_GET['full_link'];?>';
</script>
<?php
}
Look #JRuns answer in here. The idea is to create html with your custom scheme and upload it somewhere. Then if you click on your custom link on your html-file, you will be redirected to your app. I used this article for android. But dont forget to set full name Name = "MyApp.Mobile.Droid.MainActivity" attribute to your target activity.
As of 15/06/2019
what I did is include all four possibilities to open url.
i.e, with http / https and 2 with www in prefix and 2 without www
and by using this my app launches automatically now without asking me to choose a browser and other option.
<intent-filter android:autoVerify="true">
<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="example.in" />
<data android:scheme="https" android:host="www.example.in" />
<data android:scheme="http" android:host="example.in" />
<data android:scheme="http" android:host="www.example.in" />
</intent-filter>